From 88bbb4039aa274c7f41ebe3a18085b63427e5475 Mon Sep 17 00:00:00 2001 From: Mikko Rasa Date: Mon, 26 Sep 2016 01:28:16 +0300 Subject: [PATCH 1/1] Move most platform-specific code into overlay directories Unix socket addresses can now be constructed on Windows, but can't be actually used with sockets. --- Build | 8 ++ source/net/clientsocket.cpp | 31 ++------ source/net/constants.cpp | 6 +- source/net/datagramsocket.cpp | 55 ++----------- source/net/inet.cpp | 6 +- source/net/inet6.cpp | 7 +- source/net/resolve.cpp | 7 +- source/net/sockaddr.cpp | 1 + source/net/sockaddr_private.h | 12 +-- source/net/socket.cpp | 103 ++++-------------------- source/net/socket.h | 14 ++++ source/net/socket_private.h | 20 ++--- source/net/streamserversocket.cpp | 10 +-- source/net/streamsocket.cpp | 67 +++------------- source/net/unix.cpp | 59 -------------- source/net/unix/platform_api.h | 8 ++ source/net/unix/socket.cpp | 81 +++++++++++++++++++ source/net/unix/socket_platform.h | 12 +++ source/net/unix/unix.cpp | 53 +++++++++++++ source/net/windows/platform_api.h | 8 ++ source/net/windows/socket.cpp | 113 +++++++++++++++++++++++++++ source/net/windows/socket_platform.h | 13 +++ source/net/windows/unix.cpp | 29 +++++++ 23 files changed, 398 insertions(+), 325 deletions(-) create mode 100644 source/net/unix/platform_api.h create mode 100644 source/net/unix/socket.cpp create mode 100644 source/net/unix/socket_platform.h create mode 100644 source/net/unix/unix.cpp create mode 100644 source/net/windows/platform_api.h create mode 100644 source/net/windows/socket.cpp create mode 100644 source/net/windows/socket_platform.h create mode 100644 source/net/windows/unix.cpp diff --git a/Build b/Build index 7e4a693..404ddbf 100644 --- a/Build +++ b/Build @@ -14,6 +14,14 @@ package "mspnet" { source "source/net"; source "source/http"; + if_arch "windows" + { + overlay "windows"; + }; + if_arch "!windows" + { + overlay "unix"; + }; install true; install_map { diff --git a/source/net/clientsocket.cpp b/source/net/clientsocket.cpp index cbf18e5..04d0700 100644 --- a/source/net/clientsocket.cpp +++ b/source/net/clientsocket.cpp @@ -1,9 +1,4 @@ -#ifdef _WIN32 -#include -#else -#include -#include -#endif +#include "platform_api.h" #include #include "clientsocket.h" #include "socket_private.h" @@ -74,16 +69,7 @@ unsigned ClientSocket::do_write(const char *buf, unsigned size) if(size==0) return 0; - int ret = ::send(priv->handle, buf, size, 0); - if(ret<0) - { - if(errno==EAGAIN) - return 0; - else - throw system_error("send"); - } - - return ret; + return check_sys_error(::send(priv->handle, buf, size, 0), "send"); } unsigned ClientSocket::do_read(char *buf, unsigned size) @@ -95,19 +81,12 @@ unsigned ClientSocket::do_read(char *buf, unsigned size) if(size==0) return 0; - int ret = ::recv(priv->handle, buf, size, 0); - if(ret<0) - { - if(errno==EAGAIN) - return 0; - else - throw system_error("recv"); - } - else if(ret==0 && !eof_flag) + unsigned ret = check_sys_error(::recv(priv->handle, buf, size, 0), "recv"); + if(ret==0 && !eof_flag) { eof_flag = true; signal_end_of_file.emit(); - set_events(IO::P_NONE); + set_socket_events(S_NONE); } return ret; diff --git a/source/net/constants.cpp b/source/net/constants.cpp index c98945c..5088e51 100644 --- a/source/net/constants.cpp +++ b/source/net/constants.cpp @@ -1,9 +1,5 @@ #include -#ifdef _WIN32 -#include -#else -#include -#endif +#include "platform_api.h" #include "constants.h" using namespace std; diff --git a/source/net/datagramsocket.cpp b/source/net/datagramsocket.cpp index 0e405d6..fe01ef5 100644 --- a/source/net/datagramsocket.cpp +++ b/source/net/datagramsocket.cpp @@ -1,7 +1,4 @@ -#ifdef _WIN32 -#include -#endif -#include +#include "platform_api.h" #include #include #include @@ -15,25 +12,13 @@ namespace Net { DatagramSocket::DatagramSocket(Family f, int p): ClientSocket(f, SOCK_DGRAM, p) { -#ifdef _WIN32 - WSAEventSelect(priv->handle, *priv->event, FD_READ|FD_CLOSE); -#endif - set_events(IO::P_INPUT); + set_socket_events(S_INPUT); } bool DatagramSocket::connect(const SockAddr &addr) { SockAddr::SysAddr sa = addr.to_sys(); - - int err = ::connect(priv->handle, reinterpret_cast(&sa.addr), sa.size); - if(err==-1) - { -#ifdef _WIN32 - throw system_error("connect", WSAGetLastError()); -#else - throw system_error("connect"); -#endif - } + check_sys_connect_error(::connect(priv->handle, reinterpret_cast(&sa.addr), sa.size)); delete peer_addr; peer_addr = addr.copy(); @@ -54,23 +39,7 @@ unsigned DatagramSocket::sendto(const char *buf, unsigned size, const SockAddr & return 0; SockAddr::SysAddr sa = addr.to_sys(); - - int ret = ::sendto(priv->handle, buf, size, 0, reinterpret_cast(&sa.addr), sa.size); - if(ret<0) - { - if(errno==EAGAIN) - return 0; - else - { -#ifdef _WIN32 - throw system_error("sendto", WSAGetLastError()); -#else - throw system_error("sendto"); -#endif - } - } - - return ret; + return check_sys_error(::sendto(priv->handle, buf, size, 0, reinterpret_cast(&sa.addr), sa.size), "sendto"); } unsigned DatagramSocket::recvfrom(char *buf, unsigned size, SockAddr *&from_addr) @@ -79,21 +48,7 @@ unsigned DatagramSocket::recvfrom(char *buf, unsigned size, SockAddr *&from_addr return 0; SockAddr::SysAddr sa; - int ret = ::recvfrom(priv->handle, buf, size, 0, reinterpret_cast(&sa.addr), &sa.size); - if(ret<0) - { - if(errno==EAGAIN) - return 0; - else - { -#ifdef _WIN32 - throw system_error("recvfrom", WSAGetLastError()); -#else - throw system_error("recvfrom"); -#endif - } - } - + unsigned ret = check_sys_error(::recvfrom(priv->handle, buf, size, 0, reinterpret_cast(&sa.addr), &sa.size), "recvfrom"); from_addr = SockAddr::new_from_sys(sa); return ret; diff --git a/source/net/inet.cpp b/source/net/inet.cpp index f428492..8e75cd8 100644 --- a/source/net/inet.cpp +++ b/source/net/inet.cpp @@ -1,8 +1,4 @@ -#ifdef _WIN32 -#include -#else -#include -#endif +#include "platform_api.h" #include #include "inet.h" #include "sockaddr_private.h" diff --git a/source/net/inet6.cpp b/source/net/inet6.cpp index f33ed18..77d7570 100644 --- a/source/net/inet6.cpp +++ b/source/net/inet6.cpp @@ -1,9 +1,4 @@ -#ifdef _WIN32 -#include -#include -#else -#include -#endif +#include "platform_api.h" #include #include "inet6.h" #include "sockaddr_private.h" diff --git a/source/net/resolve.cpp b/source/net/resolve.cpp index 6de8838..10e8c65 100644 --- a/source/net/resolve.cpp +++ b/source/net/resolve.cpp @@ -1,9 +1,4 @@ -#ifdef _WIN32 -#define _WIN32_WINNT 0x0501 -#include -#else -#include -#endif +#include "platform_api.h" #include #include #include "sockaddr_private.h" diff --git a/source/net/sockaddr.cpp b/source/net/sockaddr.cpp index e9b1433..db436fe 100644 --- a/source/net/sockaddr.cpp +++ b/source/net/sockaddr.cpp @@ -1,4 +1,5 @@ #include +#include "platform_api.h" #include "inet.h" #include "inet6.h" #include "sockaddr_private.h" diff --git a/source/net/sockaddr_private.h b/source/net/sockaddr_private.h index 4aa9231..909ef92 100644 --- a/source/net/sockaddr_private.h +++ b/source/net/sockaddr_private.h @@ -1,12 +1,12 @@ #ifndef MSP_NET_SOCKADDR_PRIVATE_H_ #define MSP_NET_SOCKADDR_PRIVATE_H_ -#ifdef _WIN32 -#include -#else -#include +#ifndef MSP_NET_PLATFORM_API_H_ +#error platform_api.h must be included to use private headers #endif + #include "sockaddr.h" +#include "socket_platform.h" namespace Msp { namespace Net { @@ -14,11 +14,7 @@ namespace Net { struct SockAddr::SysAddr { struct sockaddr_storage addr; -#ifdef _WIN32 - int size; -#else socklen_t size; -#endif SysAddr(); }; diff --git a/source/net/socket.cpp b/source/net/socket.cpp index 031d077..e8e5eaf 100644 --- a/source/net/socket.cpp +++ b/source/net/socket.cpp @@ -1,46 +1,10 @@ -#ifdef _WIN32 -#include -#else -#include -#include -#include -#include -#endif -#include +#include "platform_api.h" #include #include -#include -#include -#include #include "sockaddr_private.h" #include "socket.h" #include "socket_private.h" -namespace { - -#ifdef _WIN32 -class WinSockHelper -{ -public: - WinSockHelper() - { - WSADATA wsa_data; - int err = WSAStartup(0x0002, &wsa_data); - if(err) - std::cerr<<"Failed to initialize WinSock: "<handle, reinterpret_cast(&sa.addr), &sa.size); local_addr = SockAddr::new_from_sys(sa); -#ifdef _WIN32 - *priv->event = CreateEvent(0, false, false, 0); -#else - *priv->event = priv->handle; -#endif + platform_init(); } Socket::Socket(Family af, int type, int proto): @@ -71,21 +31,12 @@ Socket::Socket(Family af, int type, int proto): priv->handle = socket(family_to_sys(af), type, proto); -#ifdef _WIN32 - *priv->event = CreateEvent(0, false, false, 0); -#else - *priv->event = priv->handle; -#endif + platform_init(); } Socket::~Socket() { -#ifdef _WIN32 - closesocket(priv->handle); - CloseHandle(*priv->event); -#else - ::close(priv->handle); -#endif + platform_cleanup(); delete local_addr; delete priv; @@ -97,13 +48,7 @@ void Socket::set_block(bool b) if(b) mode = (mode|IO::M_NONBLOCK); -#ifdef _WIN32 - u_long flag = !b; - ioctlsocket(priv->handle, FIONBIO, &flag); -#else - int flags = fcntl(priv->handle, F_GETFL); - fcntl(priv->handle, F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK)); -#endif + priv->set_block(b); } const IO::Handle &Socket::get_event_handle() @@ -130,36 +75,16 @@ const SockAddr &Socket::get_local_address() const return *local_addr; } -void Socket::set_timeout(const Time::TimeDelta &timeout) -{ -#ifndef _WIN32 - timeval tv = Time::rawtime_to_timeval(timeout.raw()); - priv->set_option(SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(timeval)); - priv->set_option(SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(timeval)); -#else - DWORD msecs = static_cast(timeout/Time::msec); - priv->set_option(SOL_SOCKET, SO_RCVTIMEO, &msecs, sizeof(DWORD)); - priv->set_option(SOL_SOCKET, SO_SNDTIMEO, &msecs, sizeof(DWORD)); -#endif -} - - -int Socket::Private::set_option(int level, int optname, const void *optval, socklen_t optlen) -{ -#ifdef _WIN32 - return setsockopt(handle, level, optname, reinterpret_cast(optval), optlen); -#else - return setsockopt(handle, level, optname, optval, optlen); -#endif -} - -int Socket::Private::get_option(int level, int optname, void *optval, socklen_t *optlen) +void Socket::set_socket_events(unsigned e) { -#ifdef _WIN32 - return getsockopt(handle, level, optname, reinterpret_cast(optval), optlen); -#else - return getsockopt(handle, level, optname, optval, optlen); -#endif + IO::PollEvent pe = static_cast(e&4095); + if(e&S_CONNECT) + pe = pe|IO::P_OUTPUT; + if(e&S_ACCEPT) + pe = pe|IO::P_INPUT; + + set_platform_events(e); + set_events(pe); } } // namespace Net diff --git a/source/net/socket.h b/source/net/socket.h index c830930..1f60f9b 100644 --- a/source/net/socket.h +++ b/source/net/socket.h @@ -20,6 +20,14 @@ public: class Socket: public IO::EventObject { protected: + enum SocketEvent + { + S_NONE = IO::P_NONE, + S_INPUT = IO::P_INPUT, + S_CONNECT = 4096, + S_ACCEPT = 8192 + }; + struct Private; Private *priv; @@ -27,6 +35,9 @@ protected: Socket(const Private &); Socket(Family, int, int); +private: + void platform_init(); + void platform_cleanup(); public: ~Socket(); @@ -40,6 +51,9 @@ public: const SockAddr &get_local_address() const; void set_timeout(const Time::TimeDelta &); +protected: + void set_socket_events(unsigned); + void set_platform_events(unsigned); }; } // namespace Net diff --git a/source/net/socket_private.h b/source/net/socket_private.h index 995ead0..742877b 100644 --- a/source/net/socket_private.h +++ b/source/net/socket_private.h @@ -1,32 +1,34 @@ #ifndef MSP_NET_SOCKET_PRIVATE_H_ #define MSP_NET_SOCKET_PRIVATE_H_ +#ifndef MSP_NET_PLATFORM_API_H_ +#error platform_api.h must be included to use private headers +#endif + #include +#include "sockaddr.h" #include "socket.h" +#include "socket_platform.h" namespace Msp { namespace Net { -#ifdef _WIN32 -typedef int socklen_t; -#endif - struct Socket::Private { -#ifdef _WIN32 - SOCKET handle; -#else - int handle; -#endif + SocketHandle handle; /* On POSIX platforms this is the same as the handle. This might seem strange but it allows the same syntax on both POSIX and Windows. */ IO::Handle event; + void set_block(bool); int set_option(int, int, const void *, socklen_t); int get_option(int, int, void *, socklen_t *); }; +unsigned check_sys_error(int, const char *); +bool check_sys_connect_error(int); + } // namespace Net } // namespace Msp diff --git a/source/net/streamserversocket.cpp b/source/net/streamserversocket.cpp index e408dce..9900e5d 100644 --- a/source/net/streamserversocket.cpp +++ b/source/net/streamserversocket.cpp @@ -1,7 +1,4 @@ -#ifdef _WIN32 -#include -#endif -#include +#include "platform_api.h" #include #include #include @@ -29,10 +26,7 @@ void StreamServerSocket::listen(const SockAddr &addr, unsigned backlog) if(err==-1) throw system_error("listen"); -#ifdef _WIN32 - WSAEventSelect(priv->handle, *priv->event, FD_ACCEPT); -#endif - set_events(IO::P_INPUT); + set_socket_events(S_ACCEPT); listening = true; } diff --git a/source/net/streamsocket.cpp b/source/net/streamsocket.cpp index da5069c..11887d3 100644 --- a/source/net/streamsocket.cpp +++ b/source/net/streamsocket.cpp @@ -1,9 +1,4 @@ -#ifdef _WIN32 -#include -#else -#include -#endif -#include +#include "platform_api.h" #include #include #include @@ -18,10 +13,7 @@ namespace Net { StreamSocket::StreamSocket(const Private &p, const SockAddr &paddr): ClientSocket(p, paddr) { -#ifdef _WIN32 - WSAEventSelect(priv->handle, *priv->event, FD_READ|FD_CLOSE); -#endif - set_events(IO::P_INPUT); + set_socket_events(S_INPUT); } StreamSocket::StreamSocket(Family af, int proto): @@ -34,33 +26,13 @@ bool StreamSocket::connect(const SockAddr &addr) throw bad_socket_state("already connected"); SockAddr::SysAddr sa = addr.to_sys(); - - int err = ::connect(priv->handle, reinterpret_cast(&sa.addr), sa.size); -#ifdef _WIN32 - if(err==SOCKET_ERROR) + int err = ::connect(priv->handle, reinterpret_cast(&sa.addr), sa.size); + bool finished = check_sys_connect_error(err); + if(!finished) { - int err_code = WSAGetLastError(); - if(err_code==WSAEWOULDBLOCK) - { - connecting = true; - WSAEventSelect(priv->handle, *priv->event, FD_CONNECT); - set_events(IO::P_OUTPUT); - } - else - throw system_error("connect", err_code); - } -#else - if(err==-1) - { - if(errno==EINPROGRESS) - { - connecting = true; - set_events(IO::P_OUTPUT); - } - else - throw system_error("connect"); + connecting = true; + set_socket_events(S_CONNECT); } -#endif delete peer_addr; peer_addr = addr.copy(); @@ -70,13 +42,10 @@ bool StreamSocket::connect(const SockAddr &addr) getsockname(priv->handle, reinterpret_cast(&lsa.addr), &lsa.size); local_addr = SockAddr::new_from_sys(lsa); - if(err==0) + if(finished) { connected = true; -#ifdef _WIN32 - WSAEventSelect(priv->handle, *priv->event, FD_READ|FD_CLOSE); -#endif - set_events(IO::P_INPUT); + set_socket_events(S_INPUT); signal_connect_finished.emit(0); } @@ -99,18 +68,11 @@ bool StreamSocket::poll_connect(const Time::TimeDelta &timeout) if(err!=0) { - set_events(IO::P_NONE); -#ifdef _WIN32 - throw system_error("connect", WSAGetLastError()); -#else - throw system_error("connect"); -#endif + set_socket_events(S_NONE); + throw system_error("connect", err); } -#ifdef _WIN32 - WSAEventSelect(priv->handle, *priv->event, FD_READ|FD_CLOSE); -#endif - set_events(IO::P_INPUT); + set_socket_events(S_INPUT); connected = true; } @@ -142,10 +104,7 @@ void StreamSocket::on_event(IO::PollEvent ev) peer_addr = 0; } -#ifdef _WIN32 - WSAEventSelect(priv->handle, *priv->event, FD_READ|FD_CLOSE); -#endif - set_events((err==0) ? IO::P_INPUT : IO::P_NONE); + set_socket_events((err==0) ? S_INPUT : S_NONE); } } diff --git a/source/net/unix.cpp b/source/net/unix.cpp index 9d8cf27..fe00020 100644 --- a/source/net/unix.cpp +++ b/source/net/unix.cpp @@ -1,8 +1,3 @@ -#include -#ifndef _WIN32 -#include -#endif -#include "sockaddr_private.h" #include "unix.h" using namespace std; @@ -13,60 +8,6 @@ namespace Net { UnixAddr::UnixAddr(): abstract(false) { -#ifdef _WIN32 - throw logic_error("no unix sockets on windows"); -#endif -} - -UnixAddr::UnixAddr(const SysAddr &sa): - abstract(false) -{ -#ifdef _WIN32 - (void)sa; - throw logic_error("no unix sockets on windows"); -#else - const sockaddr_un &sau = reinterpret_cast(sa.addr); - if(static_cast(sa.size)>sizeof(sa_family_t)) - { - abstract = (sau.sun_path[0]==0); - path.assign(sau.sun_path+abstract, sa.size-sizeof(sa_family_t)-abstract); - } -#endif -} - -UnixAddr::UnixAddr(const string &p, bool a): - path(p), - abstract(a) -{ -#ifdef _WIN32 - throw logic_error("no unix sockets on windows"); -#else - if(sizeof(sa_family_t)+path.size()+1>sizeof(sockaddr_storage)) - throw invalid_argument("UnixAddr"); -#endif -} - -SockAddr::SysAddr UnixAddr::to_sys() const -{ - SysAddr sa; -#ifndef _WIN32 - sa.size = sizeof(sa_family_t); - if(!path.empty()) - sa.size += path.size()+1; - - sockaddr_un &sau = reinterpret_cast(sa.addr); - sau.sun_family = AF_UNIX; - if(!path.empty()) - { - if(abstract) - sau.sun_path[0] = 0; - std::copy(path.begin(), path.end(), sau.sun_path+abstract); - if(!abstract) - sau.sun_path[path.size()] = 0; - } -#endif - - return sa; } string UnixAddr::str() const diff --git a/source/net/unix/platform_api.h b/source/net/unix/platform_api.h new file mode 100644 index 0000000..016545f --- /dev/null +++ b/source/net/unix/platform_api.h @@ -0,0 +1,8 @@ +#ifndef MSP_NET_PLATFORM_API_H_ +#define MSP_NET_PLATFORM_API_H_ + +#include +#include +#include + +#endif diff --git a/source/net/unix/socket.cpp b/source/net/unix/socket.cpp new file mode 100644 index 0000000..02ef7c3 --- /dev/null +++ b/source/net/unix/socket.cpp @@ -0,0 +1,81 @@ +#include +#include +#include +#include "platform_api.h" +#include +#include +#include +#include "sockaddr_private.h" +#include "socket.h" +#include "socket_private.h" + +namespace Msp { +namespace Net { + +void Socket::platform_init() +{ + *priv->event = priv->handle; +} + +void Socket::platform_cleanup() +{ + close(priv->handle); +} + +void Socket::set_timeout(const Time::TimeDelta &timeout) +{ + timeval tv = Time::rawtime_to_timeval(timeout.raw()); + priv->set_option(SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(timeval)); + priv->set_option(SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(timeval)); +} + +void Socket::set_platform_events(unsigned) +{ +} + + +void Socket::Private::set_block(bool b) +{ + int flags = fcntl(handle, F_GETFL); + fcntl(handle, F_SETFL, (flags&O_NONBLOCK)|(b?0:O_NONBLOCK)); +} + +int Socket::Private::set_option(int level, int optname, const void *optval, socklen_t optlen) +{ + return setsockopt(handle, level, optname, optval, optlen); +} + +int Socket::Private::get_option(int level, int optname, void *optval, socklen_t *optlen) +{ + return getsockopt(handle, level, optname, optval, optlen); +} + + +unsigned check_sys_error(int ret, const char *func) +{ + if(ret<0) + { + if(errno==EAGAIN) + return 0; + else + throw system_error(func); + } + + return ret; +} + +bool check_sys_connect_error(int ret) +{ + if(ret<0) + { + if(errno==EINPROGRESS) + return false; + else + throw system_error("connect"); + } + + return true; +} + +} // namespace Net +} // namespace Msp diff --git a/source/net/unix/socket_platform.h b/source/net/unix/socket_platform.h new file mode 100644 index 0000000..73c2fe0 --- /dev/null +++ b/source/net/unix/socket_platform.h @@ -0,0 +1,12 @@ +#ifndef MSP_NET_SOCKET_PLATFORM_H_ +#define MSP_NET_SOCKET_PLATFORM_H_ + +namespace Msp { +namespace Net { + +typedef int SocketHandle; + +} // namespace Net +} // namespace Msp + +#endif diff --git a/source/net/unix/unix.cpp b/source/net/unix/unix.cpp new file mode 100644 index 0000000..6bb3436 --- /dev/null +++ b/source/net/unix/unix.cpp @@ -0,0 +1,53 @@ +#include +#include +#include "platform_api.h" +#include "sockaddr_private.h" +#include "unix.h" + +using namespace std; + +namespace Msp { +namespace Net { + +UnixAddr::UnixAddr(const SysAddr &sa): + abstract(false) +{ + const sockaddr_un &sau = reinterpret_cast(sa.addr); + if(static_cast(sa.size)>sizeof(sa_family_t)) + { + abstract = (sau.sun_path[0]==0); + path.assign(sau.sun_path+abstract, sa.size-sizeof(sa_family_t)-abstract); + } +} + +UnixAddr::UnixAddr(const string &p, bool a): + path(p), + abstract(a) +{ + if(sizeof(sa_family_t)+path.size()+1>sizeof(sockaddr_storage)) + throw invalid_argument("UnixAddr"); +} + +SockAddr::SysAddr UnixAddr::to_sys() const +{ + SysAddr sa; + sa.size = sizeof(sa_family_t); + if(!path.empty()) + sa.size += path.size()+1; + + sockaddr_un &sau = reinterpret_cast(sa.addr); + sau.sun_family = AF_UNIX; + if(!path.empty()) + { + if(abstract) + sau.sun_path[0] = 0; + std::copy(path.begin(), path.end(), sau.sun_path+abstract); + if(!abstract) + sau.sun_path[path.size()] = 0; + } + + return sa; +} + +} // namespace Net +} // namespace Msp diff --git a/source/net/windows/platform_api.h b/source/net/windows/platform_api.h new file mode 100644 index 0000000..b2ba90c --- /dev/null +++ b/source/net/windows/platform_api.h @@ -0,0 +1,8 @@ +#ifndef MSP_NET_PLATFORM_API_H_ +#define MSP_NET_PLATFORM_API_H_ + +#include +#include +#include + +#endif diff --git a/source/net/windows/socket.cpp b/source/net/windows/socket.cpp new file mode 100644 index 0000000..f4fab44 --- /dev/null +++ b/source/net/windows/socket.cpp @@ -0,0 +1,113 @@ +#include +#include "platform_api.h" +#include +#include +#include "sockaddr_private.h" +#include "socket.h" +#include "socket_private.h" + +namespace { + +class WinSockHelper +{ +public: + WinSockHelper() + { + WSADATA wsa_data; + int err = WSAStartup(0x0002, &wsa_data); + if(err) + std::cerr<<"Failed to initialize WinSock: "<event = CreateEvent(0, false, false, 0); +} + +void Socket::platform_cleanup() +{ + closesocket(priv->handle); + CloseHandle(*priv->event); +} + +void Socket::set_timeout(const Time::TimeDelta &timeout) +{ + DWORD msecs = static_cast(timeout/Time::msec); + priv->set_option(SOL_SOCKET, SO_RCVTIMEO, &msecs, sizeof(DWORD)); + priv->set_option(SOL_SOCKET, SO_SNDTIMEO, &msecs, sizeof(DWORD)); +} + +void Socket::set_platform_events(unsigned e) +{ + long ws_events = 0; + if(e&S_INPUT) + ws_events |= FD_READ|FD_CLOSE; + if(e&S_CONNECT) + ws_events |= FD_CONNECT; + if(e&S_ACCEPT) + ws_events |= FD_ACCEPT; + WSAEventSelect(priv->handle, *priv->event, ws_events); +} + + +void Socket::Private::set_block(bool b) +{ + u_long flag = !b; + ioctlsocket(handle, FIONBIO, &flag); +} + +int Socket::Private::set_option(int level, int optname, const void *optval, socklen_t optlen) +{ + return setsockopt(handle, level, optname, reinterpret_cast(optval), optlen); +} + +int Socket::Private::get_option(int level, int optname, void *optval, socklen_t *optlen) +{ + return getsockopt(handle, level, optname, reinterpret_cast(optval), optlen); +} + + +unsigned check_sys_error(int ret, const char *func) +{ + if(ret<0) + { + int err_code = WSAGetLastError(); + if(err_code==WSAEWOULDBLOCK) + return 0; + else + throw system_error(func, err_code); + } + + return ret; +} + +bool check_sys_connect_error(int ret) +{ + if(ret==SOCKET_ERROR) + { + int err_code = WSAGetLastError(); + if(err_code==WSAEWOULDBLOCK) + return false; + else + throw system_error("connect", err_code); + } + + return true; +} + +} // namespace Net +} // namespace Msp diff --git a/source/net/windows/socket_platform.h b/source/net/windows/socket_platform.h new file mode 100644 index 0000000..5168579 --- /dev/null +++ b/source/net/windows/socket_platform.h @@ -0,0 +1,13 @@ +#ifndef MSP_NET_SOCKET_PLATFORM_H_ +#define MSP_NET_SOCKET_PLATFORM_H_ + +namespace Msp { +namespace Net { + +typedef int socklen_t; +typedef SOCKET SocketHandle; + +} // namespace Net +} // namespace Msp + +#endif diff --git a/source/net/windows/unix.cpp b/source/net/windows/unix.cpp new file mode 100644 index 0000000..2aa8857 --- /dev/null +++ b/source/net/windows/unix.cpp @@ -0,0 +1,29 @@ +#include +#include "platform_api.h" +#include "sockaddr_private.h" +#include "unix.h" + +using namespace std; + +namespace Msp { +namespace Net { + +UnixAddr::UnixAddr(const SysAddr &): + abstract(false) +{ + throw logic_error("AF_UNIX not supported"); +} + +UnixAddr::UnixAddr(const string &p, bool a): + path(p), + abstract(a) +{ +} + +SockAddr::SysAddr UnixAddr::to_sys() const +{ + throw logic_error("AF_UNIX not supported"); +} + +} // namespace Net +} // namespace Msp -- 2.43.0