X-Git-Url: http://git.tdb.fi/?a=blobdiff_plain;f=source%2Fnet%2Fsocket.cpp;h=2a1a71c0a4b3aa404b616f09a7be6e1799660c27;hb=HEAD;hp=2378207048c9a9a91395eca79227ea6088c5a56b;hpb=3840d5d193327059b84406ee6b0ba263f5ef2401;p=libs%2Fnet.git diff --git a/source/net/socket.cpp b/source/net/socket.cpp index 2378207..2a1a71c 100644 --- a/source/net/socket.cpp +++ b/source/net/socket.cpp @@ -1,103 +1,66 @@ -#ifndef WIN32 -#include -#include -#include -#include -#endif -#include +#include "platform_api.h" +#include "socket.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: "<()) { + mode = IO::M_RDWR; + priv->handle = p.handle; SockAddr::SysAddr sa; getsockname(priv->handle, reinterpret_cast(&sa.addr), &sa.size); - local_addr = SockAddr::new_from_sys(sa); + local_addr.reset(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): - priv(new Private), - local_addr(0) + priv(make_unique()) { - priv->handle = socket(family_to_sys(af), type, proto); + mode = IO::M_RDWR; -#ifdef WIN32 - *priv->event = CreateEvent(0, false, false, 0); -#else - *priv->event = priv->handle; +#ifdef __linux__ + type |= SOCK_CLOEXEC; +#endif + priv->handle = socket(family_to_sys(af), type, proto); +#ifndef __linux__ + set_inherit(false); #endif + + platform_init(); } Socket::~Socket() { -#ifdef WIN32 - closesocket(priv->handle); - CloseHandle(*priv->event); -#else - ::close(priv->handle); -#endif - - delete local_addr; - delete priv; + platform_cleanup(); } void Socket::set_block(bool b) { - mode = (mode&~IO::M_NONBLOCK); - 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 + IO::adjust_mode(mode, IO::M_NONBLOCK, !b); + priv->set_block(b); +} + +void Socket::set_inherit(bool i) +{ + IO::adjust_mode(mode, IO::M_INHERIT, i); + priv->set_inherit(i); +} + +const IO::Handle &Socket::get_handle(IO::Mode) +{ + // TODO could this be implemented somehow? + throw unsupported("Socket::get_handle"); } const IO::Handle &Socket::get_event_handle() @@ -105,7 +68,6 @@ const IO::Handle &Socket::get_event_handle() return priv->event; } - void Socket::bind(const SockAddr &addr) { SockAddr::SysAddr sa = addr.to_sys(); @@ -114,47 +76,26 @@ void Socket::bind(const SockAddr &addr) if(err==-1) throw system_error("bind"); - delete local_addr; - local_addr = addr.copy(); + local_addr.reset(addr.copy()); } const SockAddr &Socket::get_local_address() const { - if(local_addr==0) + if(!local_addr) throw bad_socket_state("not bound"); return *local_addr; } -void Socket::set_timeout(const Time::TimeDelta &timeout) +void Socket::set_socket_events(unsigned e) { -#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) -{ -#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