]> git.tdb.fi Git - libs/net.git/blob - source/net/windows/socket.cpp
Add a dynamic receiver class for more flexible packet handling
[libs/net.git] / source / net / windows / socket.cpp
1 #include "platform_api.h"
2 #include "socket.h"
3 #include <iostream>
4 #include <msp/core/systemerror.h>
5 #include <msp/io/handle_private.h>
6 #include "sockaddr_private.h"
7 #include "socket_private.h"
8
9 using namespace std;
10
11 namespace {
12
13 class WinSockHelper
14 {
15 public:
16         WinSockHelper()
17         {
18                 WSADATA wsa_data;
19                 int err = WSAStartup(0x0002, &wsa_data);
20                 if(err)
21                         std::cerr<<"Failed to initialize WinSock: "<<err<<'\n';
22         }
23
24         ~WinSockHelper()
25         {
26                 WSACleanup();
27         }
28 };
29
30 unique_ptr<WinSockHelper> wsh;
31
32 }
33
34
35 namespace Msp {
36 namespace Net {
37
38 void Socket::platform_init()
39 {
40         if(!wsh)
41                 wsh = make_unique<WinSockHelper>();
42         *priv->event = CreateEvent(0, false, false, 0);
43 }
44
45 void Socket::platform_cleanup()
46 {
47         closesocket(priv->handle);
48         CloseHandle(*priv->event);
49 }
50
51 void Socket::set_timeout(const Time::TimeDelta &timeout)
52 {
53         DWORD msecs = static_cast<DWORD>(timeout/Time::msec);
54         priv->set_option(SOL_SOCKET, SO_RCVTIMEO, &msecs, sizeof(DWORD));
55         priv->set_option(SOL_SOCKET, SO_SNDTIMEO, &msecs, sizeof(DWORD));
56 }
57
58 void Socket::set_platform_events(unsigned e)
59 {
60         long ws_events = 0;
61         if(e&S_INPUT)
62                 ws_events |= FD_READ|FD_CLOSE;
63         if(e&S_CONNECT)
64                 ws_events |= FD_CONNECT;
65         if(e&S_ACCEPT)
66                 ws_events |= FD_ACCEPT;
67         WSAEventSelect(priv->handle, *priv->event, ws_events);
68 }
69
70
71 void Socket::Private::set_block(bool b)
72 {
73         u_long flag = !b;
74         ioctlsocket(handle, FIONBIO, &flag);
75 }
76
77 void Socket::Private::set_inherit(bool)
78 {
79 }
80
81 int Socket::Private::set_option(int level, int optname, const void *optval, socklen_t optlen)
82 {
83         return setsockopt(handle, level, optname, reinterpret_cast<const char *>(optval), optlen);
84 }
85
86 int Socket::Private::get_option(int level, int optname, void *optval, socklen_t *optlen)
87 {
88         return getsockopt(handle, level, optname, reinterpret_cast<char *>(optval), optlen);
89 }
90
91
92 size_t check_sys_error(make_signed<size_t>::type ret, const char *func)
93 {
94         if(ret<0)
95         {
96                 int err_code = WSAGetLastError();
97                 if(err_code==WSAEWOULDBLOCK)
98                         return 0;
99                 else
100                         throw system_error(func, err_code);
101         }
102
103         return ret;
104 }
105
106 bool check_sys_connect_error(int ret)
107 {
108         if(ret==SOCKET_ERROR)
109         {
110                 int err_code = WSAGetLastError();
111                 if(err_code==WSAEWOULDBLOCK)
112                         return false;
113                 else
114                         throw system_error("connect", err_code);
115         }
116
117         return true;
118 }
119
120 } // namespace Net
121 } // namespace Msp