1 /*
2  * synergy -- mouse and keyboard sharing utility
3  * Copyright (C) 2012-2016 Symless Ltd.
4  * Copyright (C) 2002 Chris Schoeneman
5  *
6  * This package is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU General Public License
8  * found in the file LICENSE that should have accompanied this file.
9  *
10  * This package is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18 
19 #include "arch/win32/ArchNetworkWinsock.h"
20 #include "arch/win32/ArchMultithreadWindows.h"
21 #include "arch/win32/XArchWindows.h"
22 #include "arch/IArchMultithread.h"
23 #include "arch/Arch.h"
24 
25 #include <malloc.h>
26 
27 static const int s_family[] = {
28     PF_UNSPEC,
29     PF_INET,
30     PF_INET6,
31 };
32 static const int s_type[] = {
33     SOCK_DGRAM,
34     SOCK_STREAM
35 };
36 
37 static SOCKET (PASCAL FAR *accept_winsock)(SOCKET s, struct sockaddr FAR *addr, int FAR *addrlen);
38 static int (PASCAL FAR *bind_winsock)(SOCKET s, const struct sockaddr FAR *addr, int namelen);
39 static int (PASCAL FAR *close_winsock)(SOCKET s);
40 static int (PASCAL FAR *connect_winsock)(SOCKET s, const struct sockaddr FAR *name, int namelen);
41 static int (PASCAL FAR *gethostname_winsock)(char FAR * name, int namelen);
42 static int (PASCAL FAR *getsockerror_winsock)(void);
43 static int (PASCAL FAR *getsockopt_winsock)(SOCKET s, int level, int optname, void FAR * optval, int FAR *optlen);
44 static u_short (PASCAL FAR *htons_winsock)(u_short v);
45 static char FAR * (PASCAL FAR *inet_ntoa_winsock)(struct in_addr in);
46 static unsigned long (PASCAL FAR *inet_addr_winsock)(const char FAR * cp);
47 static int (PASCAL FAR *ioctl_winsock)(SOCKET s, int cmd, void FAR * data);
48 static int (PASCAL FAR *listen_winsock)(SOCKET s, int backlog);
49 static u_short (PASCAL FAR *ntohs_winsock)(u_short v);
50 static int (PASCAL FAR *recv_winsock)(SOCKET s, void FAR * buf, int len, int flags);
51 static int (PASCAL FAR *select_winsock)(int nfds, fd_set FAR *readfds, fd_set FAR *writefds, fd_set FAR *exceptfds, const struct timeval FAR *timeout);
52 static int (PASCAL FAR *send_winsock)(SOCKET s, const void FAR * buf, int len, int flags);
53 static int (PASCAL FAR *setsockopt_winsock)(SOCKET s, int level, int optname, const void FAR * optval, int optlen);
54 static int (PASCAL FAR *shutdown_winsock)(SOCKET s, int how);
55 static SOCKET (PASCAL FAR *socket_winsock)(int af, int type, int protocol);
56 static struct hostent FAR * (PASCAL FAR *gethostbyaddr_winsock)(const char FAR * addr, int len, int type);
57 static struct hostent FAR * (PASCAL FAR *gethostbyname_winsock)(const char FAR * name);
58 static int (PASCAL FAR *WSACleanup_winsock)(void);
59 static int (PASCAL FAR *WSAFDIsSet_winsock)(SOCKET, fd_set FAR * fdset);
60 static WSAEVENT (PASCAL FAR *WSACreateEvent_winsock)(void);
61 static BOOL (PASCAL FAR *WSACloseEvent_winsock)(WSAEVENT);
62 static BOOL (PASCAL FAR *WSASetEvent_winsock)(WSAEVENT);
63 static BOOL (PASCAL FAR *WSAResetEvent_winsock)(WSAEVENT);
64 static int (PASCAL FAR *WSAEventSelect_winsock)(SOCKET, WSAEVENT, long);
65 static DWORD (PASCAL FAR *WSAWaitForMultipleEvents_winsock)(DWORD, const WSAEVENT FAR*, BOOL, DWORD, BOOL);
66 static int (PASCAL FAR *WSAEnumNetworkEvents_winsock)(SOCKET, WSAEVENT, LPWSANETWORKEVENTS);
67 
68 #undef FD_ISSET
69 #define FD_ISSET(fd, set) WSAFDIsSet_winsock((SOCKET)(fd), (fd_set FAR *)(set))
70 
71 #define setfunc(var, name, type) var = (type)netGetProcAddress(module, #name)
72 
73 static HMODULE            s_networkModule = NULL;
74 
75 static
76 FARPROC
netGetProcAddress(HMODULE module,LPCSTR name)77 netGetProcAddress(HMODULE module, LPCSTR name)
78 {
79     FARPROC func = ::GetProcAddress(module, name);
80     if (!func) {
81         throw XArchNetworkSupport("");
82     }
83     return func;
84 }
85 
86 ArchNetAddressImpl*
alloc(size_t size)87 ArchNetAddressImpl::alloc(size_t size)
88 {
89     size_t totalSize = size + ADDR_HDR_SIZE;
90     ArchNetAddressImpl* addr = (ArchNetAddressImpl*)malloc(totalSize);
91     addr->m_len = (int)size;
92     return addr;
93 }
94 
95 
96 //
97 // ArchNetworkWinsock
98 //
99 
ArchNetworkWinsock()100 ArchNetworkWinsock::ArchNetworkWinsock() :
101     m_mutex(NULL)
102 {
103 }
104 
~ArchNetworkWinsock()105 ArchNetworkWinsock::~ArchNetworkWinsock()
106 {
107     if (s_networkModule != NULL) {
108         WSACleanup_winsock();
109         ::FreeLibrary(s_networkModule);
110 
111         WSACleanup_winsock = NULL;
112         s_networkModule    = NULL;
113     }
114     if (m_mutex != NULL) {
115         ARCH->closeMutex(m_mutex);
116     }
117 
118     EventList::iterator it;
119     for (it = m_unblockEvents.begin(); it != m_unblockEvents.end(); it++) {
120         delete *it;
121     }
122 }
123 
124 void
init()125 ArchNetworkWinsock::init()
126 {
127     static const char* s_library[] = { "ws2_32.dll" };
128 
129     assert(WSACleanup_winsock == NULL);
130     assert(s_networkModule    == NULL);
131 
132     // try each winsock library
133     for (size_t i = 0; i < sizeof(s_library) / sizeof(s_library[0]); ++i) {
134         try {
135             initModule((HMODULE)::LoadLibrary(s_library[i]));
136             m_mutex = ARCH->newMutex();
137             return;
138         }
139         catch (XArchNetwork&) {
140             // ignore
141         }
142     }
143 
144     // can't initialize any library
145     throw XArchNetworkSupport("Cannot load winsock library");
146 }
147 
148 void
initModule(HMODULE module)149 ArchNetworkWinsock::initModule(HMODULE module)
150 {
151     if (module == NULL) {
152         throw XArchNetworkSupport("");
153     }
154 
155     // get startup function address
156     int (PASCAL FAR *startup)(WORD, LPWSADATA);
157     setfunc(startup, WSAStartup, int(PASCAL FAR*)(WORD, LPWSADATA));
158 
159     // startup network library
160     WORD version = MAKEWORD(2 /*major*/, 2 /*minor*/);
161     WSADATA data;
162     int err = startup(version, &data);
163     if (data.wVersion != version) {
164         throw XArchNetworkSupport(new XArchEvalWinsock(err));
165     }
166     if (err != 0) {
167         // some other initialization error
168         throwError(err);
169     }
170 
171     // get function addresses
172     setfunc(accept_winsock, accept, SOCKET (PASCAL FAR *)(SOCKET s, struct sockaddr FAR *addr, int FAR *addrlen));
173     setfunc(bind_winsock, bind, int (PASCAL FAR *)(SOCKET s, const struct sockaddr FAR *addr, int namelen));
174     setfunc(close_winsock, closesocket, int (PASCAL FAR *)(SOCKET s));
175     setfunc(connect_winsock, connect, int (PASCAL FAR *)(SOCKET s, const struct sockaddr FAR *name, int namelen));
176     setfunc(gethostname_winsock, gethostname, int (PASCAL FAR *)(char FAR * name, int namelen));
177     setfunc(getsockerror_winsock, WSAGetLastError, int (PASCAL FAR *)(void));
178     setfunc(getsockopt_winsock, getsockopt, int (PASCAL FAR *)(SOCKET s, int level, int optname, void FAR * optval, int FAR *optlen));
179     setfunc(htons_winsock, htons, u_short (PASCAL FAR *)(u_short v));
180     setfunc(inet_ntoa_winsock, inet_ntoa, char FAR * (PASCAL FAR *)(struct in_addr in));
181     setfunc(inet_addr_winsock, inet_addr, unsigned long (PASCAL FAR *)(const char FAR * cp));
182     setfunc(ioctl_winsock, ioctlsocket, int (PASCAL FAR *)(SOCKET s, int cmd, void FAR *));
183     setfunc(listen_winsock, listen, int (PASCAL FAR *)(SOCKET s, int backlog));
184     setfunc(ntohs_winsock, ntohs, u_short (PASCAL FAR *)(u_short v));
185     setfunc(recv_winsock, recv, int (PASCAL FAR *)(SOCKET s, void FAR * buf, int len, int flags));
186     setfunc(select_winsock, select, int (PASCAL FAR *)(int nfds, fd_set FAR *readfds, fd_set FAR *writefds, fd_set FAR *exceptfds, const struct timeval FAR *timeout));
187     setfunc(send_winsock, send, int (PASCAL FAR *)(SOCKET s, const void FAR * buf, int len, int flags));
188     setfunc(setsockopt_winsock, setsockopt, int (PASCAL FAR *)(SOCKET s, int level, int optname, const void FAR * optval, int optlen));
189     setfunc(shutdown_winsock, shutdown, int (PASCAL FAR *)(SOCKET s, int how));
190     setfunc(socket_winsock, socket, SOCKET (PASCAL FAR *)(int af, int type, int protocol));
191     setfunc(gethostbyaddr_winsock, gethostbyaddr, struct hostent FAR * (PASCAL FAR *)(const char FAR * addr, int len, int type));
192     setfunc(gethostbyname_winsock, gethostbyname, struct hostent FAR * (PASCAL FAR *)(const char FAR * name));
193     setfunc(WSACleanup_winsock, WSACleanup, int (PASCAL FAR *)(void));
194     setfunc(WSAFDIsSet_winsock, __WSAFDIsSet, int (PASCAL FAR *)(SOCKET, fd_set FAR *));
195     setfunc(WSACreateEvent_winsock, WSACreateEvent, WSAEVENT (PASCAL FAR *)(void));
196     setfunc(WSACloseEvent_winsock, WSACloseEvent, BOOL (PASCAL FAR *)(WSAEVENT));
197     setfunc(WSASetEvent_winsock, WSASetEvent, BOOL (PASCAL FAR *)(WSAEVENT));
198     setfunc(WSAResetEvent_winsock, WSAResetEvent, BOOL (PASCAL FAR *)(WSAEVENT));
199     setfunc(WSAEventSelect_winsock, WSAEventSelect, int (PASCAL FAR *)(SOCKET, WSAEVENT, long));
200     setfunc(WSAWaitForMultipleEvents_winsock, WSAWaitForMultipleEvents, DWORD (PASCAL FAR *)(DWORD, const WSAEVENT FAR*, BOOL, DWORD, BOOL));
201     setfunc(WSAEnumNetworkEvents_winsock, WSAEnumNetworkEvents, int (PASCAL FAR *)(SOCKET, WSAEVENT, LPWSANETWORKEVENTS));
202 
203     s_networkModule = module;
204 }
205 
206 ArchSocket
newSocket(EAddressFamily family,ESocketType type)207 ArchNetworkWinsock::newSocket(EAddressFamily family, ESocketType type)
208 {
209     // create socket
210     SOCKET fd = socket_winsock(s_family[family], s_type[type], 0);
211     if (fd == INVALID_SOCKET) {
212         throwError(getsockerror_winsock());
213     }
214     try {
215         setBlockingOnSocket(fd, false);
216         BOOL flag = 0;
217         int size     = sizeof(flag);
218         if (setsockopt_winsock(fd, IPPROTO_IPV6, IPV6_V6ONLY, &flag, size) == SOCKET_ERROR) {
219             throwError(getsockerror_winsock());
220         }
221     }
222     catch (...) {
223         close_winsock(fd);
224         throw;
225     }
226 
227     // allocate socket object
228     ArchSocketImpl* socket = new ArchSocketImpl;
229     socket->m_socket        = fd;
230     socket->m_refCount      = 1;
231     socket->m_event         = WSACreateEvent_winsock();
232     socket->m_pollWrite     = true;
233     return socket;
234 }
235 
236 ArchSocket
copySocket(ArchSocket s)237 ArchNetworkWinsock::copySocket(ArchSocket s)
238 {
239     assert(s != NULL);
240 
241     // ref the socket and return it
242     ARCH->lockMutex(m_mutex);
243     ++s->m_refCount;
244     ARCH->unlockMutex(m_mutex);
245     return s;
246 }
247 
248 void
closeSocket(ArchSocket s)249 ArchNetworkWinsock::closeSocket(ArchSocket s)
250 {
251     assert(s != NULL);
252 
253     // unref the socket and note if it should be released
254     ARCH->lockMutex(m_mutex);
255     const bool doClose = (--s->m_refCount == 0);
256     ARCH->unlockMutex(m_mutex);
257 
258     // close the socket if necessary
259     if (doClose) {
260         if (close_winsock(s->m_socket) == SOCKET_ERROR) {
261             // close failed.  restore the last ref and throw.
262             int err = getsockerror_winsock();
263             ARCH->lockMutex(m_mutex);
264             ++s->m_refCount;
265             ARCH->unlockMutex(m_mutex);
266             throwError(err);
267         }
268         WSACloseEvent_winsock(s->m_event);
269         delete s;
270     }
271 }
272 
273 void
closeSocketForRead(ArchSocket s)274 ArchNetworkWinsock::closeSocketForRead(ArchSocket s)
275 {
276     assert(s != NULL);
277 
278     if (shutdown_winsock(s->m_socket, SD_RECEIVE) == SOCKET_ERROR) {
279         if (getsockerror_winsock() != WSAENOTCONN) {
280             throwError(getsockerror_winsock());
281         }
282     }
283 }
284 
285 void
closeSocketForWrite(ArchSocket s)286 ArchNetworkWinsock::closeSocketForWrite(ArchSocket s)
287 {
288     assert(s != NULL);
289 
290     if (shutdown_winsock(s->m_socket, SD_SEND) == SOCKET_ERROR) {
291         if (getsockerror_winsock() != WSAENOTCONN) {
292             throwError(getsockerror_winsock());
293         }
294     }
295 }
296 
297 void
bindSocket(ArchSocket s,ArchNetAddress addr)298 ArchNetworkWinsock::bindSocket(ArchSocket s, ArchNetAddress addr)
299 {
300     assert(s    != NULL);
301     assert(addr != NULL);
302 
303     if (bind_winsock(s->m_socket, TYPED_ADDR(struct sockaddr, addr), addr->m_len) == SOCKET_ERROR) {
304         throwError(getsockerror_winsock());
305     }
306 }
307 
308 void
listenOnSocket(ArchSocket s)309 ArchNetworkWinsock::listenOnSocket(ArchSocket s)
310 {
311     assert(s != NULL);
312 
313     // hardcoding backlog
314     if (listen_winsock(s->m_socket, 3) == SOCKET_ERROR) {
315         throwError(getsockerror_winsock());
316     }
317 }
318 
319 ArchSocket
acceptSocket(ArchSocket s,ArchNetAddress * const addr)320 ArchNetworkWinsock::acceptSocket(ArchSocket s, ArchNetAddress* const addr)
321 {
322     assert(s != NULL);
323 
324     // create new socket and temporary address
325     ArchSocketImpl* socket = new ArchSocketImpl;
326     ArchNetAddress tmp = ArchNetAddressImpl::alloc(sizeof(struct sockaddr_in6));
327 
328     // accept on socket
329     SOCKET fd = accept_winsock(s->m_socket, TYPED_ADDR(struct sockaddr, tmp), &tmp->m_len);
330     if (fd == INVALID_SOCKET) {
331         int err = getsockerror_winsock();
332         delete socket;
333         free(tmp);
334         if (addr) {
335             *addr = NULL;
336         }
337         if (err == WSAEWOULDBLOCK) {
338             return NULL;
339         }
340         throwError(err);
341     }
342 
343     try {
344         setBlockingOnSocket(fd, false);
345     }
346     catch (...) {
347         close_winsock(fd);
348         delete socket;
349         free(tmp);
350         if (addr) {
351             *addr = NULL;
352         }
353         throw;
354     }
355 
356     // initialize socket
357     socket->m_socket    = fd;
358     socket->m_refCount  = 1;
359     socket->m_event     = WSACreateEvent_winsock();
360     socket->m_pollWrite = true;
361 
362     // copy address if requested
363     if (addr != NULL) {
364         *addr = ARCH->copyAddr(tmp);
365     }
366 
367     free(tmp);
368     return socket;
369 }
370 
371 bool
connectSocket(ArchSocket s,ArchNetAddress addr)372 ArchNetworkWinsock::connectSocket(ArchSocket s, ArchNetAddress addr)
373 {
374     assert(s    != NULL);
375     assert(addr != NULL);
376 
377     if (connect_winsock(s->m_socket, TYPED_ADDR(struct sockaddr, addr),
378                             addr->m_len) == SOCKET_ERROR) {
379         if (getsockerror_winsock() == WSAEISCONN) {
380             return true;
381         }
382         if (getsockerror_winsock() == WSAEWOULDBLOCK) {
383             return false;
384         }
385         throwError(getsockerror_winsock());
386     }
387     return true;
388 }
389 
390 int
pollSocket(PollEntry pe[],int num,double timeout)391 ArchNetworkWinsock::pollSocket(PollEntry pe[], int num, double timeout)
392 {
393     int i;
394     DWORD n;
395 
396     // prepare sockets and wait list
397     bool canWrite = false;
398     WSAEVENT* events = (WSAEVENT*)alloca((num + 1) * sizeof(WSAEVENT));
399     for (i = 0, n = 0; i < num; ++i) {
400         // reset return flags
401         pe[i].m_revents = 0;
402 
403         // set invalid flag if socket is bogus then go to next socket
404         if (pe[i].m_socket == NULL) {
405             pe[i].m_revents |= kPOLLNVAL;
406             continue;
407         }
408 
409         // select desired events
410         long socketEvents = 0;
411         if ((pe[i].m_events & kPOLLIN) != 0) {
412             socketEvents |= FD_READ | FD_ACCEPT | FD_CLOSE;
413         }
414         if ((pe[i].m_events & kPOLLOUT) != 0) {
415             socketEvents |= FD_WRITE | FD_CONNECT | FD_CLOSE;
416 
417             // if m_pollWrite is false then we assume the socket is
418             // writable.  winsock doesn't signal writability except
419             // when the state changes from unwritable.
420             if (!pe[i].m_socket->m_pollWrite) {
421                 canWrite         = true;
422                 pe[i].m_revents |= kPOLLOUT;
423             }
424         }
425 
426         // if no events then ignore socket
427         if (socketEvents == 0) {
428             continue;
429         }
430 
431         // select socket for desired events
432         WSAEventSelect_winsock(pe[i].m_socket->m_socket,
433                             pe[i].m_socket->m_event, socketEvents);
434 
435         // add socket event to wait list
436         events[n++] = pe[i].m_socket->m_event;
437     }
438 
439     // if no sockets then return immediately
440     if (n == 0) {
441         return 0;
442     }
443 
444     // add the unblock event
445     ArchMultithreadWindows* mt = ArchMultithreadWindows::getInstance();
446     ArchThread thread     = mt->newCurrentThread();
447     WSAEVENT* unblockEvent = (WSAEVENT*)mt->getNetworkDataForThread(thread);
448     ARCH->closeThread(thread);
449     if (unblockEvent == NULL) {
450         unblockEvent  = new WSAEVENT;
451         m_unblockEvents.push_back(unblockEvent);
452         *unblockEvent = WSACreateEvent_winsock();
453         mt->setNetworkDataForCurrentThread(unblockEvent);
454     }
455     events[n++] = *unblockEvent;
456 
457     // prepare timeout
458     DWORD t = (timeout < 0.0) ? INFINITE : (DWORD)(1000.0 * timeout);
459     if (canWrite) {
460         // if we know we can write then don't block
461         t = 0;
462     }
463 
464     // wait
465     DWORD result = WSAWaitForMultipleEvents_winsock(n, events, FALSE, t, FALSE);
466 
467     // reset the unblock event
468     WSAResetEvent_winsock(*unblockEvent);
469 
470     // handle results
471     if (result == WSA_WAIT_FAILED) {
472         if (getsockerror_winsock() == WSAEINTR) {
473             // interrupted system call
474             ARCH->testCancelThread();
475             return 0;
476         }
477         throwError(getsockerror_winsock());
478     }
479     if (result == WSA_WAIT_TIMEOUT && !canWrite) {
480         return 0;
481     }
482     if (result == WSA_WAIT_EVENT_0 + n - 1) {
483         // the unblock event was signalled
484         return 0;
485     }
486     for (i = 0, n = 0; i < num; ++i) {
487         // skip events we didn't check
488         if (pe[i].m_socket == NULL ||
489             (pe[i].m_events & (kPOLLIN | kPOLLOUT)) == 0) {
490             continue;
491         }
492 
493         // get events
494         WSANETWORKEVENTS info;
495         if (WSAEnumNetworkEvents_winsock(pe[i].m_socket->m_socket,
496                             pe[i].m_socket->m_event, &info) == SOCKET_ERROR) {
497             continue;
498         }
499         if ((info.lNetworkEvents & FD_READ) != 0) {
500             pe[i].m_revents |= kPOLLIN;
501         }
502         if ((info.lNetworkEvents & FD_ACCEPT) != 0) {
503             pe[i].m_revents |= kPOLLIN;
504         }
505         if ((info.lNetworkEvents & FD_WRITE) != 0) {
506             pe[i].m_revents |= kPOLLOUT;
507 
508             // socket is now writable so don't bothing polling for
509             // writable until it becomes unwritable.
510             pe[i].m_socket->m_pollWrite = false;
511         }
512         if ((info.lNetworkEvents & FD_CONNECT) != 0) {
513             if (info.iErrorCode[FD_CONNECT_BIT] != 0) {
514                 pe[i].m_revents |= kPOLLERR;
515             }
516             else {
517                 pe[i].m_revents |= kPOLLOUT;
518                 pe[i].m_socket->m_pollWrite = false;
519             }
520         }
521         if ((info.lNetworkEvents & FD_CLOSE) != 0) {
522             if (info.iErrorCode[FD_CLOSE_BIT] != 0) {
523                 pe[i].m_revents |= kPOLLERR;
524             }
525             else {
526                 if ((pe[i].m_events & kPOLLIN) != 0) {
527                     pe[i].m_revents |= kPOLLIN;
528                 }
529                 if ((pe[i].m_events & kPOLLOUT) != 0) {
530                     pe[i].m_revents |= kPOLLOUT;
531                 }
532             }
533         }
534         if (pe[i].m_revents != 0) {
535             ++n;
536         }
537     }
538 
539     return (int)n;
540 }
541 
542 void
unblockPollSocket(ArchThread thread)543 ArchNetworkWinsock::unblockPollSocket(ArchThread thread)
544 {
545     // set the unblock event
546     ArchMultithreadWindows* mt = ArchMultithreadWindows::getInstance();
547     WSAEVENT* unblockEvent = (WSAEVENT*)mt->getNetworkDataForThread(thread);
548     if (unblockEvent != NULL) {
549         WSASetEvent_winsock(*unblockEvent);
550     }
551 }
552 
553 size_t
readSocket(ArchSocket s,void * buf,size_t len)554 ArchNetworkWinsock::readSocket(ArchSocket s, void* buf, size_t len)
555 {
556     assert(s != NULL);
557 
558     int n = recv_winsock(s->m_socket, buf, (int)len, 0);
559     if (n == SOCKET_ERROR) {
560         int err = getsockerror_winsock();
561         if (err == WSAEINTR || err == WSAEWOULDBLOCK) {
562             return 0;
563         }
564         throwError(err);
565     }
566     return static_cast<size_t>(n);
567 }
568 
569 size_t
writeSocket(ArchSocket s,const void * buf,size_t len)570 ArchNetworkWinsock::writeSocket(ArchSocket s, const void* buf, size_t len)
571 {
572     assert(s != NULL);
573 
574     int n = send_winsock(s->m_socket, buf, (int)len, 0);
575     if (n == SOCKET_ERROR) {
576         int err = getsockerror_winsock();
577         if (err == WSAEINTR) {
578             return 0;
579         }
580         if (err == WSAEWOULDBLOCK) {
581             s->m_pollWrite = true;
582             return 0;
583         }
584         throwError(err);
585     }
586     return static_cast<size_t>(n);
587 }
588 
589 void
throwErrorOnSocket(ArchSocket s)590 ArchNetworkWinsock::throwErrorOnSocket(ArchSocket s)
591 {
592     assert(s != NULL);
593 
594     // get the error from the socket layer
595     int err  = 0;
596     int size = sizeof(err);
597     if (getsockopt_winsock(s->m_socket, SOL_SOCKET,
598                                     SO_ERROR, &err, &size) == SOCKET_ERROR) {
599         err = getsockerror_winsock();
600     }
601 
602     // throw if there's an error
603     if (err != 0) {
604         throwError(err);
605     }
606 }
607 
608 void
setBlockingOnSocket(SOCKET s,bool blocking)609 ArchNetworkWinsock::setBlockingOnSocket(SOCKET s, bool blocking)
610 {
611     assert(s != 0);
612 
613     int flag = blocking ? 0 : 1;
614     if (ioctl_winsock(s, FIONBIO, &flag) == SOCKET_ERROR) {
615         throwError(getsockerror_winsock());
616     }
617 }
618 
619 bool
setNoDelayOnSocket(ArchSocket s,bool noDelay)620 ArchNetworkWinsock::setNoDelayOnSocket(ArchSocket s, bool noDelay)
621 {
622     assert(s != NULL);
623 
624     // get old state
625     BOOL oflag;
626     int size = sizeof(oflag);
627     if (getsockopt_winsock(s->m_socket, IPPROTO_TCP,
628                                 TCP_NODELAY, &oflag, &size) == SOCKET_ERROR) {
629         throwError(getsockerror_winsock());
630     }
631 
632     // set new state
633     BOOL flag = noDelay ? 1 : 0;
634     size     = sizeof(flag);
635     if (setsockopt_winsock(s->m_socket, IPPROTO_TCP,
636                                 TCP_NODELAY, &flag, size) == SOCKET_ERROR) {
637         throwError(getsockerror_winsock());
638     }
639 
640     return (oflag != 0);
641 }
642 
643 bool
setReuseAddrOnSocket(ArchSocket s,bool reuse)644 ArchNetworkWinsock::setReuseAddrOnSocket(ArchSocket s, bool reuse)
645 {
646     assert(s != NULL);
647 
648     // get old state
649     BOOL oflag;
650     int size = sizeof(oflag);
651     if (getsockopt_winsock(s->m_socket, SOL_SOCKET,
652                                 SO_REUSEADDR, &oflag, &size) == SOCKET_ERROR) {
653         throwError(getsockerror_winsock());
654     }
655 
656     // set new state
657     BOOL flag = reuse ? 1 : 0;
658     size     = sizeof(flag);
659     if (setsockopt_winsock(s->m_socket, SOL_SOCKET,
660                                 SO_REUSEADDR, &flag, size) == SOCKET_ERROR) {
661         throwError(getsockerror_winsock());
662     }
663 
664     return (oflag != 0);
665 }
666 
667 std::string
getHostName()668 ArchNetworkWinsock::getHostName()
669 {
670     char name[256];
671     if (gethostname_winsock(name, sizeof(name)) == -1) {
672         name[0] = '\0';
673     }
674     else {
675         name[sizeof(name) - 1] = '\0';
676     }
677     return name;
678 }
679 
680 ArchNetAddress
newAnyAddr(EAddressFamily family)681 ArchNetworkWinsock::newAnyAddr(EAddressFamily family)
682 {
683     ArchNetAddressImpl* addr = NULL;
684     switch (family) {
685     case kINET: {
686         addr = ArchNetAddressImpl::alloc(sizeof(struct sockaddr_in));
687         struct sockaddr_in* ipAddr = TYPED_ADDR(struct sockaddr_in, addr);
688         ipAddr->sin_family         = AF_INET;
689         ipAddr->sin_port           = 0;
690         ipAddr->sin_addr.s_addr    = INADDR_ANY;
691         break;
692     }
693 
694     case kINET6: {
695         addr = ArchNetAddressImpl::alloc(sizeof(struct sockaddr_in6));
696         struct sockaddr_in6* ipAddr = TYPED_ADDR(struct sockaddr_in6, addr);
697         ipAddr->sin6_family         = AF_INET6;
698         ipAddr->sin6_port           = 0;
699         memcpy(&ipAddr->sin6_addr, &in6addr_any, sizeof(in6addr_any));
700         break;
701     }
702 
703     default:
704         assert(0 && "invalid family");
705     }
706     return addr;
707 }
708 
709 ArchNetAddress
copyAddr(ArchNetAddress addr)710 ArchNetworkWinsock::copyAddr(ArchNetAddress addr)
711 {
712     assert(addr != NULL);
713 
714     ArchNetAddressImpl* copy = ArchNetAddressImpl::alloc(addr->m_len);
715     memcpy(TYPED_ADDR(void, copy), TYPED_ADDR(void, addr), addr->m_len);
716     return copy;
717 }
718 
719 std::vector<ArchNetAddress>
nameToAddr(const std::string & name)720 ArchNetworkWinsock::nameToAddr(const std::string& name)
721 {
722     // allocate address
723     std::vector<ArchNetAddressImpl*> addresses;
724 
725     struct addrinfo hints;
726     struct addrinfo *pResult;
727     memset(&hints, 0, sizeof(hints));
728     hints.ai_family = AF_UNSPEC;
729     int ret = -1;
730 
731     ARCH->lockMutex(m_mutex);
732     if ((ret = getaddrinfo(name.c_str(), NULL, &hints, &pResult)) != 0) {
733         ARCH->unlockMutex(m_mutex);
734         throwNameError(ret);
735     }
736 
737     for(; pResult != nullptr; pResult = pResult->ai_next ){
738         addresses.push_back(new ArchNetAddressImpl);
739         if (pResult->ai_family == AF_INET) {
740             addresses.back()->m_len = (socklen_t)sizeof(struct sockaddr_in);
741         } else {
742             addresses.back()->m_len = (socklen_t)sizeof(struct sockaddr_in6);
743         }
744 
745         memcpy(&addresses.back()->m_addr, pResult->ai_addr, addresses.back()->m_len);
746     }
747 
748     freeaddrinfo(pResult);
749     ARCH->unlockMutex(m_mutex);
750     return addresses;
751 }
752 
753 void
closeAddr(ArchNetAddress addr)754 ArchNetworkWinsock::closeAddr(ArchNetAddress addr)
755 {
756     assert(addr != NULL);
757 
758     free(addr);
759 }
760 
761 std::string
addrToName(ArchNetAddress addr)762 ArchNetworkWinsock::addrToName(ArchNetAddress addr)
763 {
764     assert(addr != NULL);
765 
766     char host[1024];
767     char service[20];
768     int ret = getnameinfo(TYPED_ADDR(struct sockaddr, addr), addr->m_len, host, sizeof(host), service, sizeof(service), 0);
769 
770     if (ret  != NULL) {
771         throwNameError(ret);
772     }
773 
774     // return (primary) name
775     std::string name = host;
776     return name;
777 }
778 
779 std::string
addrToString(ArchNetAddress addr)780 ArchNetworkWinsock::addrToString(ArchNetAddress addr)
781 {
782     assert(addr != NULL);
783 
784     switch (getAddrFamily(addr)) {
785     case kINET: {
786         struct sockaddr_in* ipAddr = TYPED_ADDR(struct sockaddr_in, addr);
787         return inet_ntoa_winsock(ipAddr->sin_addr);
788     }
789 
790     case kINET6: {
791         char strAddr[INET6_ADDRSTRLEN];
792         struct sockaddr_in6* ipAddr = TYPED_ADDR(struct sockaddr_in6, addr);
793         inet_ntop(AF_INET6, &ipAddr->sin6_addr, strAddr, INET6_ADDRSTRLEN);
794         return strAddr;
795     }
796 
797     default:
798         assert(0 && "unknown address family");
799         return "";
800     }
801 }
802 
803 IArchNetwork::EAddressFamily
getAddrFamily(ArchNetAddress addr)804 ArchNetworkWinsock::getAddrFamily(ArchNetAddress addr)
805 {
806     assert(addr != NULL);
807 
808     switch (addr->m_addr.ss_family) {
809     case AF_INET:
810         return kINET;
811 
812     case AF_INET6:
813         return kINET6;
814 
815     default:
816         return kUNKNOWN;
817     }
818 }
819 
820 void
setAddrPort(ArchNetAddress addr,int port)821 ArchNetworkWinsock::setAddrPort(ArchNetAddress addr, int port)
822 {
823     assert(addr != NULL);
824 
825     switch (getAddrFamily(addr)) {
826     case kINET: {
827         struct sockaddr_in* ipAddr = TYPED_ADDR(struct sockaddr_in, addr);
828         ipAddr->sin_port = htons_winsock(static_cast<u_short>(port));
829         break;
830     }
831 
832     case kINET6: {
833         struct sockaddr_in6* ipAddr = TYPED_ADDR(struct sockaddr_in6, addr);
834         ipAddr->sin6_port = htons_winsock(static_cast<u_short>(port));
835         break;
836     }
837 
838     default:
839         assert(0 && "unknown address family");
840         break;
841     }
842 }
843 
844 int
getAddrPort(ArchNetAddress addr)845 ArchNetworkWinsock::getAddrPort(ArchNetAddress addr)
846 {
847     assert(addr != NULL);
848 
849     switch (getAddrFamily(addr)) {
850     case kINET: {
851         struct sockaddr_in* ipAddr = TYPED_ADDR(struct sockaddr_in, addr);
852         return ntohs_winsock(ipAddr->sin_port);
853     }
854 
855     case kINET6: {
856         struct sockaddr_in6* ipAddr = TYPED_ADDR(struct sockaddr_in6, addr);
857         return ntohs_winsock(ipAddr->sin6_port);
858     }
859 
860     default:
861         assert(0 && "unknown address family");
862         return 0;
863     }
864 }
865 
866 bool
isAnyAddr(ArchNetAddress addr)867 ArchNetworkWinsock::isAnyAddr(ArchNetAddress addr)
868 {
869     assert(addr != NULL);
870 
871     switch (getAddrFamily(addr)) {
872     case kINET: {
873         struct sockaddr_in* ipAddr = TYPED_ADDR(struct sockaddr_in, addr);
874         return (addr->m_len == sizeof(struct sockaddr_in) &&
875                 ipAddr->sin_addr.s_addr == INADDR_ANY);
876     }
877 
878     case kINET6: {
879         struct sockaddr_in6* ipAddr = TYPED_ADDR(struct sockaddr_in6, addr);
880         return (addr->m_len == sizeof(struct sockaddr_in) &&
881                 memcmp(&ipAddr->sin6_addr, &in6addr_any, sizeof(in6addr_any))== 0);
882     }
883 
884     default:
885         assert(0 && "unknown address family");
886         return true;
887     }
888 }
889 
890 bool
isEqualAddr(ArchNetAddress a,ArchNetAddress b)891 ArchNetworkWinsock::isEqualAddr(ArchNetAddress a, ArchNetAddress b)
892 {
893     return (a == b || (a->m_len == b->m_len &&
894             memcmp(&a->m_addr, &b->m_addr, a->m_len) == 0));
895 }
896 
897 void
throwError(int err)898 ArchNetworkWinsock::throwError(int err)
899 {
900     switch (err) {
901     case WSAEACCES:
902         throw XArchNetworkAccess(new XArchEvalWinsock(err));
903 
904     case WSAEMFILE:
905     case WSAENOBUFS:
906     case WSAENETDOWN:
907         throw XArchNetworkResource(new XArchEvalWinsock(err));
908 
909     case WSAEPROTOTYPE:
910     case WSAEPROTONOSUPPORT:
911     case WSAEAFNOSUPPORT:
912     case WSAEPFNOSUPPORT:
913     case WSAESOCKTNOSUPPORT:
914     case WSAEINVAL:
915     case WSAENOPROTOOPT:
916     case WSAEOPNOTSUPP:
917     case WSAESHUTDOWN:
918     case WSANOTINITIALISED:
919     case WSAVERNOTSUPPORTED:
920     case WSASYSNOTREADY:
921         throw XArchNetworkSupport(new XArchEvalWinsock(err));
922 
923     case WSAEADDRNOTAVAIL:
924         throw XArchNetworkNoAddress(new XArchEvalWinsock(err));
925 
926     case WSAEADDRINUSE:
927         throw XArchNetworkAddressInUse(new XArchEvalWinsock(err));
928 
929     case WSAEHOSTUNREACH:
930     case WSAENETUNREACH:
931         throw XArchNetworkNoRoute(new XArchEvalWinsock(err));
932 
933     case WSAENOTCONN:
934         throw XArchNetworkNotConnected(new XArchEvalWinsock(err));
935 
936     case WSAEDISCON:
937         throw XArchNetworkShutdown(new XArchEvalWinsock(err));
938 
939     case WSAENETRESET:
940     case WSAECONNABORTED:
941     case WSAECONNRESET:
942         throw XArchNetworkDisconnected(new XArchEvalWinsock(err));
943 
944     case WSAECONNREFUSED:
945         throw XArchNetworkConnectionRefused(new XArchEvalWinsock(err));
946 
947     case WSAEHOSTDOWN:
948     case WSAETIMEDOUT:
949         throw XArchNetworkTimedOut(new XArchEvalWinsock(err));
950 
951     case WSAHOST_NOT_FOUND:
952         throw XArchNetworkNameUnknown(new XArchEvalWinsock(err));
953 
954     case WSANO_DATA:
955         throw XArchNetworkNameNoAddress(new XArchEvalWinsock(err));
956 
957     case WSANO_RECOVERY:
958         throw XArchNetworkNameFailure(new XArchEvalWinsock(err));
959 
960     case WSATRY_AGAIN:
961         throw XArchNetworkNameUnavailable(new XArchEvalWinsock(err));
962 
963     default:
964         throw XArchNetwork(new XArchEvalWinsock(err));
965     }
966 }
967 
968 void
throwNameError(int err)969 ArchNetworkWinsock::throwNameError(int err)
970 {
971     switch (err) {
972     case WSAHOST_NOT_FOUND:
973         throw XArchNetworkNameUnknown(new XArchEvalWinsock(err));
974 
975     case WSANO_DATA:
976         throw XArchNetworkNameNoAddress(new XArchEvalWinsock(err));
977 
978     case WSANO_RECOVERY:
979         throw XArchNetworkNameFailure(new XArchEvalWinsock(err));
980 
981     case WSATRY_AGAIN:
982         throw XArchNetworkNameUnavailable(new XArchEvalWinsock(err));
983 
984     default:
985         throw XArchNetworkName(new XArchEvalWinsock(err));
986     }
987 }
988