00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "CArchNetworkWinsock.h"
00021 #include "CArch.h"
00022 #include "CArchMultithreadWindows.h"
00023 #include "IArchMultithread.h"
00024 #include "XArchWindows.h"
00025 #include <malloc.h>
00026
00027 static const int s_family[] = {
00028 PF_UNSPEC,
00029 PF_INET
00030 };
00031 static const int s_type[] = {
00032 SOCK_DGRAM,
00033 SOCK_STREAM
00034 };
00035
00036 static SOCKET (PASCAL FAR *accept_winsock)(SOCKET s, struct sockaddr FAR *addr, int FAR *addrlen);
00037 static int (PASCAL FAR *bind_winsock)(SOCKET s, const struct sockaddr FAR *addr, int namelen);
00038 static int (PASCAL FAR *close_winsock)(SOCKET s);
00039 static int (PASCAL FAR *connect_winsock)(SOCKET s, const struct sockaddr FAR *name, int namelen);
00040 static int (PASCAL FAR *gethostname_winsock)(char FAR * name, int namelen);
00041 static int (PASCAL FAR *getsockerror_winsock)(void);
00042 static int (PASCAL FAR *getsockopt_winsock)(SOCKET s, int level, int optname, void FAR * optval, int FAR *optlen);
00043 static u_short (PASCAL FAR *htons_winsock)(u_short v);
00044 static char FAR * (PASCAL FAR *inet_ntoa_winsock)(struct in_addr in);
00045 static unsigned long (PASCAL FAR *inet_addr_winsock)(const char FAR * cp);
00046 static int (PASCAL FAR *ioctl_winsock)(SOCKET s, int cmd, void FAR * data);
00047 static int (PASCAL FAR *listen_winsock)(SOCKET s, int backlog);
00048 static u_short (PASCAL FAR *ntohs_winsock)(u_short v);
00049 static int (PASCAL FAR *recv_winsock)(SOCKET s, void FAR * buf, int len, int flags);
00050 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);
00051 static int (PASCAL FAR *send_winsock)(SOCKET s, const void FAR * buf, int len, int flags);
00052 static int (PASCAL FAR *setsockopt_winsock)(SOCKET s, int level, int optname, const void FAR * optval, int optlen);
00053 static int (PASCAL FAR *shutdown_winsock)(SOCKET s, int how);
00054 static SOCKET (PASCAL FAR *socket_winsock)(int af, int type, int protocol);
00055 static struct hostent FAR * (PASCAL FAR *gethostbyaddr_winsock)(const char FAR * addr, int len, int type);
00056 static struct hostent FAR * (PASCAL FAR *gethostbyname_winsock)(const char FAR * name);
00057 static int (PASCAL FAR *WSACleanup_winsock)(void);
00058 static int (PASCAL FAR *WSAFDIsSet_winsock)(SOCKET, fd_set FAR * fdset);
00059 static WSAEVENT (PASCAL FAR *WSACreateEvent_winsock)(void);
00060 static BOOL (PASCAL FAR *WSACloseEvent_winsock)(WSAEVENT);
00061 static BOOL (PASCAL FAR *WSASetEvent_winsock)(WSAEVENT);
00062 static BOOL (PASCAL FAR *WSAResetEvent_winsock)(WSAEVENT);
00063 static int (PASCAL FAR *WSAEventSelect_winsock)(SOCKET, WSAEVENT, long);
00064 static DWORD (PASCAL FAR *WSAWaitForMultipleEvents_winsock)(DWORD, const WSAEVENT FAR*, BOOL, DWORD, BOOL);
00065 static int (PASCAL FAR *WSAEnumNetworkEvents_winsock)(SOCKET, WSAEVENT, LPWSANETWORKEVENTS);
00066
00067 #undef FD_ISSET
00068 #define FD_ISSET(fd, set) WSAFDIsSet_winsock((SOCKET)(fd), (fd_set FAR *)(set))
00069
00070 #define setfunc(var, name, type) var = (type)netGetProcAddress(module, #name)
00071
00072 static HMODULE s_networkModule = NULL;
00073
00074 static
00075 FARPROC
00076 netGetProcAddress(HMODULE module, LPCSTR name)
00077 {
00078 FARPROC func = ::GetProcAddress(module, name);
00079 if (!func) {
00080 throw XArchNetworkSupport("");
00081 }
00082 return func;
00083 }
00084
00085 CArchNetAddressImpl*
00086 CArchNetAddressImpl::alloc(size_t size)
00087 {
00088 size_t totalSize = size + ADDR_HDR_SIZE;
00089 CArchNetAddressImpl* addr = (CArchNetAddressImpl*)malloc(totalSize);
00090 addr->m_len = (int)size;
00091 return addr;
00092 }
00093
00094
00095
00096
00097
00098
00099 CArchNetworkWinsock::CArchNetworkWinsock()
00100 {
00101 }
00102
00103 CArchNetworkWinsock::~CArchNetworkWinsock()
00104 {
00105 if (s_networkModule != NULL) {
00106 WSACleanup_winsock();
00107 ::FreeLibrary(s_networkModule);
00108
00109 WSACleanup_winsock = NULL;
00110 s_networkModule = NULL;
00111 }
00112 ARCH->closeMutex(m_mutex);
00113
00114 CEventList::iterator it;
00115 for (it = m_unblockEvents.begin(); it != m_unblockEvents.end(); it++) {
00116 delete *it;
00117 }
00118 }
00119
00120 void
00121 CArchNetworkWinsock::init()
00122 {
00123 static const char* s_library[] = { "ws2_32.dll" };
00124
00125 assert(WSACleanup_winsock == NULL);
00126 assert(s_networkModule == NULL);
00127
00128
00129 for (size_t i = 0; i < sizeof(s_library) / sizeof(s_library[0]); ++i) {
00130 try {
00131 initModule((HMODULE)::LoadLibrary(s_library[i]));
00132 m_mutex = ARCH->newMutex();
00133 return;
00134 }
00135 catch (XArchNetwork&) {
00136
00137 }
00138 }
00139
00140
00141 throw XArchNetworkSupport("Cannot load winsock library");
00142 }
00143
00144 void
00145 CArchNetworkWinsock::initModule(HMODULE module)
00146 {
00147 if (module == NULL) {
00148 throw XArchNetworkSupport("");
00149 }
00150
00151
00152 int (PASCAL FAR *startup)(WORD, LPWSADATA);
00153 setfunc(startup, WSAStartup, int(PASCAL FAR*)(WORD, LPWSADATA));
00154
00155
00156 WORD version = MAKEWORD(2 , 0 );
00157 WSADATA data;
00158 int err = startup(version, &data);
00159 if (data.wVersion != version) {
00160 throw XArchNetworkSupport(new XArchEvalWinsock(err));
00161 }
00162 if (err != 0) {
00163
00164 throwError(err);
00165 }
00166
00167
00168 setfunc(accept_winsock, accept, SOCKET (PASCAL FAR *)(SOCKET s, struct sockaddr FAR *addr, int FAR *addrlen));
00169 setfunc(bind_winsock, bind, int (PASCAL FAR *)(SOCKET s, const struct sockaddr FAR *addr, int namelen));
00170 setfunc(close_winsock, closesocket, int (PASCAL FAR *)(SOCKET s));
00171 setfunc(connect_winsock, connect, int (PASCAL FAR *)(SOCKET s, const struct sockaddr FAR *name, int namelen));
00172 setfunc(gethostname_winsock, gethostname, int (PASCAL FAR *)(char FAR * name, int namelen));
00173 setfunc(getsockerror_winsock, WSAGetLastError, int (PASCAL FAR *)(void));
00174 setfunc(getsockopt_winsock, getsockopt, int (PASCAL FAR *)(SOCKET s, int level, int optname, void FAR * optval, int FAR *optlen));
00175 setfunc(htons_winsock, htons, u_short (PASCAL FAR *)(u_short v));
00176 setfunc(inet_ntoa_winsock, inet_ntoa, char FAR * (PASCAL FAR *)(struct in_addr in));
00177 setfunc(inet_addr_winsock, inet_addr, unsigned long (PASCAL FAR *)(const char FAR * cp));
00178 setfunc(ioctl_winsock, ioctlsocket, int (PASCAL FAR *)(SOCKET s, int cmd, void FAR *));
00179 setfunc(listen_winsock, listen, int (PASCAL FAR *)(SOCKET s, int backlog));
00180 setfunc(ntohs_winsock, ntohs, u_short (PASCAL FAR *)(u_short v));
00181 setfunc(recv_winsock, recv, int (PASCAL FAR *)(SOCKET s, void FAR * buf, int len, int flags));
00182 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));
00183 setfunc(send_winsock, send, int (PASCAL FAR *)(SOCKET s, const void FAR * buf, int len, int flags));
00184 setfunc(setsockopt_winsock, setsockopt, int (PASCAL FAR *)(SOCKET s, int level, int optname, const void FAR * optval, int optlen));
00185 setfunc(shutdown_winsock, shutdown, int (PASCAL FAR *)(SOCKET s, int how));
00186 setfunc(socket_winsock, socket, SOCKET (PASCAL FAR *)(int af, int type, int protocol));
00187 setfunc(gethostbyaddr_winsock, gethostbyaddr, struct hostent FAR * (PASCAL FAR *)(const char FAR * addr, int len, int type));
00188 setfunc(gethostbyname_winsock, gethostbyname, struct hostent FAR * (PASCAL FAR *)(const char FAR * name));
00189 setfunc(WSACleanup_winsock, WSACleanup, int (PASCAL FAR *)(void));
00190 setfunc(WSAFDIsSet_winsock, __WSAFDIsSet, int (PASCAL FAR *)(SOCKET, fd_set FAR *));
00191 setfunc(WSACreateEvent_winsock, WSACreateEvent, WSAEVENT (PASCAL FAR *)(void));
00192 setfunc(WSACloseEvent_winsock, WSACloseEvent, BOOL (PASCAL FAR *)(WSAEVENT));
00193 setfunc(WSASetEvent_winsock, WSASetEvent, BOOL (PASCAL FAR *)(WSAEVENT));
00194 setfunc(WSAResetEvent_winsock, WSAResetEvent, BOOL (PASCAL FAR *)(WSAEVENT));
00195 setfunc(WSAEventSelect_winsock, WSAEventSelect, int (PASCAL FAR *)(SOCKET, WSAEVENT, long));
00196 setfunc(WSAWaitForMultipleEvents_winsock, WSAWaitForMultipleEvents, DWORD (PASCAL FAR *)(DWORD, const WSAEVENT FAR*, BOOL, DWORD, BOOL));
00197 setfunc(WSAEnumNetworkEvents_winsock, WSAEnumNetworkEvents, int (PASCAL FAR *)(SOCKET, WSAEVENT, LPWSANETWORKEVENTS));
00198
00199 s_networkModule = module;
00200 }
00201
00202 CArchSocket
00203 CArchNetworkWinsock::newSocket(EAddressFamily family, ESocketType type)
00204 {
00205
00206 SOCKET fd = socket_winsock(s_family[family], s_type[type], 0);
00207 if (fd == INVALID_SOCKET) {
00208 throwError(getsockerror_winsock());
00209 }
00210 try {
00211 setBlockingOnSocket(fd, false);
00212 }
00213 catch (...) {
00214 close_winsock(fd);
00215 throw;
00216 }
00217
00218
00219 CArchSocketImpl* socket = new CArchSocketImpl;
00220 socket->m_socket = fd;
00221 socket->m_refCount = 1;
00222 socket->m_event = WSACreateEvent_winsock();
00223 socket->m_pollWrite = true;
00224 return socket;
00225 }
00226
00227 CArchSocket
00228 CArchNetworkWinsock::copySocket(CArchSocket s)
00229 {
00230 assert(s != NULL);
00231
00232
00233 ARCH->lockMutex(m_mutex);
00234 ++s->m_refCount;
00235 ARCH->unlockMutex(m_mutex);
00236 return s;
00237 }
00238
00239 void
00240 CArchNetworkWinsock::closeSocket(CArchSocket s)
00241 {
00242 assert(s != NULL);
00243
00244
00245 ARCH->lockMutex(m_mutex);
00246 const bool doClose = (--s->m_refCount == 0);
00247 ARCH->unlockMutex(m_mutex);
00248
00249
00250 if (doClose) {
00251 if (close_winsock(s->m_socket) == SOCKET_ERROR) {
00252
00253 int err = getsockerror_winsock();
00254 ARCH->lockMutex(m_mutex);
00255 ++s->m_refCount;
00256 ARCH->unlockMutex(m_mutex);
00257 throwError(err);
00258 }
00259 WSACloseEvent_winsock(s->m_event);
00260 delete s;
00261 }
00262 }
00263
00264 void
00265 CArchNetworkWinsock::closeSocketForRead(CArchSocket s)
00266 {
00267 assert(s != NULL);
00268
00269 if (shutdown_winsock(s->m_socket, SD_RECEIVE) == SOCKET_ERROR) {
00270 if (getsockerror_winsock() != WSAENOTCONN) {
00271 throwError(getsockerror_winsock());
00272 }
00273 }
00274 }
00275
00276 void
00277 CArchNetworkWinsock::closeSocketForWrite(CArchSocket s)
00278 {
00279 assert(s != NULL);
00280
00281 if (shutdown_winsock(s->m_socket, SD_SEND) == SOCKET_ERROR) {
00282 if (getsockerror_winsock() != WSAENOTCONN) {
00283 throwError(getsockerror_winsock());
00284 }
00285 }
00286 }
00287
00288 void
00289 CArchNetworkWinsock::bindSocket(CArchSocket s, CArchNetAddress addr)
00290 {
00291 assert(s != NULL);
00292 assert(addr != NULL);
00293
00294 if (bind_winsock(s->m_socket, &addr->m_addr, addr->m_len) == SOCKET_ERROR) {
00295 throwError(getsockerror_winsock());
00296 }
00297 }
00298
00299 void
00300 CArchNetworkWinsock::listenOnSocket(CArchSocket s)
00301 {
00302 assert(s != NULL);
00303
00304
00305 if (listen_winsock(s->m_socket, 3) == SOCKET_ERROR) {
00306 throwError(getsockerror_winsock());
00307 }
00308 }
00309
00310 CArchSocket
00311 CArchNetworkWinsock::acceptSocket(CArchSocket s, CArchNetAddress* addr)
00312 {
00313 assert(s != NULL);
00314
00315
00316 CArchSocketImpl* socket = new CArchSocketImpl;
00317 CArchNetAddress tmp = CArchNetAddressImpl::alloc(sizeof(struct sockaddr));
00318
00319
00320 SOCKET fd = accept_winsock(s->m_socket, &tmp->m_addr, &tmp->m_len);
00321 if (fd == INVALID_SOCKET) {
00322 int err = getsockerror_winsock();
00323 delete socket;
00324 free(tmp);
00325 *addr = NULL;
00326 if (err == WSAEWOULDBLOCK) {
00327 return NULL;
00328 }
00329 throwError(err);
00330 }
00331
00332 try {
00333 setBlockingOnSocket(fd, false);
00334 }
00335 catch (...) {
00336 close_winsock(fd);
00337 delete socket;
00338 free(tmp);
00339 *addr = NULL;
00340 throw;
00341 }
00342
00343
00344 socket->m_socket = fd;
00345 socket->m_refCount = 1;
00346 socket->m_event = WSACreateEvent_winsock();
00347 socket->m_pollWrite = true;
00348
00349
00350 if (addr != NULL) {
00351 *addr = ARCH->copyAddr(tmp);
00352 }
00353
00354 free(tmp);
00355 return socket;
00356 }
00357
00358 bool
00359 CArchNetworkWinsock::connectSocket(CArchSocket s, CArchNetAddress addr)
00360 {
00361 assert(s != NULL);
00362 assert(addr != NULL);
00363
00364 if (connect_winsock(s->m_socket, &addr->m_addr,
00365 addr->m_len) == SOCKET_ERROR) {
00366 if (getsockerror_winsock() == WSAEISCONN) {
00367 return true;
00368 }
00369 if (getsockerror_winsock() == WSAEWOULDBLOCK) {
00370 return false;
00371 }
00372 throwError(getsockerror_winsock());
00373 }
00374 return true;
00375 }
00376
00377 int
00378 CArchNetworkWinsock::pollSocket(CPollEntry pe[], int num, double timeout)
00379 {
00380 int i;
00381 DWORD n;
00382
00383
00384 bool canWrite = false;
00385 WSAEVENT* events = (WSAEVENT*)alloca((num + 1) * sizeof(WSAEVENT));
00386 for (i = 0, n = 0; i < num; ++i) {
00387
00388 pe[i].m_revents = 0;
00389
00390
00391 if (pe[i].m_socket == NULL) {
00392 pe[i].m_revents |= kPOLLNVAL;
00393 continue;
00394 }
00395
00396
00397 long socketEvents = 0;
00398 if ((pe[i].m_events & kPOLLIN) != 0) {
00399 socketEvents |= FD_READ | FD_ACCEPT | FD_CLOSE;
00400 }
00401 if ((pe[i].m_events & kPOLLOUT) != 0) {
00402 socketEvents |= FD_WRITE | FD_CONNECT | FD_CLOSE;
00403
00404
00405
00406
00407 if (!pe[i].m_socket->m_pollWrite) {
00408 canWrite = true;
00409 pe[i].m_revents |= kPOLLOUT;
00410 }
00411 }
00412
00413
00414 if (socketEvents == 0) {
00415 continue;
00416 }
00417
00418
00419 WSAEventSelect_winsock(pe[i].m_socket->m_socket,
00420 pe[i].m_socket->m_event, socketEvents);
00421
00422
00423 events[n++] = pe[i].m_socket->m_event;
00424 }
00425
00426
00427 if (n == 0) {
00428 return 0;
00429 }
00430
00431
00432 CArchMultithreadWindows* mt = CArchMultithreadWindows::getInstance();
00433 CArchThread thread = mt->newCurrentThread();
00434 WSAEVENT* unblockEvent = (WSAEVENT*)mt->getNetworkDataForThread(thread);
00435 ARCH->closeThread(thread);
00436 if (unblockEvent == NULL) {
00437 unblockEvent = new WSAEVENT;
00438 m_unblockEvents.push_back(unblockEvent);
00439 *unblockEvent = WSACreateEvent_winsock();
00440 mt->setNetworkDataForCurrentThread(unblockEvent);
00441 }
00442 events[n++] = *unblockEvent;
00443
00444
00445 DWORD t = (timeout < 0.0) ? INFINITE : (DWORD)(1000.0 * timeout);
00446 if (canWrite) {
00447
00448 t = 0;
00449 }
00450
00451
00452 DWORD result = WSAWaitForMultipleEvents_winsock(n, events, FALSE, t, FALSE);
00453
00454
00455 WSAResetEvent_winsock(*unblockEvent);
00456
00457
00458 if (result == WSA_WAIT_FAILED) {
00459 if (getsockerror_winsock() == WSAEINTR) {
00460
00461 ARCH->testCancelThread();
00462 return 0;
00463 }
00464 throwError(getsockerror_winsock());
00465 }
00466 if (result == WSA_WAIT_TIMEOUT && !canWrite) {
00467 return 0;
00468 }
00469 if (result == WSA_WAIT_EVENT_0 + n - 1) {
00470
00471 return 0;
00472 }
00473 for (i = 0, n = 0; i < num; ++i) {
00474
00475 if (pe[i].m_socket == NULL ||
00476 (pe[i].m_events & (kPOLLIN | kPOLLOUT)) == 0) {
00477 continue;
00478 }
00479
00480
00481 WSANETWORKEVENTS info;
00482 if (WSAEnumNetworkEvents_winsock(pe[i].m_socket->m_socket,
00483 pe[i].m_socket->m_event, &info) == SOCKET_ERROR) {
00484 continue;
00485 }
00486 if ((info.lNetworkEvents & FD_READ) != 0) {
00487 pe[i].m_revents |= kPOLLIN;
00488 }
00489 if ((info.lNetworkEvents & FD_ACCEPT) != 0) {
00490 pe[i].m_revents |= kPOLLIN;
00491 }
00492 if ((info.lNetworkEvents & FD_WRITE) != 0) {
00493 pe[i].m_revents |= kPOLLOUT;
00494
00495
00496
00497 pe[i].m_socket->m_pollWrite = false;
00498 }
00499 if ((info.lNetworkEvents & FD_CONNECT) != 0) {
00500 if (info.iErrorCode[FD_CONNECT_BIT] != 0) {
00501 pe[i].m_revents |= kPOLLERR;
00502 }
00503 else {
00504 pe[i].m_revents |= kPOLLOUT;
00505 pe[i].m_socket->m_pollWrite = false;
00506 }
00507 }
00508 if ((info.lNetworkEvents & FD_CLOSE) != 0) {
00509 if (info.iErrorCode[FD_CLOSE_BIT] != 0) {
00510 pe[i].m_revents |= kPOLLERR;
00511 }
00512 else {
00513 if ((pe[i].m_events & kPOLLIN) != 0) {
00514 pe[i].m_revents |= kPOLLIN;
00515 }
00516 if ((pe[i].m_events & kPOLLOUT) != 0) {
00517 pe[i].m_revents |= kPOLLOUT;
00518 }
00519 }
00520 }
00521 if (pe[i].m_revents != 0) {
00522 ++n;
00523 }
00524 }
00525
00526 return (int)n;
00527 }
00528
00529 void
00530 CArchNetworkWinsock::unblockPollSocket(CArchThread thread)
00531 {
00532
00533 CArchMultithreadWindows* mt = CArchMultithreadWindows::getInstance();
00534 WSAEVENT* unblockEvent = (WSAEVENT*)mt->getNetworkDataForThread(thread);
00535 if (unblockEvent != NULL) {
00536 WSASetEvent_winsock(*unblockEvent);
00537 }
00538 }
00539
00540 size_t
00541 CArchNetworkWinsock::readSocket(CArchSocket s, void* buf, size_t len)
00542 {
00543 assert(s != NULL);
00544
00545 int n = recv_winsock(s->m_socket, buf, (int)len, 0);
00546 if (n == SOCKET_ERROR) {
00547 int err = getsockerror_winsock();
00548 if (err == WSAEINTR || err == WSAEWOULDBLOCK) {
00549 return 0;
00550 }
00551 throwError(err);
00552 }
00553 return static_cast<size_t>(n);
00554 }
00555
00556 size_t
00557 CArchNetworkWinsock::writeSocket(CArchSocket s, const void* buf, size_t len)
00558 {
00559 assert(s != NULL);
00560
00561 int n = send_winsock(s->m_socket, buf, (int)len, 0);
00562 if (n == SOCKET_ERROR) {
00563 int err = getsockerror_winsock();
00564 if (err == WSAEINTR) {
00565 return 0;
00566 }
00567 if (err == WSAEWOULDBLOCK) {
00568 s->m_pollWrite = true;
00569 return 0;
00570 }
00571 throwError(err);
00572 }
00573 return static_cast<size_t>(n);
00574 }
00575
00576 void
00577 CArchNetworkWinsock::throwErrorOnSocket(CArchSocket s)
00578 {
00579 assert(s != NULL);
00580
00581
00582 int err = 0;
00583 int size = sizeof(err);
00584 if (getsockopt_winsock(s->m_socket, SOL_SOCKET,
00585 SO_ERROR, &err, &size) == SOCKET_ERROR) {
00586 err = getsockerror_winsock();
00587 }
00588
00589
00590 if (err != 0) {
00591 throwError(err);
00592 }
00593 }
00594
00595 void
00596 CArchNetworkWinsock::setBlockingOnSocket(SOCKET s, bool blocking)
00597 {
00598 assert(s != 0);
00599
00600 int flag = blocking ? 0 : 1;
00601 if (ioctl_winsock(s, FIONBIO, &flag) == SOCKET_ERROR) {
00602 throwError(getsockerror_winsock());
00603 }
00604 }
00605
00606 bool
00607 CArchNetworkWinsock::setNoDelayOnSocket(CArchSocket s, bool noDelay)
00608 {
00609 assert(s != NULL);
00610
00611
00612 BOOL oflag;
00613 int size = sizeof(oflag);
00614 if (getsockopt_winsock(s->m_socket, IPPROTO_TCP,
00615 TCP_NODELAY, &oflag, &size) == SOCKET_ERROR) {
00616 throwError(getsockerror_winsock());
00617 }
00618
00619
00620 BOOL flag = noDelay ? 1 : 0;
00621 size = sizeof(flag);
00622 if (setsockopt_winsock(s->m_socket, IPPROTO_TCP,
00623 TCP_NODELAY, &flag, size) == SOCKET_ERROR) {
00624 throwError(getsockerror_winsock());
00625 }
00626
00627 return (oflag != 0);
00628 }
00629
00630 bool
00631 CArchNetworkWinsock::setReuseAddrOnSocket(CArchSocket s, bool reuse)
00632 {
00633 assert(s != NULL);
00634
00635
00636 BOOL oflag;
00637 int size = sizeof(oflag);
00638 if (getsockopt_winsock(s->m_socket, SOL_SOCKET,
00639 SO_REUSEADDR, &oflag, &size) == SOCKET_ERROR) {
00640 throwError(getsockerror_winsock());
00641 }
00642
00643
00644 BOOL flag = reuse ? 1 : 0;
00645 size = sizeof(flag);
00646 if (setsockopt_winsock(s->m_socket, SOL_SOCKET,
00647 SO_REUSEADDR, &flag, size) == SOCKET_ERROR) {
00648 throwError(getsockerror_winsock());
00649 }
00650
00651 return (oflag != 0);
00652 }
00653
00654 std::string
00655 CArchNetworkWinsock::getHostName()
00656 {
00657 char name[256];
00658 if (gethostname_winsock(name, sizeof(name)) == -1) {
00659 name[0] = '\0';
00660 }
00661 else {
00662 name[sizeof(name) - 1] = '\0';
00663 }
00664 return name;
00665 }
00666
00667 CArchNetAddress
00668 CArchNetworkWinsock::newAnyAddr(EAddressFamily family)
00669 {
00670 CArchNetAddressImpl* addr = NULL;
00671 switch (family) {
00672 case kINET: {
00673 addr = CArchNetAddressImpl::alloc(sizeof(struct sockaddr_in));
00674 struct sockaddr_in* ipAddr = TYPED_ADDR(struct sockaddr_in, addr);
00675 ipAddr->sin_family = AF_INET;
00676 ipAddr->sin_port = 0;
00677 ipAddr->sin_addr.s_addr = INADDR_ANY;
00678 break;
00679 }
00680
00681 default:
00682 assert(0 && "invalid family");
00683 }
00684 return addr;
00685 }
00686
00687 CArchNetAddress
00688 CArchNetworkWinsock::copyAddr(CArchNetAddress addr)
00689 {
00690 assert(addr != NULL);
00691
00692 CArchNetAddressImpl* copy = CArchNetAddressImpl::alloc(addr->m_len);
00693 memcpy(TYPED_ADDR(void, copy), TYPED_ADDR(void, addr), addr->m_len);
00694 return copy;
00695 }
00696
00697 CArchNetAddress
00698 CArchNetworkWinsock::nameToAddr(const std::string& name)
00699 {
00700
00701 CArchNetAddressImpl* addr = NULL;
00702
00703
00704 struct sockaddr_in inaddr;
00705 memset(&inaddr, 0, sizeof(inaddr));
00706 inaddr.sin_family = AF_INET;
00707 inaddr.sin_port = 0;
00708 inaddr.sin_addr.s_addr = inet_addr_winsock(name.c_str());
00709 if (inaddr.sin_addr.s_addr != INADDR_NONE) {
00710
00711 addr = CArchNetAddressImpl::alloc(sizeof(struct sockaddr_in));
00712 memcpy(TYPED_ADDR(void, addr), &inaddr, addr->m_len);
00713 }
00714
00715 else {
00716
00717 struct hostent* info = gethostbyname_winsock(name.c_str());
00718 if (info == NULL) {
00719 throwNameError(getsockerror_winsock());
00720 }
00721
00722
00723 if (info->h_addrtype == AF_INET) {
00724 addr = CArchNetAddressImpl::alloc(sizeof(struct sockaddr_in));
00725 memcpy(&inaddr.sin_addr, info->h_addr_list[0],
00726 sizeof(inaddr.sin_addr));
00727 memcpy(TYPED_ADDR(void, addr), &inaddr, addr->m_len);
00728 }
00729 else {
00730 throw XArchNetworkNameUnsupported(
00731 "The requested name is valid but "
00732 "does not have a supported address family");
00733 }
00734 }
00735
00736 return addr;
00737 }
00738
00739 void
00740 CArchNetworkWinsock::closeAddr(CArchNetAddress addr)
00741 {
00742 assert(addr != NULL);
00743
00744 free(addr);
00745 }
00746
00747 std::string
00748 CArchNetworkWinsock::addrToName(CArchNetAddress addr)
00749 {
00750 assert(addr != NULL);
00751
00752
00753 struct hostent* info = gethostbyaddr_winsock(
00754 reinterpret_cast<const char FAR*>(&addr->m_addr),
00755 addr->m_len, addr->m_addr.sa_family);
00756 if (info == NULL) {
00757 throwNameError(getsockerror_winsock());
00758 }
00759
00760
00761 return info->h_name;
00762 }
00763
00764 std::string
00765 CArchNetworkWinsock::addrToString(CArchNetAddress addr)
00766 {
00767 assert(addr != NULL);
00768
00769 switch (getAddrFamily(addr)) {
00770 case kINET: {
00771 struct sockaddr_in* ipAddr =
00772 reinterpret_cast<struct sockaddr_in*>(&addr->m_addr);
00773 return inet_ntoa_winsock(ipAddr->sin_addr);
00774 }
00775
00776 default:
00777 assert(0 && "unknown address family");
00778 return "";
00779 }
00780 }
00781
00782 IArchNetwork::EAddressFamily
00783 CArchNetworkWinsock::getAddrFamily(CArchNetAddress addr)
00784 {
00785 assert(addr != NULL);
00786
00787 switch (addr->m_addr.sa_family) {
00788 case AF_INET:
00789 return kINET;
00790
00791 default:
00792 return kUNKNOWN;
00793 }
00794 }
00795
00796 void
00797 CArchNetworkWinsock::setAddrPort(CArchNetAddress addr, int port)
00798 {
00799 assert(addr != NULL);
00800
00801 switch (getAddrFamily(addr)) {
00802 case kINET: {
00803 struct sockaddr_in* ipAddr =
00804 reinterpret_cast<struct sockaddr_in*>(&addr->m_addr);
00805 ipAddr->sin_port = htons_winsock(static_cast<u_short>(port));
00806 break;
00807 }
00808
00809 default:
00810 assert(0 && "unknown address family");
00811 break;
00812 }
00813 }
00814
00815 int
00816 CArchNetworkWinsock::getAddrPort(CArchNetAddress addr)
00817 {
00818 assert(addr != NULL);
00819
00820 switch (getAddrFamily(addr)) {
00821 case kINET: {
00822 struct sockaddr_in* ipAddr =
00823 reinterpret_cast<struct sockaddr_in*>(&addr->m_addr);
00824 return ntohs_winsock(ipAddr->sin_port);
00825 }
00826
00827 default:
00828 assert(0 && "unknown address family");
00829 return 0;
00830 }
00831 }
00832
00833 bool
00834 CArchNetworkWinsock::isAnyAddr(CArchNetAddress addr)
00835 {
00836 assert(addr != NULL);
00837
00838 switch (getAddrFamily(addr)) {
00839 case kINET: {
00840 struct sockaddr_in* ipAddr =
00841 reinterpret_cast<struct sockaddr_in*>(&addr->m_addr);
00842 return (addr->m_len == sizeof(struct sockaddr_in) &&
00843 ipAddr->sin_addr.s_addr == INADDR_ANY);
00844 }
00845
00846 default:
00847 assert(0 && "unknown address family");
00848 return true;
00849 }
00850 }
00851
00852 bool
00853 CArchNetworkWinsock::isEqualAddr(CArchNetAddress a, CArchNetAddress b)
00854 {
00855 return (a == b || (a->m_len == b->m_len &&
00856 memcmp(&a->m_addr, &b->m_addr, a->m_len) == 0));
00857 }
00858
00859 void
00860 CArchNetworkWinsock::throwError(int err)
00861 {
00862 switch (err) {
00863 case WSAEACCES:
00864 throw XArchNetworkAccess(new XArchEvalWinsock(err));
00865
00866 case WSAEMFILE:
00867 case WSAENOBUFS:
00868 case WSAENETDOWN:
00869 throw XArchNetworkResource(new XArchEvalWinsock(err));
00870
00871 case WSAEPROTOTYPE:
00872 case WSAEPROTONOSUPPORT:
00873 case WSAEAFNOSUPPORT:
00874 case WSAEPFNOSUPPORT:
00875 case WSAESOCKTNOSUPPORT:
00876 case WSAEINVAL:
00877 case WSAENOPROTOOPT:
00878 case WSAEOPNOTSUPP:
00879 case WSAESHUTDOWN:
00880 case WSANOTINITIALISED:
00881 case WSAVERNOTSUPPORTED:
00882 case WSASYSNOTREADY:
00883 throw XArchNetworkSupport(new XArchEvalWinsock(err));
00884
00885 case WSAEADDRNOTAVAIL:
00886 throw XArchNetworkNoAddress(new XArchEvalWinsock(err));
00887
00888 case WSAEADDRINUSE:
00889 throw XArchNetworkAddressInUse(new XArchEvalWinsock(err));
00890
00891 case WSAEHOSTUNREACH:
00892 case WSAENETUNREACH:
00893 throw XArchNetworkNoRoute(new XArchEvalWinsock(err));
00894
00895 case WSAENOTCONN:
00896 throw XArchNetworkNotConnected(new XArchEvalWinsock(err));
00897
00898 case WSAEDISCON:
00899 throw XArchNetworkShutdown(new XArchEvalWinsock(err));
00900
00901 case WSAENETRESET:
00902 case WSAECONNABORTED:
00903 case WSAECONNRESET:
00904 throw XArchNetworkDisconnected(new XArchEvalWinsock(err));
00905
00906 case WSAECONNREFUSED:
00907 throw XArchNetworkConnectionRefused(new XArchEvalWinsock(err));
00908
00909 case WSAEHOSTDOWN:
00910 case WSAETIMEDOUT:
00911 throw XArchNetworkTimedOut(new XArchEvalWinsock(err));
00912
00913 case WSAHOST_NOT_FOUND:
00914 throw XArchNetworkNameUnknown(new XArchEvalWinsock(err));
00915
00916 case WSANO_DATA:
00917 throw XArchNetworkNameNoAddress(new XArchEvalWinsock(err));
00918
00919 case WSANO_RECOVERY:
00920 throw XArchNetworkNameFailure(new XArchEvalWinsock(err));
00921
00922 case WSATRY_AGAIN:
00923 throw XArchNetworkNameUnavailable(new XArchEvalWinsock(err));
00924
00925 default:
00926 throw XArchNetwork(new XArchEvalWinsock(err));
00927 }
00928 }
00929
00930 void
00931 CArchNetworkWinsock::throwNameError(int err)
00932 {
00933 switch (err) {
00934 case WSAHOST_NOT_FOUND:
00935 throw XArchNetworkNameUnknown(new XArchEvalWinsock(err));
00936
00937 case WSANO_DATA:
00938 throw XArchNetworkNameNoAddress(new XArchEvalWinsock(err));
00939
00940 case WSANO_RECOVERY:
00941 throw XArchNetworkNameFailure(new XArchEvalWinsock(err));
00942
00943 case WSATRY_AGAIN:
00944 throw XArchNetworkNameUnavailable(new XArchEvalWinsock(err));
00945
00946 default:
00947 throw XArchNetworkName(new XArchEvalWinsock(err));
00948 }
00949 }