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