diff --git a/src/net/SocketDescriptor.cxx b/src/net/SocketDescriptor.cxx index a63b04921..350931ea7 100644 --- a/src/net/SocketDescriptor.cxx +++ b/src/net/SocketDescriptor.cxx @@ -8,7 +8,6 @@ #include "IPv6Address.hxx" #ifdef _WIN32 -#include #include #else #include diff --git a/src/net/SocketDescriptor.hxx b/src/net/SocketDescriptor.hxx index 35bafbb97..f333cd1ed 100644 --- a/src/net/SocketDescriptor.hxx +++ b/src/net/SocketDescriptor.hxx @@ -5,9 +5,17 @@ #define SOCKET_DESCRIPTOR_HXX #include "Features.hxx" + +#ifndef _WIN32 #include "io/FileDescriptor.hxx" +#endif #include +#include + +#ifdef _WIN32 +#include // for SOCKET, INVALID_SOCKET +#endif class SocketAddress; class StaticSocketAddress; @@ -15,24 +23,44 @@ class IPv4Address; class IPv6Address; /** - * An OO wrapper for a UNIX socket descriptor. + * An OO wrapper for a Berkeley or WinSock socket descriptor. */ -class SocketDescriptor : protected FileDescriptor { +class SocketDescriptor +#ifndef _WIN32 +/* Berkeley sockets are represented as file descriptors */ + : protected FileDescriptor +#endif +{ protected: +#ifdef _WIN32 + /* WinSock sockets are not file descriptors, they are a + special type */ + SOCKET fd; +#else // !_WIN32 explicit constexpr SocketDescriptor(FileDescriptor _fd) noexcept :FileDescriptor(_fd) {} +#endif // !_WIN32 public: SocketDescriptor() = default; +#ifdef _WIN32 + explicit constexpr SocketDescriptor(SOCKET _fd) noexcept + :fd(_fd) {} +#else // !_WIN32 explicit constexpr SocketDescriptor(int _fd) noexcept :FileDescriptor(_fd) {} +#endif // !_WIN32 constexpr bool operator==(SocketDescriptor other) const noexcept { return fd == other.fd; } -#ifndef _WIN32 +#ifdef _WIN32 + constexpr bool IsDefined() const noexcept { + return fd != INVALID_SOCKET; + } +#else // !_WIN32 /** * Convert a #FileDescriptor to a #SocketDescriptor. This is only * possible on operating systems where socket descriptors are the @@ -52,13 +80,11 @@ public: constexpr const FileDescriptor &ToFileDescriptor() const noexcept { return *this; } -#endif using FileDescriptor::IsDefined; -#ifndef _WIN32 using FileDescriptor::IsValid; using FileDescriptor::IsSocket; -#endif +#endif // !_WIN32 /** * Determine the socket type, i.e. SOCK_STREAM, SOCK_DGRAM or @@ -73,25 +99,48 @@ public: [[gnu::pure]] bool IsStream() const noexcept; + static constexpr SocketDescriptor Undefined() noexcept { +#ifdef _WIN32 + return SocketDescriptor{INVALID_SOCKET}; +#else // !_WIN32 + return SocketDescriptor(FileDescriptor::Undefined()); +#endif // !_WIN32 + } + +#ifndef _WIN32 using FileDescriptor::Get; using FileDescriptor::Set; using FileDescriptor::Steal; using FileDescriptor::SetUndefined; - static constexpr SocketDescriptor Undefined() noexcept { - return SocketDescriptor(FileDescriptor::Undefined()); - } - using FileDescriptor::EnableCloseOnExec; using FileDescriptor::DisableCloseOnExec; -#ifndef _WIN32 using FileDescriptor::SetNonBlocking; using FileDescriptor::SetBlocking; using FileDescriptor::Duplicate; using FileDescriptor::CheckDuplicate; using FileDescriptor::Close; #else + constexpr SOCKET Get() const noexcept { + return fd; + } + + constexpr void Set(SOCKET _fd) noexcept { + fd = _fd; + } + + constexpr void SetUndefined() noexcept { + fd = INVALID_SOCKET; + } + + constexpr SOCKET Steal() noexcept { + return std::exchange(fd, INVALID_SOCKET); + } + + void EnableCloseOnExec() const noexcept {} + void DisableCloseOnExec() const noexcept {} + bool SetNonBlocking() const noexcept; /** diff --git a/src/net/UniqueSocketDescriptor.hxx b/src/net/UniqueSocketDescriptor.hxx index 6b0d38b03..a6809aef5 100644 --- a/src/net/UniqueSocketDescriptor.hxx +++ b/src/net/UniqueSocketDescriptor.hxx @@ -20,13 +20,20 @@ public: explicit UniqueSocketDescriptor(SocketDescriptor _fd) noexcept :SocketDescriptor(_fd) {} +#ifndef _WIN32 explicit UniqueSocketDescriptor(FileDescriptor _fd) noexcept :SocketDescriptor(_fd) {} +#endif // !_WIN32 explicit UniqueSocketDescriptor(int _fd) noexcept :SocketDescriptor(_fd) {} +#ifdef _WIN32 + UniqueSocketDescriptor(UniqueSocketDescriptor &&other) noexcept + :SocketDescriptor(std::exchange(other.fd, INVALID_SOCKET)) {} +#else // !_WIN32 UniqueSocketDescriptor(UniqueSocketDescriptor &&other) noexcept :SocketDescriptor(std::exchange(other.fd, -1)) {} +#endif // !_WIN32 ~UniqueSocketDescriptor() noexcept { if (IsDefined())