00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015 #include "CArchNetworkBSD.h"
00016 #include "CArch.h"
00017 #include "CArchMultithreadPosix.h"
00018 #include "XArchUnix.h"
00019 #if HAVE_UNISTD_H
00020 # include <unistd.h>
00021 #endif
00022 #include <netinet/in.h>
00023 #include <netdb.h>
00024 #if !defined(TCP_NODELAY)
00025 # include <netinet/tcp.h>
00026 #endif
00027 #include <arpa/inet.h>
00028 #include <fcntl.h>
00029 #include <errno.h>
00030 #include <string.h>
00031
00032 #if HAVE_POLL
00033 # include <poll.h>
00034 #else
00035 # if HAVE_SYS_SELECT_H
00036 # include <sys/select.h>
00037 # endif
00038 # if HAVE_SYS_TIME_H
00039 # include <sys/time.h>
00040 # endif
00041 #endif
00042
00043 #if !HAVE_INET_ATON
00044 # include <stdio.h>
00045 #endif
00046
00047 static const int s_family[] = {
00048 PF_UNSPEC,
00049 PF_INET
00050 };
00051 static const int s_type[] = {
00052 SOCK_DGRAM,
00053 SOCK_STREAM
00054 };
00055
00056 #if !HAVE_INET_ATON
00057
00058
00059 static
00060 in_addr_t
00061 inet_aton(const char* cp, struct in_addr* inp)
00062 {
00063 unsigned int a, b, c, d;
00064 if (sscanf(cp, "%u.%u.%u.%u", &a, &b, &c, &d) != 4) {
00065 return 0;
00066 }
00067 if (a >= 256 || b >= 256 || c >= 256 || d >= 256) {
00068 return 0;
00069 }
00070 unsigned char* incp = (unsigned char*)inp;
00071 incp[0] = (unsigned char)(a & 0xffu);
00072 incp[1] = (unsigned char)(b & 0xffu);
00073 incp[2] = (unsigned char)(c & 0xffu);
00074 incp[3] = (unsigned char)(d & 0xffu);
00075 return inp->s_addr;
00076 }
00077 #endif
00078
00079
00080
00081
00082
00083 CArchNetworkBSD::CArchNetworkBSD()
00084 {
00085
00086 m_mutex = ARCH->newMutex();
00087 }
00088
00089 CArchNetworkBSD::~CArchNetworkBSD()
00090 {
00091 ARCH->closeMutex(m_mutex);
00092 }
00093
00094 CArchSocket
00095 CArchNetworkBSD::newSocket(EAddressFamily family, ESocketType type)
00096 {
00097
00098 int fd = socket(s_family[family], s_type[type], 0);
00099 if (fd == -1) {
00100 throwError(errno);
00101 }
00102 try {
00103 setBlockingOnSocket(fd, false);
00104 }
00105 catch (...) {
00106 close(fd);
00107 throw;
00108 }
00109
00110
00111 CArchSocketImpl* newSocket = new CArchSocketImpl;
00112 newSocket->m_fd = fd;
00113 newSocket->m_refCount = 1;
00114 return newSocket;
00115 }
00116
00117 CArchSocket
00118 CArchNetworkBSD::copySocket(CArchSocket s)
00119 {
00120 assert(s != NULL);
00121
00122
00123 ARCH->lockMutex(m_mutex);
00124 ++s->m_refCount;
00125 ARCH->unlockMutex(m_mutex);
00126 return s;
00127 }
00128
00129 void
00130 CArchNetworkBSD::closeSocket(CArchSocket s)
00131 {
00132 assert(s != NULL);
00133
00134
00135 ARCH->lockMutex(m_mutex);
00136 const bool doClose = (--s->m_refCount == 0);
00137 ARCH->unlockMutex(m_mutex);
00138
00139
00140 if (doClose) {
00141 if (close(s->m_fd) == -1) {
00142
00143 int err = errno;
00144 ARCH->lockMutex(m_mutex);
00145 ++s->m_refCount;
00146 ARCH->unlockMutex(m_mutex);
00147 throwError(err);
00148 }
00149 delete s;
00150 }
00151 }
00152
00153 void
00154 CArchNetworkBSD::closeSocketForRead(CArchSocket s)
00155 {
00156 assert(s != NULL);
00157
00158 if (shutdown(s->m_fd, 0) == -1) {
00159 if (errno != ENOTCONN) {
00160 throwError(errno);
00161 }
00162 }
00163 }
00164
00165 void
00166 CArchNetworkBSD::closeSocketForWrite(CArchSocket s)
00167 {
00168 assert(s != NULL);
00169
00170 if (shutdown(s->m_fd, 1) == -1) {
00171 if (errno != ENOTCONN) {
00172 throwError(errno);
00173 }
00174 }
00175 }
00176
00177 void
00178 CArchNetworkBSD::bindSocket(CArchSocket s, CArchNetAddress addr)
00179 {
00180 assert(s != NULL);
00181 assert(addr != NULL);
00182
00183 if (bind(s->m_fd, &addr->m_addr, addr->m_len) == -1) {
00184 throwError(errno);
00185 }
00186 }
00187
00188 void
00189 CArchNetworkBSD::listenOnSocket(CArchSocket s)
00190 {
00191 assert(s != NULL);
00192
00193
00194 if (listen(s->m_fd, 3) == -1) {
00195 throwError(errno);
00196 }
00197 }
00198
00199 CArchSocket
00200 CArchNetworkBSD::acceptSocket(CArchSocket s, CArchNetAddress* addr)
00201 {
00202 assert(s != NULL);
00203
00204
00205 CArchNetAddress dummy;
00206 if (addr == NULL) {
00207 addr = &dummy;
00208 }
00209
00210
00211 CArchSocketImpl* newSocket = new CArchSocketImpl;
00212 *addr = new CArchNetAddressImpl;
00213
00214
00215 ACCEPT_TYPE_ARG3 len = (ACCEPT_TYPE_ARG3)((*addr)->m_len);
00216 int fd = accept(s->m_fd, &(*addr)->m_addr, &len);
00217 (*addr)->m_len = (socklen_t)len;
00218 if (fd == -1) {
00219 int err = errno;
00220 delete newSocket;
00221 delete *addr;
00222 *addr = NULL;
00223 if (err == EAGAIN) {
00224 return NULL;
00225 }
00226 throwError(err);
00227 }
00228
00229 try {
00230 setBlockingOnSocket(fd, false);
00231 }
00232 catch (...) {
00233 close(fd);
00234 delete newSocket;
00235 delete *addr;
00236 *addr = NULL;
00237 throw;
00238 }
00239
00240
00241 newSocket->m_fd = fd;
00242 newSocket->m_refCount = 1;
00243
00244
00245 if (addr == &dummy) {
00246 ARCH->closeAddr(dummy);
00247 }
00248
00249 return newSocket;
00250 }
00251
00252 bool
00253 CArchNetworkBSD::connectSocket(CArchSocket s, CArchNetAddress addr)
00254 {
00255 assert(s != NULL);
00256 assert(addr != NULL);
00257
00258 if (connect(s->m_fd, &addr->m_addr, addr->m_len) == -1) {
00259 if (errno == EISCONN) {
00260 return true;
00261 }
00262 if (errno == EINPROGRESS) {
00263 return false;
00264 }
00265 throwError(errno);
00266 }
00267 return true;
00268 }
00269
00270 #if HAVE_POLL
00271
00272 int
00273 CArchNetworkBSD::pollSocket(CPollEntry pe[], int num, double timeout)
00274 {
00275 assert(pe != NULL || num == 0);
00276
00277
00278 if (num == 0) {
00279 if (timeout > 0.0) {
00280 ARCH->sleep(timeout);
00281 }
00282 return 0;
00283 }
00284
00285
00286 struct pollfd* pfd = new struct pollfd[1 + num];
00287
00288
00289 for (int i = 0; i < num; ++i) {
00290 pfd[i].fd = (pe[i].m_socket == NULL) ? -1 : pe[i].m_socket->m_fd;
00291 pfd[i].events = 0;
00292 if ((pe[i].m_events & kPOLLIN) != 0) {
00293 pfd[i].events |= POLLIN;
00294 }
00295 if ((pe[i].m_events & kPOLLOUT) != 0) {
00296 pfd[i].events |= POLLOUT;
00297 }
00298 }
00299 int n = num;
00300
00301
00302 const int* unblockPipe = getUnblockPipe();
00303 if (unblockPipe != NULL) {
00304 pfd[n].fd = unblockPipe[0];
00305 pfd[n].events = POLLIN;
00306 ++n;
00307 }
00308
00309
00310 int t = (timeout < 0.0) ? -1 : static_cast<int>(1000.0 * timeout);
00311
00312
00313 n = poll(pfd, n, t);
00314
00315
00316 if (n > 0 && unblockPipe != NULL && (pfd[num].revents & POLLIN) != 0) {
00317
00318 char dummy[100];
00319 int ignore;
00320
00321 do {
00322 ignore = read(unblockPipe[0], dummy, sizeof(dummy));
00323 } while (errno != EAGAIN);
00324
00325
00326 --n;
00327 }
00328
00329
00330 if (n == -1) {
00331 if (errno == EINTR) {
00332
00333 ARCH->testCancelThread();
00334 delete[] pfd;
00335 return 0;
00336 }
00337 delete[] pfd;
00338 throwError(errno);
00339 }
00340
00341
00342 for (int i = 0; i < num; ++i) {
00343 pe[i].m_revents = 0;
00344 if ((pfd[i].revents & POLLIN) != 0) {
00345 pe[i].m_revents |= kPOLLIN;
00346 }
00347 if ((pfd[i].revents & POLLOUT) != 0) {
00348 pe[i].m_revents |= kPOLLOUT;
00349 }
00350 if ((pfd[i].revents & POLLERR) != 0) {
00351 pe[i].m_revents |= kPOLLERR;
00352 }
00353 if ((pfd[i].revents & POLLNVAL) != 0) {
00354 pe[i].m_revents |= kPOLLNVAL;
00355 }
00356 }
00357
00358 delete[] pfd;
00359 return n;
00360 }
00361
00362 #else
00363
00364 int
00365 CArchNetworkBSD::pollSocket(CPollEntry pe[], int num, double timeout)
00366 {
00367 int i, n;
00368
00369
00370 n = 0;
00371 fd_set readSet, writeSet, errSet;
00372 fd_set* readSetP = NULL;
00373 fd_set* writeSetP = NULL;
00374 fd_set* errSetP = NULL;
00375 FD_ZERO(&readSet);
00376 FD_ZERO(&writeSet);
00377 FD_ZERO(&errSet);
00378 for (i = 0; i < num; ++i) {
00379
00380 pe[i].m_revents = 0;
00381
00382
00383 if (pe[i].m_socket == NULL) {
00384 pe[i].m_revents |= kPOLLNVAL;
00385 continue;
00386 }
00387
00388 int fdi = pe[i].m_socket->m_fd;
00389 if (pe[i].m_events & kPOLLIN) {
00390 FD_SET(pe[i].m_socket->m_fd, &readSet);
00391 readSetP = &readSet;
00392 if (fdi > n) {
00393 n = fdi;
00394 }
00395 }
00396 if (pe[i].m_events & kPOLLOUT) {
00397 FD_SET(pe[i].m_socket->m_fd, &writeSet);
00398 writeSetP = &writeSet;
00399 if (fdi > n) {
00400 n = fdi;
00401 }
00402 }
00403 if (true) {
00404 FD_SET(pe[i].m_socket->m_fd, &errSet);
00405 errSetP = &errSet;
00406 if (fdi > n) {
00407 n = fdi;
00408 }
00409 }
00410 }
00411
00412
00413 const int* unblockPipe = getUnblockPipe();
00414 if (unblockPipe != NULL) {
00415 FD_SET(unblockPipe[0], &readSet);
00416 readSetP = &readSet;
00417 if (unblockPipe[0] > n) {
00418 n = unblockPipe[0];
00419 }
00420 }
00421
00422
00423 if (n == 0 && timeout < 0.0) {
00424 timeout = 0.0;
00425 }
00426
00427
00428 struct timeval timeout2;
00429 struct timeval* timeout2P;
00430 if (timeout < 0.0) {
00431 timeout2P = NULL;
00432 }
00433 else {
00434 timeout2P = &timeout2;
00435 timeout2.tv_sec = static_cast<int>(timeout);
00436 timeout2.tv_usec = static_cast<int>(1.0e+6 *
00437 (timeout - timeout2.tv_sec));
00438 }
00439
00440
00441 n = select((SELECT_TYPE_ARG1) n + 1,
00442 SELECT_TYPE_ARG234 readSetP,
00443 SELECT_TYPE_ARG234 writeSetP,
00444 SELECT_TYPE_ARG234 errSetP,
00445 SELECT_TYPE_ARG5 timeout2P);
00446
00447
00448 if (n > 0 && unblockPipe != NULL && FD_ISSET(unblockPipe[0], &readSet)) {
00449
00450 char dummy[100];
00451 do {
00452 read(unblockPipe[0], dummy, sizeof(dummy));
00453 } while (errno != EAGAIN);
00454 }
00455
00456
00457 if (n == -1) {
00458 if (errno == EINTR) {
00459
00460 ARCH->testCancelThread();
00461 return 0;
00462 }
00463 throwError(errno);
00464 }
00465 n = 0;
00466 for (i = 0; i < num; ++i) {
00467 if (pe[i].m_socket != NULL) {
00468 if (FD_ISSET(pe[i].m_socket->m_fd, &readSet)) {
00469 pe[i].m_revents |= kPOLLIN;
00470 }
00471 if (FD_ISSET(pe[i].m_socket->m_fd, &writeSet)) {
00472 pe[i].m_revents |= kPOLLOUT;
00473 }
00474 if (FD_ISSET(pe[i].m_socket->m_fd, &errSet)) {
00475 pe[i].m_revents |= kPOLLERR;
00476 }
00477 }
00478 if (pe[i].m_revents != 0) {
00479 ++n;
00480 }
00481 }
00482
00483 return n;
00484 }
00485
00486 #endif
00487
00488 void
00489 CArchNetworkBSD::unblockPollSocket(CArchThread thread)
00490 {
00491 const int* unblockPipe = getUnblockPipeForThread(thread);
00492 if (unblockPipe != NULL) {
00493 char dummy = 0;
00494 int ignore;
00495
00496 ignore = write(unblockPipe[1], &dummy, 1);
00497 }
00498 }
00499
00500 size_t
00501 CArchNetworkBSD::readSocket(CArchSocket s, void* buf, size_t len)
00502 {
00503 assert(s != NULL);
00504
00505 ssize_t n = read(s->m_fd, buf, len);
00506 if (n == -1) {
00507 if (errno == EINTR || errno == EAGAIN) {
00508 return 0;
00509 }
00510 throwError(errno);
00511 }
00512 return n;
00513 }
00514
00515 size_t
00516 CArchNetworkBSD::writeSocket(CArchSocket s, const void* buf, size_t len)
00517 {
00518 assert(s != NULL);
00519
00520 ssize_t n = write(s->m_fd, buf, len);
00521 if (n == -1) {
00522 if (errno == EINTR || errno == EAGAIN) {
00523 return 0;
00524 }
00525 throwError(errno);
00526 }
00527 return n;
00528 }
00529
00530 void
00531 CArchNetworkBSD::throwErrorOnSocket(CArchSocket s)
00532 {
00533 assert(s != NULL);
00534
00535
00536 int err = 0;
00537 socklen_t size = (socklen_t)sizeof(err);
00538 if (getsockopt(s->m_fd, SOL_SOCKET, SO_ERROR,
00539 (optval_t*)&err, &size) == -1) {
00540 err = errno;
00541 }
00542
00543
00544 if (err != 0) {
00545 throwError(err);
00546 }
00547 }
00548
00549 void
00550 CArchNetworkBSD::setBlockingOnSocket(int fd, bool blocking)
00551 {
00552 assert(fd != -1);
00553
00554 int mode = fcntl(fd, F_GETFL, 0);
00555 if (mode == -1) {
00556 throwError(errno);
00557 }
00558 if (blocking) {
00559 mode &= ~O_NONBLOCK;
00560 }
00561 else {
00562 mode |= O_NONBLOCK;
00563 }
00564 if (fcntl(fd, F_SETFL, mode) == -1) {
00565 throwError(errno);
00566 }
00567 }
00568
00569 bool
00570 CArchNetworkBSD::setNoDelayOnSocket(CArchSocket s, bool noDelay)
00571 {
00572 assert(s != NULL);
00573
00574
00575 int oflag;
00576 socklen_t size = (socklen_t)sizeof(oflag);
00577 if (getsockopt(s->m_fd, IPPROTO_TCP, TCP_NODELAY,
00578 (optval_t*)&oflag, &size) == -1) {
00579 throwError(errno);
00580 }
00581
00582 int flag = noDelay ? 1 : 0;
00583 size = (socklen_t)sizeof(flag);
00584 if (setsockopt(s->m_fd, IPPROTO_TCP, TCP_NODELAY,
00585 (optval_t*)&flag, size) == -1) {
00586 throwError(errno);
00587 }
00588
00589 return (oflag != 0);
00590 }
00591
00592 bool
00593 CArchNetworkBSD::setReuseAddrOnSocket(CArchSocket s, bool reuse)
00594 {
00595 assert(s != NULL);
00596
00597
00598 int oflag;
00599 socklen_t size = (socklen_t)sizeof(oflag);
00600 if (getsockopt(s->m_fd, SOL_SOCKET, SO_REUSEADDR,
00601 (optval_t*)&oflag, &size) == -1) {
00602 throwError(errno);
00603 }
00604
00605 int flag = reuse ? 1 : 0;
00606 size = (socklen_t)sizeof(flag);
00607 if (setsockopt(s->m_fd, SOL_SOCKET, SO_REUSEADDR,
00608 (optval_t*)&flag, size) == -1) {
00609 throwError(errno);
00610 }
00611
00612 return (oflag != 0);
00613 }
00614
00615 std::string
00616 CArchNetworkBSD::getHostName()
00617 {
00618 char name[256];
00619 if (gethostname(name, sizeof(name)) == -1) {
00620 name[0] = '\0';
00621 }
00622 else {
00623 name[sizeof(name) - 1] = '\0';
00624 }
00625 return name;
00626 }
00627
00628 CArchNetAddress
00629 CArchNetworkBSD::newAnyAddr(EAddressFamily family)
00630 {
00631
00632 CArchNetAddressImpl* addr = new CArchNetAddressImpl;
00633
00634
00635 switch (family) {
00636 case kINET: {
00637 struct sockaddr_in* ipAddr =
00638 reinterpret_cast<struct sockaddr_in*>(&addr->m_addr);
00639 ipAddr->sin_family = AF_INET;
00640 ipAddr->sin_port = 0;
00641 ipAddr->sin_addr.s_addr = INADDR_ANY;
00642 addr->m_len = (socklen_t)sizeof(struct sockaddr_in);
00643 break;
00644 }
00645
00646 default:
00647 delete addr;
00648 assert(0 && "invalid family");
00649 }
00650
00651 return addr;
00652 }
00653
00654 CArchNetAddress
00655 CArchNetworkBSD::copyAddr(CArchNetAddress addr)
00656 {
00657 assert(addr != NULL);
00658
00659
00660 return new CArchNetAddressImpl(*addr);
00661 }
00662
00663 CArchNetAddress
00664 CArchNetworkBSD::nameToAddr(const std::string& name)
00665 {
00666
00667 CArchNetAddressImpl* addr = new CArchNetAddressImpl;
00668
00669
00670 struct sockaddr_in inaddr;
00671 memset(&inaddr, 0, sizeof(inaddr));
00672 if (inet_aton(name.c_str(), &inaddr.sin_addr) != 0) {
00673
00674 addr->m_len = (socklen_t)sizeof(struct sockaddr_in);
00675 inaddr.sin_family = AF_INET;
00676 inaddr.sin_port = 0;
00677 memcpy(&addr->m_addr, &inaddr, addr->m_len);
00678 }
00679
00680 else {
00681
00682 ARCH->lockMutex(m_mutex);
00683 struct hostent* info = gethostbyname(name.c_str());
00684 if (info == NULL) {
00685 ARCH->unlockMutex(m_mutex);
00686 delete addr;
00687 throwNameError(h_errno);
00688 }
00689
00690
00691 if (info->h_addrtype == AF_INET) {
00692 addr->m_len = (socklen_t)sizeof(struct sockaddr_in);
00693 inaddr.sin_family = info->h_addrtype;
00694 inaddr.sin_port = 0;
00695 memcpy(&inaddr.sin_addr, info->h_addr_list[0],
00696 sizeof(inaddr.sin_addr));
00697 memcpy(&addr->m_addr, &inaddr, addr->m_len);
00698 }
00699 else {
00700 ARCH->unlockMutex(m_mutex);
00701 delete addr;
00702 throw XArchNetworkNameUnsupported(
00703 "The requested name is valid but "
00704 "does not have a supported address family");
00705 }
00706
00707
00708 ARCH->unlockMutex(m_mutex);
00709 }
00710
00711 return addr;
00712 }
00713
00714 void
00715 CArchNetworkBSD::closeAddr(CArchNetAddress addr)
00716 {
00717 assert(addr != NULL);
00718
00719 delete addr;
00720 }
00721
00722 std::string
00723 CArchNetworkBSD::addrToName(CArchNetAddress addr)
00724 {
00725 assert(addr != NULL);
00726
00727
00728 ARCH->lockMutex(m_mutex);
00729 struct hostent* info = gethostbyaddr(
00730 reinterpret_cast<const char*>(&addr->m_addr),
00731 addr->m_len, addr->m_addr.sa_family);
00732 if (info == NULL) {
00733 ARCH->unlockMutex(m_mutex);
00734 throwNameError(h_errno);
00735 }
00736
00737
00738 std::string name = info->h_name;
00739
00740
00741 ARCH->unlockMutex(m_mutex);
00742
00743 return name;
00744 }
00745
00746 std::string
00747 CArchNetworkBSD::addrToString(CArchNetAddress addr)
00748 {
00749 assert(addr != NULL);
00750
00751 switch (getAddrFamily(addr)) {
00752 case kINET: {
00753 struct sockaddr_in* ipAddr =
00754 reinterpret_cast<struct sockaddr_in*>(&addr->m_addr);
00755 ARCH->lockMutex(m_mutex);
00756 std::string s = inet_ntoa(ipAddr->sin_addr);
00757 ARCH->unlockMutex(m_mutex);
00758 return s;
00759 }
00760
00761 default:
00762 assert(0 && "unknown address family");
00763 return "";
00764 }
00765 }
00766
00767 IArchNetwork::EAddressFamily
00768 CArchNetworkBSD::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 CArchNetworkBSD::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(port);
00791 break;
00792 }
00793
00794 default:
00795 assert(0 && "unknown address family");
00796 break;
00797 }
00798 }
00799
00800 int
00801 CArchNetworkBSD::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(ipAddr->sin_port);
00810 }
00811
00812 default:
00813 assert(0 && "unknown address family");
00814 return 0;
00815 }
00816 }
00817
00818 bool
00819 CArchNetworkBSD::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 (ipAddr->sin_addr.s_addr == INADDR_ANY &&
00828 addr->m_len == (socklen_t)sizeof(struct sockaddr_in));
00829 }
00830
00831 default:
00832 assert(0 && "unknown address family");
00833 return true;
00834 }
00835 }
00836
00837 bool
00838 CArchNetworkBSD::isEqualAddr(CArchNetAddress a, CArchNetAddress b)
00839 {
00840 return (a->m_len == b->m_len &&
00841 memcmp(&a->m_addr, &b->m_addr, a->m_len) == 0);
00842 }
00843
00844 const int*
00845 CArchNetworkBSD::getUnblockPipe()
00846 {
00847 CArchMultithreadPosix* mt = CArchMultithreadPosix::getInstance();
00848 CArchThread thread = mt->newCurrentThread();
00849 const int* p = getUnblockPipeForThread(thread);
00850 ARCH->closeThread(thread);
00851 return p;
00852 }
00853
00854 const int*
00855 CArchNetworkBSD::getUnblockPipeForThread(CArchThread thread)
00856 {
00857 CArchMultithreadPosix* mt = CArchMultithreadPosix::getInstance();
00858 int* unblockPipe = (int*)mt->getNetworkDataForThread(thread);
00859 if (unblockPipe == NULL) {
00860 unblockPipe = new int[2];
00861 if (pipe(unblockPipe) != -1) {
00862 try {
00863 setBlockingOnSocket(unblockPipe[0], false);
00864 mt->setNetworkDataForCurrentThread(unblockPipe);
00865 }
00866 catch (...) {
00867 delete[] unblockPipe;
00868 unblockPipe = NULL;
00869 }
00870 }
00871 else {
00872 delete[] unblockPipe;
00873 unblockPipe = NULL;
00874 }
00875 }
00876 return unblockPipe;
00877 }
00878
00879 void
00880 CArchNetworkBSD::throwError(int err)
00881 {
00882 switch (err) {
00883 case EINTR:
00884 ARCH->testCancelThread();
00885 throw XArchNetworkInterrupted(new XArchEvalUnix(err));
00886
00887 case EACCES:
00888 case EPERM:
00889 throw XArchNetworkAccess(new XArchEvalUnix(err));
00890
00891 case ENFILE:
00892 case EMFILE:
00893 case ENODEV:
00894 case ENOBUFS:
00895 case ENOMEM:
00896 case ENETDOWN:
00897 #if defined(ENOSR)
00898 case ENOSR:
00899 #endif
00900 throw XArchNetworkResource(new XArchEvalUnix(err));
00901
00902 case EPROTOTYPE:
00903 case EPROTONOSUPPORT:
00904 case EAFNOSUPPORT:
00905 case EPFNOSUPPORT:
00906 case ESOCKTNOSUPPORT:
00907 case EINVAL:
00908 case ENOPROTOOPT:
00909 case EOPNOTSUPP:
00910 case ESHUTDOWN:
00911 #if defined(ENOPKG)
00912 case ENOPKG:
00913 #endif
00914 throw XArchNetworkSupport(new XArchEvalUnix(err));
00915
00916 case EIO:
00917 throw XArchNetworkIO(new XArchEvalUnix(err));
00918
00919 case EADDRNOTAVAIL:
00920 throw XArchNetworkNoAddress(new XArchEvalUnix(err));
00921
00922 case EADDRINUSE:
00923 throw XArchNetworkAddressInUse(new XArchEvalUnix(err));
00924
00925 case EHOSTUNREACH:
00926 case ENETUNREACH:
00927 throw XArchNetworkNoRoute(new XArchEvalUnix(err));
00928
00929 case ENOTCONN:
00930 throw XArchNetworkNotConnected(new XArchEvalUnix(err));
00931
00932 case EPIPE:
00933 throw XArchNetworkShutdown(new XArchEvalUnix(err));
00934
00935 case ECONNABORTED:
00936 case ECONNRESET:
00937 throw XArchNetworkDisconnected(new XArchEvalUnix(err));
00938
00939 case ECONNREFUSED:
00940 throw XArchNetworkConnectionRefused(new XArchEvalUnix(err));
00941
00942 case EHOSTDOWN:
00943 case ETIMEDOUT:
00944 throw XArchNetworkTimedOut(new XArchEvalUnix(err));
00945
00946 default:
00947 throw XArchNetwork(new XArchEvalUnix(err));
00948 }
00949 }
00950
00951 void
00952 CArchNetworkBSD::throwNameError(int err)
00953 {
00954 static const char* s_msg[] = {
00955 "The specified host is unknown",
00956 "The requested name is valid but does not have an IP address",
00957 "A non-recoverable name server error occurred",
00958 "A temporary error occurred on an authoritative name server",
00959 "An unknown name server error occurred"
00960 };
00961
00962 switch (err) {
00963 case HOST_NOT_FOUND:
00964 throw XArchNetworkNameUnknown(s_msg[0]);
00965
00966 case NO_DATA:
00967 throw XArchNetworkNameNoAddress(s_msg[1]);
00968
00969 case NO_RECOVERY:
00970 throw XArchNetworkNameFailure(s_msg[2]);
00971
00972 case TRY_AGAIN:
00973 throw XArchNetworkNameUnavailable(s_msg[3]);
00974
00975 default:
00976 throw XArchNetworkName(s_msg[4]);
00977 }
00978 }