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