00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035 #include "wavesock.h"
00036
00037
00038 #include <fcntl.h>
00039
00040 #ifdef WIN32
00041 #include <winsock2.h>
00042 #include <iphlpapi.h>
00043
00044
00045 #else // WIN32
00046
00047
00048 #include <netdb.h>
00049 #include <linux/if.h>
00050 #include <sys/errno.h>
00051 #include <sys/ioctl.h>
00052 #include <sys/select.h>
00053 #include <sys/time.h>
00054
00055 #endif // WIN32
00056
00057
00058
00059 #include "common/wave_ex.h"
00060 #include "perf/perf.h"
00061 #include "util/parsing.h"
00062
00063
00064 namespace netlib {
00065
00066
00067 #define ASSERT_SOCK(s) ASSERT( wsIsValidSocket(s) , "Bad socket: %d", s)
00068
00069
00070
00071 #ifdef WIN32
00072 typedef int socket_length_t;
00073 #else // WIN32
00074 typedef socklen_t socket_length_t;
00075 #endif // WIN32
00076
00077
00078
00079
00080
00081
00082
00083
00084
00085 class smart_socket {
00086 public:
00087 smart_socket(void) throw() : m_s(-1) { }
00088 ~smart_socket(void) throw() {
00089 this->clear();
00090 }
00091
00092 void set(IN int s) throw() {
00093 this->clear();
00094 m_s = s;
00095 }
00096
00097 int get(void) throw() { return m_s; }
00098
00099 operator bool (void) const throw() { return (m_s >= 0); }
00100
00101 private:
00102 void clear(void) throw() {
00103 if (m_s >= 0) {
00104 wsCloseSocket(m_s);
00105 }
00106 m_s = -1;
00107 }
00108
00109 int m_s;
00110 };
00111
00112
00113 #ifndef WIN32
00114
00115
00116 static void
00117 dumpErrorInfo
00118 (
00119 IN const char * msg
00120 )
00121 {
00122 const int s_bufsize = 256;
00123 char buffer[s_bufsize];
00124 int error = wsGetError();
00125 wsGetErrorMessage(buffer, s_bufsize);
00126
00127 DPRINTF("%s", msg);
00128 DPRINTF("Error: %d", error);
00129 DPRINTF("%s", buffer);
00130 }
00131
00132
00133
00134 static void
00135 verify
00136 (
00137 IN bool isOK,
00138 IN const char * msg
00139 )
00140 {
00141 if (isOK)
00142 return;
00143
00144
00145 dumpErrorInfo(msg);
00146 ASSERT(false, "halting");
00147 }
00148 #endif // WIN32
00149
00150
00151
00152 static void
00153 setNonBlocking
00154 (
00155 IN int s
00156 )
00157 {
00158 ASSERT_SOCK(s);
00159
00160 #ifdef WIN32
00161
00162 #else // WIN32
00163 int flags = fcntl(s, F_GETFL, 0);
00164 verify(flags >= 0, "Failed to get socket descriptor flags");
00165 verify(fcntl(s, F_SETFL, flags | O_NONBLOCK) >= 0,
00166 "Failed to set nonblocking flag on socket");
00167 #endif // WIN32
00168 }
00169
00170
00171
00172 static void
00173 getAddressFromSockaddr
00174 (
00175 IN const struct sockaddr_storage * psa,
00176 OUT address_t& address
00177 )
00178 throw()
00179 {
00180 ASSERT(psa, "null");
00181
00182 const struct sockaddr_in * psi = (const struct sockaddr_in *) psa;
00183
00184 address.port = ntohs(psi->sin_port);
00185 address.ip.setIPv4((byte_t *) &psi->sin_addr);
00186
00187 }
00188
00189
00190
00191 static void
00192 getSockaddrFromAddress
00193 (
00194 IN const address_t& address,
00195 OUT struct sockaddr_in& sa
00196 )
00197 throw()
00198 {
00199 ASSERT(address.ip.isValid(), "invalid");
00200 memset(&sa, 0, sizeof(sa));
00201 sa.sin_family = AF_INET;
00202 sa.sin_port = htons(address.port);
00203 memcpy(&sa.sin_addr, address.ip.addr, 4 * sizeof(byte_t));
00204 }
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214 bool
00215 getLocalInterfaces
00216 (
00217 OUT map_ip_addr_t& map
00218 )
00219 {
00220 map.clear();
00221 std::vector<char> vecbytes;
00222
00223 #ifdef WIN32
00224
00225 DWORD bufsize = sizeof(MIB_IFTABLE);
00226 vecbytes.resize(bufsize);
00227 dword_t retval =
00228 GetIfTable((PMIB_IFTABLE) &vecbytes[0], &bufsize, TRUE);
00229
00230
00231 if (ERROR_INSUFFICIENT_BUFFER == retval) {
00232
00233 vecbytes.resize(bufsize);
00234 retval =
00235 GetIfTable((PMIB_IFTABLE) &vecbytes[0], &bufsize, TRUE);
00236 }
00237
00238 ASSERT_THROW(NO_ERROR == retval,
00239 "Failed to acquire local interfaces");
00240
00241
00242 PMIB_IFTABLE pTable = (PMIB_IFTABLE) &vecbytes[0];
00243 int nInterfaces = (int) pTable->dwNumEntries;
00244 DPRINTF("Found %d interfaces...", nInterfaces);
00245 for (int i = 0; i < nInterfaces; ++i) {
00246 MIB_IFROW& ifr = pTable->table[i];
00247 if (!ifr.wszName[0])
00248 continue;
00249
00250
00251
00252
00253 int strSize =
00254 WideCharToMultiByte(CP_UTF8, 0, ifr.wszName, -1,
00255 NULL, 0, NULL, NULL);
00256 ASSERT_THROW(strSize > 0,
00257 "error attempting to determine UTF-8 string size");
00258 vecbytes.resize(strSize + 1);
00259
00260
00261 if (strSize != WideCharToMultiByte(CP_UTF8, 0, ifr.wszName, -1,
00262 (char *) &vecbytes[0], strSize + 1, NULL, NULL)) {
00263 ASSERT_THROW(false,
00264 "Error translating UTF-16 name to UTF-8");
00265 }
00266 const char * name = (const char *) &vecbytes[0];
00267 DPRINTF("Interface name: '%s'", name);
00268
00269
00270 }
00271
00272 #else // WIN32
00273
00274
00275
00276
00277 smart_socket s;
00278 s.set(socket(AF_INET, SOCK_DGRAM, 0));
00279 if (!s) {
00280 DPRINTF("Failed to create UDP socket?");
00281 return false;
00282 }
00283
00284
00285
00286
00287
00288 struct ifconf ifconf;
00289 int bufSize = sizeof(struct ifreq);
00290 int lastIfcReturned = -1;
00291 while (true) {
00292 vecbytes.resize(bufSize);
00293 ifconf.ifc_len = bufSize;
00294 ifconf.ifc_buf = &vecbytes[0];
00295 int retval = ioctl(s.get(), SIOCGIFCONF, &ifconf);
00296
00297 if (retval < 0) {
00298 DPRINTF("Error calling ioctl(SIOCGIFCONF)");
00299 return false;
00300 }
00301
00302
00303
00304
00305 if (ifconf.ifc_len == lastIfcReturned) {
00306
00307 break;
00308 }
00309
00310
00311 bufSize *= 4;
00312
00313 lastIfcReturned = ifconf.ifc_len;
00314 }
00315
00316
00317 for (int n = 0; n < ifconf.ifc_len; n += sizeof(struct ifreq)) {
00318 struct ifreq * ifreq = (struct ifreq *) (&vecbytes[0] + n);
00319
00320 address_t address;
00321 getAddressFromSockaddr(
00322 (const struct sockaddr_storage *) &ifreq->ifr_ifru.ifru_addr,
00323 address);
00324
00325
00326 map[ifreq->ifr_ifrn.ifrn_name] = address.ip;
00327 }
00328 #endif // WIN32
00329
00330
00331 return true;
00332 }
00333
00334
00335
00336 bool
00337 ip_addr_t::lookupHostname
00338 (
00339 IN const char * hostname
00340 )
00341 {
00342 ASSERT(hostname, "null");
00343
00344 struct hostent * h = gethostbyname(hostname);
00345 ASSERT_THROW(h, "Failed to get host by name: " << hostname);
00346
00347
00348 {
00349 DPRINTF("Asked to look up server: '%s'", hostname);
00350 DPRINTF(" official name: '%s'", h->h_name);
00351 DPRINTF(" Aliases:");
00352 for (char ** p = h->h_aliases; *p; ++p) {
00353 DPRINTF(" '%s'", *p);
00354 }
00355 DPRINTF(" address type: %s", (AF_INET == h->h_addrtype) ?
00356 "AF_INET" : "unknown?");
00357 DPRINTF(" address length: %d", h->h_length);
00358 DPRINTF(" addresses:");
00359 for (char ** p = h->h_addr_list; *p; ++p) {
00360 const byte_t * ip = (const byte_t *) *p;
00361 if (4 == h->h_length) {
00362 DPRINTF(" %d.%d.%d.%d",
00363 ip[0], ip[1], ip[2], ip[3]);
00364 } else {
00365 DPRINTF(" (don't know how to print)");
00366 }
00367 }
00368 }
00369
00370
00371 if (4 != h->h_length) {
00372 DPRINTF(" Unknown address length: %d", h->h_length);
00373 DPRINTF(" Failing address lookup for host: %s", hostname);
00374 return false;
00375 }
00376
00377
00378 ASSERT(4 == h->h_length, "Only allow IPv4 for now");
00379
00380
00381 for (char ** p = h->h_addr_list; *p; ++p) {
00382 const byte_t * ip = (const byte_t *) *p;
00383 if (127 == ip[0] &&
00384 0 == ip[1] &&
00385 0 == ip[2] &&
00386 1 == ip[3]) {
00387 DPRINTF("skipping localhost!");
00388 continue;
00389 }
00390
00391
00392 DPRINTF(" Using: %d.%d.%d.%d",
00393 ip[0], ip[1], ip[2], ip[3]);
00394 this->setIPv4(ip);
00395 return true;
00396 }
00397
00398
00399 DPRINTF("Only have a local host address for host: %s", hostname);
00400 this->setIPv4((byte_t *) h->h_addr_list[0]);
00401 return true;
00402 }
00403
00404
00405
00406 bool
00407 ip_addr_t::isLoopback
00408 (
00409 void
00410 )
00411 const
00412 throw()
00413 {
00414 if (eType_IPv4 == flags) {
00415 return (127 == addr[0] &&
00416 0 == addr[1] &&
00417 0 == addr[2] &&
00418 1 == addr[3]);
00419 }
00420
00421 DPRINTF("Invalid ip address--not loopback!");
00422 return false;
00423 }
00424
00425
00426
00427 void
00428 ip_addr_t::setLoopback
00429 (
00430 void
00431 )
00432 throw()
00433 {
00434 byte_t ip[4] = { 127, 0, 0, 1 };
00435 this->setIPv4(ip);
00436 }
00437
00438
00439
00440 bool
00441 ip_addr_t::setBroadcast
00442 (
00443 void
00444 )
00445 throw()
00446 {
00447 if (eType_IPv4 != flags) {
00448 DPRINTF("Attempting setBroadcast() on invalid IP address");
00449 return false;
00450 }
00451
00452
00453 addr[3] = 255;
00454 return true;
00455 }
00456
00457
00458
00459 bool
00460 address_t::set
00461 (
00462 IN const char * servername,
00463 IN int remotePort
00464 )
00465 {
00466 ASSERT(servername, "null");
00467 ASSERT(remotePort > 0, "Bad port: %d", remotePort);
00468
00469 if (!this->ip.lookupHostname(servername)) {
00470 DPRINTF("Failed to look up host: %s", servername);
00471 return false;
00472 }
00473 port = remotePort;
00474 return true;
00475 }
00476
00477
00478
00479 static bool
00480 tryInterface
00481 (
00482 IN const map_ip_addr_t& map,
00483 IN const char * name,
00484 OUT ip_addr_t& ip
00485 )
00486 throw()
00487 {
00488 ASSERT(name, "null");
00489
00490 DPRINTF("Looking for interface '%s'...", name);
00491 map_ip_addr_t::const_iterator i = map.find(name);
00492 if (i == map.end()) {
00493 return false;
00494 }
00495
00496 DPRINTF("Found interface '%s'", name);
00497 ip = i->second;
00498 ip.dump(name);
00499 return true;
00500 }
00501
00502
00503
00504 bool
00505 address_t::setlocal
00506 (
00507 IN int remotePort
00508 )
00509 {
00510 ASSERT(remotePort > 0, "Bad port: %d", remotePort);
00511
00512 map_ip_addr_t map;
00513 getLocalInterfaces(map);
00514
00515
00516 {
00517 DPRINTF("Found local interfaces:");
00518 for (map_ip_addr_t::const_iterator i = map.begin();
00519 i != map.end(); ++i) {
00520 const char * name = i->first.c_str();
00521 const ip_addr_t& ip = i->second;
00522 ip.dump(name);
00523 }
00524 }
00525
00526
00527 port = remotePort;
00528
00529
00530 if (tryInterface(map, "eth0", ip)) {
00531 return true;
00532 }
00533 if (tryInterface(map, "wlan0", ip)) {
00534 return true;
00535 }
00536
00537 DPRINTF("Couldn't find a preconfigured interface, guessing...");
00538 for (map_ip_addr_t::const_iterator i = map.begin();
00539 i != map.end(); ++i) {
00540 const char * name = i->first.c_str();
00541
00542 if (!strcmp("lo", name))
00543 continue;
00544
00545 DPRINTF(" Using interface '%s'", name);
00546 ip = i->second;
00547 ip.dump(name);
00548 return true;
00549 }
00550
00551 return tryInterface(map, "lo", ip);
00552 }
00553
00554
00555
00556 bool
00557 wsIsValidSocket
00558 (
00559 IN int s
00560 )
00561 throw()
00562 {
00563 return (s >= 0);
00564 }
00565
00566
00567
00568 eWSError
00569 wsGetError
00570 (
00571 void
00572 )
00573 throw()
00574 {
00575 switch (errno) {
00576 case 0: return eWS_Okay;
00577
00578 #ifdef WIN32
00579
00580 case WSAEACCES: return eWS_Denied;
00581 case WSAEWOULDBLOCK: return eWS_Again;
00582 case WSAEADDRINUSE: return eWS_InUse;
00583 case WSAECONNREFUSED: return eWS_ConnectionRefused;
00584
00585 #else // WIN32
00586
00587 case EAGAIN: return eWS_Again;
00588 case EACCES: return eWS_Denied;
00589 case EADDRINUSE: return eWS_InUse;
00590 case ECONNREFUSED: return eWS_ConnectionRefused;
00591 #endif // WIN32
00592
00593 default:
00594 return eWS_Unknown;
00595 }
00596 }
00597
00598
00599
00600 void
00601 wsGetErrorMessage
00602 (
00603 IO char * buffer,
00604 IN int bufferSize
00605 )
00606 throw()
00607 {
00608 ASSERT(buffer, "null");
00609 ASSERT(bufferSize > 0, "Bad buffer size: %d", bufferSize);
00610
00611 const int localBufSize = 256;
00612 char local[localBufSize];
00613
00614 int error = errno;
00615 strncpy(local, strerror(error), localBufSize);
00616 local[localBufSize - 1] = 0;
00617
00618 eWSError wserr = wsGetError();
00619 snprintf(buffer, bufferSize, "%d(%d): %s", wserr, error, local);
00620 buffer[bufferSize - 1] = 0;
00621 }
00622
00623
00624
00625 int
00626 wsCreateTcpSocket
00627 (
00628 void
00629 )
00630 throw()
00631 {
00632 return socket(PF_INET, SOCK_STREAM, 0);
00633 }
00634
00635
00636
00637 int
00638 wsCreateUdpSocket
00639 (
00640 IN bool broadcast
00641 )
00642 throw()
00643 {
00644 int s = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
00645 if (s >= 0 && broadcast) {
00646 #ifdef WIN32
00647 BOOL b = 1;
00648 #else // WIN32
00649 int b = 1;
00650 #endif // WIN32
00651 const char * optval = (const char *) &b;
00652 if (setsockopt(s, SOL_SOCKET, SO_BROADCAST, optval, sizeof(b)) < 0)
00653 {
00654 wsCloseSocket(s);
00655 s = -1;
00656 }
00657 }
00658 return s;
00659 }
00660
00661
00662
00663 int
00664 wsBindToPort
00665 (
00666 IN int s,
00667 IN int port
00668 )
00669 throw()
00670 {
00671 ASSERT_SOCK(s);
00672 ASSERT(port > 0, "Bad port: %d", port);
00673
00674 struct sockaddr_in sa;
00675 memset(&sa, 0, sizeof(sa));
00676 sa.sin_family = AF_INET;
00677 sa.sin_port = htons(port);
00678 sa.sin_addr.s_addr = htonl(INADDR_ANY);
00679
00680 int retval = bind(s, (struct sockaddr *) &sa, sizeof(sa));
00681 if (!retval) {
00682 setNonBlocking(s);
00683 }
00684 return retval;
00685 }
00686
00687
00688
00689 int
00690 wsListen
00691 (
00692 IN int s,
00693 IN int maxBacklog
00694 )
00695 throw()
00696 {
00697 ASSERT_SOCK(s);
00698 ASSERT(maxBacklog >= 0, "Bad max backlog: %d", maxBacklog);
00699
00700 return listen(s, maxBacklog);
00701 }
00702
00703
00704
00705 int
00706 wsConnect
00707 (
00708 IN int s,
00709 IN const address_t& address
00710 )
00711 throw()
00712 {
00713 ASSERT_SOCK(s);
00714 ASSERT(address.port > 0, "bad port: %d", address.port);
00715
00716 struct sockaddr_in sa;
00717 getSockaddrFromAddress(address, sa);
00718 int retval = connect(s, (struct sockaddr *) &sa, sizeof(sa));
00719 if (!retval) {
00720 setNonBlocking(s);
00721 }
00722 return retval;
00723 }
00724
00725
00726
00727 int
00728 wsReceive
00729 (
00730 IN int s,
00731 IN char * buffer,
00732 IN int bufferSize
00733 )
00734 throw()
00735 {
00736 ASSERT_SOCK(s);
00737 ASSERT(buffer, "null");
00738 ASSERT(bufferSize > 0, "Bad buffer size: %d", bufferSize);
00739
00740 int flags = 0;
00741 return recv(s, buffer, bufferSize, flags);
00742 }
00743
00744
00745
00746 int
00747 wsReceiveFrom
00748 (
00749 IN int s,
00750 IN char * buffer,
00751 IN int bufferSize,
00752 OUT address_t& from
00753 )
00754 throw()
00755 {
00756 ASSERT_SOCK(s);
00757 ASSERT(buffer, "null");
00758 ASSERT(bufferSize > 0, "Bad buffer size: %d", bufferSize);
00759 from.clear();
00760
00761 struct sockaddr_storage sa;
00762 socket_length_t bytes = sizeof(sa);
00763 int flags = 0;
00764 int retval = recvfrom(s, buffer, bufferSize, flags,
00765 (struct sockaddr *) &sa, &bytes);
00766
00767
00768 if (retval > 0) {
00769 getAddressFromSockaddr(&sa, from);
00770
00771 }
00772
00773
00774 return retval;
00775 }
00776
00777
00778
00779 int
00780 wsSend
00781 (
00782 IN int s,
00783 IN const char * buffer,
00784 IN int bufferSize
00785 )
00786 throw()
00787 {
00788 ASSERT_SOCK(s);
00789 ASSERT(buffer, "null");
00790 ASSERT(bufferSize >= 0, "bad buffer size: %d", bufferSize);
00791
00792 int flags = 0;
00793
00794 #ifdef WIN32
00795 #else // WIN32
00796 flags |= MSG_NOSIGNAL;
00797 #endif // WIN32
00798
00799 return send(s, buffer, bufferSize, flags);
00800 }
00801
00802
00803
00804 int
00805 wsSendTo
00806 (
00807 IN int s,
00808 IN const char * buffer,
00809 IN int bufferSize,
00810 IN const address_t& address
00811 )
00812 throw()
00813 {
00814 ASSERT_SOCK(s);
00815 ASSERT(buffer, "null");
00816 ASSERT(bufferSize > 0, "Bad buffer size: %d", bufferSize);
00817
00818 struct sockaddr_in sa;
00819 getSockaddrFromAddress(address, sa);
00820
00821 int flags = 0;
00822 #ifdef WIN32
00823 #else // WIN32
00824 flags |= MSG_NOSIGNAL;
00825 #endif // WIN32
00826
00827 return sendto(s, buffer, bufferSize, flags,
00828 (struct sockaddr *) &sa, sizeof(sa));
00829 }
00830
00831
00832
00833 int
00834 wsAccept
00835 (
00836 IN int s,
00837 OUT address_t& address
00838 )
00839 throw()
00840 {
00841 ASSERT_SOCK(s);
00842
00843 struct sockaddr_storage sa;
00844 socket_length_t bytes = sizeof(sa);
00845 int c = accept(s, (struct sockaddr *) &sa, &bytes);
00846 if (wsIsValidSocket(c)) {
00847 getAddressFromSockaddr(&sa, address);
00848 setNonBlocking(c);
00849 }
00850
00851 return c;
00852 }
00853
00854
00855
00856 ws_set_t
00857 wsCreateSet
00858 (
00859 void
00860 )
00861 {
00862 fd_set * pf = new fd_set;
00863 ASSERT_THROW(pf, "out of memory");
00864
00865 return (ws_set_t) pf;
00866 }
00867
00868
00869
00870 void
00871 wsClearSet
00872 (
00873 IN ws_set_t set
00874 )
00875 throw()
00876 {
00877 fd_set * pf = (fd_set *) set;
00878 ASSERT(pf, "null");
00879
00880 FD_ZERO(pf);
00881 }
00882
00883
00884
00885 void
00886 wsAddSocketToSet
00887 (
00888 IN ws_set_t set,
00889 IN int s
00890 )
00891 throw()
00892 {
00893 ASSERT_SOCK(s);
00894 fd_set * pf = (fd_set *) set;
00895 ASSERT(pf, "null");
00896
00897
00898 FD_SET((word_t) s, pf);
00899 }
00900
00901
00902
00903 bool
00904 wsIsSocketInSet
00905 (
00906 IN ws_set_t set,
00907 IN int s
00908 )
00909 throw()
00910 {
00911 ASSERT_SOCK(s);
00912 fd_set * pf = (fd_set *) set;
00913 ASSERT(pf, "null");
00914
00915 return (FD_ISSET(s, pf) != 0);
00916 }
00917
00918
00919
00920 void
00921 wsDestroySet
00922 (
00923 IN ws_set_t set
00924 )
00925 throw()
00926 {
00927 fd_set * pf = (fd_set *) set;
00928
00929
00930 delete pf;
00931 }
00932
00933
00934
00935 int
00936 wsSelect
00937 (
00938 IN int maxSockets,
00939 IN ws_set_t readers,
00940 IN ws_set_t writers,
00941 IN long wait_microseconds
00942 )
00943 throw()
00944 {
00945 ASSERT_SOCK(maxSockets);
00946 ASSERT(readers, "null");
00947 ASSERT(writers, "null");
00948 ASSERT(wait_microseconds >= 0, "Bad wait time: %ld", wait_microseconds);
00949
00950 struct timeval timeout;
00951 timeout.tv_sec = 0;
00952 timeout.tv_usec = wait_microseconds;
00953
00954 return select(maxSockets, (fd_set *) readers, (fd_set *) writers,
00955 NULL, &timeout);
00956 }
00957
00958
00959
00960 void
00961 wsCloseSocket
00962 (
00963 IN int s
00964 )
00965 throw()
00966 {
00967 int ops = 0;
00968
00969 #ifdef WIN32
00970 ops = SD_BOTH;
00971 #else // WIN32
00972 ops = SHUT_RDWR;
00973 #endif // WIN32
00974
00975 shutdown(s, ops);
00976
00977 #ifdef WIN32
00978 closesocket(s);
00979 #else // WIN32
00980 close(s);
00981 #endif // WIN32
00982 }
00983
00984
00985
00986 };
00987