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