summaryrefslogtreecommitdiffstats
path: root/net/Socket.cpp
diff options
context:
space:
mode:
authorMichael Meeks <michael.meeks@collabora.com>2018-01-09 14:02:02 +0000
committerMichael Meeks <michael.meeks@collabora.com>2018-01-09 22:03:17 +0000
commita1ee97c222d60bbb81c597327e2b5ff89e903970 (patch)
tree1c7bce7af2a9b81ca5c7a5b405505d3c7a82233e /net/Socket.cpp
parentloleaflet: updated UI pot (diff)
downloadonline-a1ee97c222d60bbb81c597327e2b5ff89e903970.tar.gz
online-a1ee97c222d60bbb81c597327e2b5ff89e903970.zip
Add IPv6 support, and configuration option.
Default to listening on both IPv44 and IPv6 for public interfaces. Change-Id: Ib04e3bf65e7dcf2a798d381297b15ee9c56e9259
Diffstat (limited to 'net/Socket.cpp')
-rw-r--r--net/Socket.cpp56
1 files changed, 56 insertions, 0 deletions
diff --git a/net/Socket.cpp b/net/Socket.cpp
index eb2f19fb80..d0a791ec9c 100644
--- a/net/Socket.cpp
+++ b/net/Socket.cpp
@@ -28,6 +28,12 @@ int SocketPoll::DefaultPollTimeoutMs = 5000;
std::atomic<bool> SocketPoll::InhibitThreadChecks(false);
std::atomic<bool> Socket::InhibitThreadChecks(false);
+int Socket::createSocket(Socket::Type type)
+{
+ int domain = type == Type::IPv4 ? AF_INET : AF_INET6;
+ return socket(domain, SOCK_STREAM | SOCK_NONBLOCK, 0);
+}
+
// help with initialization order
namespace {
std::vector<int> &getWakeupsArray()
@@ -183,6 +189,56 @@ void SocketPoll::dumpState(std::ostream& os)
i->dumpState(os);
}
+/// Returns true on success only.
+bool ServerSocket::bind(Type type, int port)
+{
+ // Enable address reuse to avoid stalling after
+ // recycling, when previous socket is TIME_WAIT.
+ //TODO: Might be worth refactoring out.
+ const int reuseAddress = 1;
+ constexpr unsigned int len = sizeof(reuseAddress);
+ ::setsockopt(getFD(), SOL_SOCKET, SO_REUSEADDR, &reuseAddress, len);
+
+ int rc;
+
+ if (_type == Socket::Type::IPv4)
+ {
+ struct sockaddr_in addrv4;
+ std::memset(&addrv4, 0, sizeof(addrv4));
+ addrv4.sin_family = AF_INET;
+ addrv4.sin_port = htons(port);
+ if (type == Type::Public)
+ addrv4.sin_addr.s_addr = type == htonl(INADDR_ANY);
+ else
+ addrv4.sin_addr.s_addr = type == htonl(INADDR_LOOPBACK);
+
+ rc = ::bind(getFD(), (const sockaddr *)&addrv4, sizeof(addrv4));
+ }
+ else
+ {
+ struct sockaddr_in6 addrv6;
+ std::memset(&addrv6, 0, sizeof(addrv6));
+ addrv6.sin6_family = AF_INET6;
+ addrv6.sin6_port = htons(port);
+ if (type == Type::Public)
+ addrv6.sin6_addr = in6addr_any;
+ else
+ addrv6.sin6_addr = in6addr_loopback;
+
+ int ipv6only = _type == Socket::Type::All ? 0 : 1;
+ if (::setsockopt(getFD(), IPPROTO_IPV6, IPV6_V6ONLY, (char*)&ipv6only, sizeof(ipv6only)) == -1)
+ LOG_SYS("Failed set ipv6 socket to %d" << ipv6only);
+
+ rc = ::bind(getFD(), (const sockaddr *)&addrv6, sizeof(addrv6));
+ }
+
+ if (rc)
+ LOG_SYS("Failed to bind to: " << (_type == Socket::Type::IPv4 ? "IPv4" : "IPv6") << " port: " << port);
+
+ return rc == 0;
+}
+
+
namespace HttpHelper
{
void sendUncompressedFileContent(const std::shared_ptr<StreamSocket>& socket,