00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 #include <netcomm/socket/socket.h>
00025
00026 #include <core/exceptions/system.h>
00027 #include <utils/time/time.h>
00028
00029 #ifndef _GNU_SOURCE
00030 #define _GNU_SOURCE
00031 #endif
00032
00033 #include <errno.h>
00034 #include <sys/types.h>
00035 #include <sys/socket.h>
00036 #include <netdb.h>
00037 #include <unistd.h>
00038 #include <fcntl.h>
00039 #include <string.h>
00040 #include <stdlib.h>
00041
00042 #include <netinet/in.h>
00043 #include <netinet/in_systm.h>
00044 #include <netinet/ip.h>
00045 #include <poll.h>
00046
00047 #include <cstdio>
00048
00049
00050 #ifdef __linux__
00051 # ifndef IP_MTU
00052 # define IP_MTU 14
00053 # endif
00054 #endif // __linux__
00055 #ifdef __FreeBSD__
00056 # include <net/if.h>
00057 # include <sys/ioctl.h>
00058 #endif
00059
00060 namespace fawkes {
00061
00062
00063
00064
00065
00066
00067
00068
00069
00070
00071
00072 SocketException::SocketException(const char *msg)
00073 : Exception("%s", msg)
00074 {
00075 }
00076
00077
00078
00079
00080
00081
00082 SocketException::SocketException(const char *msg, int _errno)
00083 : Exception(_errno, "%s", msg)
00084 {
00085 }
00086
00087
00088
00089
00090
00091
00092
00093
00094
00095
00096
00097
00098
00099
00100
00101
00102
00103
00104
00105
00106
00107
00108
00109
00110
00111
00112
00113
00114 const short Socket::POLL_IN = POLLIN;
00115
00116
00117 const short Socket::POLL_OUT = POLLOUT;
00118
00119
00120
00121
00122 const short Socket::POLL_PRI = POLLPRI;
00123
00124
00125
00126
00127
00128 #ifdef POLLRDHUP
00129 const short Socket::POLL_RDHUP = POLLRDHUP;
00130 #else
00131 const short Socket::POLL_RDHUP = 0;
00132 #endif
00133
00134
00135 const short Socket::POLL_ERR = POLLERR;
00136
00137
00138 const short Socket::POLL_HUP = POLLHUP;
00139
00140
00141 const short Socket::POLL_NVAL = POLLNVAL;
00142
00143
00144
00145
00146
00147
00148
00149
00150
00151
00152
00153
00154
00155 Socket::Socket(int domain, int type, int protocol, float timeout)
00156 {
00157 this->timeout = timeout;
00158 if ( (sock_fd = socket(domain, type, protocol)) == -1 ) {
00159 throw SocketException("Could not open socket", errno);
00160 }
00161
00162 if (timeout > 0.f) {
00163
00164 if ( fcntl(sock_fd, F_SETFL, O_NONBLOCK) == -1 ) {
00165 throw SocketException("Could not set socket to non-blocking", errno);
00166 }
00167 }
00168
00169 client_addr = NULL;
00170 client_addr_len = 0;
00171 }
00172
00173
00174
00175
00176
00177
00178
00179 Socket::Socket()
00180 {
00181 client_addr = NULL;
00182 client_addr_len = 0;
00183 timeout = 0.f;
00184 sock_fd = -1;
00185 }
00186
00187
00188
00189
00190
00191 Socket::Socket(Socket &socket)
00192 {
00193 if ( socket.client_addr != NULL ) {
00194 client_addr = (struct ::sockaddr_in *)malloc(socket.client_addr_len);
00195 client_addr_len = socket.client_addr_len;
00196 memcpy(client_addr, socket.client_addr, client_addr_len);
00197 } else {
00198 client_addr = NULL;
00199 client_addr_len = 0;
00200 }
00201 timeout = socket.timeout;
00202 sock_fd = socket.sock_fd;
00203 }
00204
00205
00206
00207 Socket::~Socket()
00208 {
00209 close();
00210 if ( client_addr != NULL ) {
00211 free(client_addr);
00212 client_addr = NULL;
00213 }
00214 }
00215
00216
00217
00218 void
00219 Socket::close()
00220 {
00221 if ( sock_fd != -1 ) {
00222 ::close(sock_fd);
00223 sock_fd = -1;
00224 }
00225 }
00226
00227
00228
00229
00230
00231
00232
00233
00234
00235
00236 void
00237 Socket::connect(struct sockaddr *addr_port, unsigned int struct_size)
00238 {
00239 if ( sock_fd == -1 ) throw SocketException("Trying to connect invalid socket");
00240
00241 if (timeout == 0.f) {
00242 if ( ::connect(sock_fd, addr_port, struct_size) < 0 ) {
00243 throw SocketException("Could not connect", errno);
00244 }
00245 } else {
00246 struct timeval start, now;
00247 gettimeofday(&start, NULL);
00248 do {
00249 if ( ::connect(sock_fd, addr_port, struct_size) < 0 ) {
00250 if ( (errno != EINPROGRESS) &&
00251 (errno != EALREADY) ) {
00252 throw SocketException("Could not connect", errno);
00253 }
00254 }
00255 gettimeofday(&now, NULL);
00256 } while (time_diff_sec(now, start) < timeout);
00257 }
00258 }
00259
00260
00261
00262
00263
00264
00265
00266
00267
00268
00269 void
00270 Socket::connect(const char *hostname, unsigned short int port)
00271 {
00272 if ( sock_fd == -1 ) throw SocketException("Trying to connect invalid socket");
00273
00274 struct hostent* h;
00275 struct ::sockaddr_in host;
00276
00277
00278 h = gethostbyname(hostname);
00279 if ( ! h ) {
00280 throw SocketException("Cannot lookup hostname", h_errno);
00281 }
00282
00283 memset(&host, 0, sizeof(host));
00284 host.sin_family = AF_INET;
00285 memcpy((char *)&host.sin_addr.s_addr, h->h_addr, h->h_length);
00286 host.sin_port = htons(port);
00287
00288 connect((struct sockaddr *)&host, sizeof(host));
00289 }
00290
00291
00292
00293
00294
00295
00296
00297 void
00298 Socket::bind(const unsigned short int port)
00299 {
00300 struct ::sockaddr_in host;
00301
00302 host.sin_family = AF_INET;
00303 host.sin_addr.s_addr = INADDR_ANY;
00304 host.sin_port = htons(port);
00305
00306 int reuse = 1;
00307 if ( setsockopt(sock_fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) == -1) {
00308 throw SocketException("Could not set SO_REUSEADDR", errno);
00309 }
00310
00311 if (::bind(sock_fd, (struct sockaddr *) &host, sizeof(host)) < 0) {
00312 throw SocketException("Could not bind to port", errno);
00313 }
00314 }
00315
00316
00317
00318
00319
00320
00321
00322 void
00323 Socket::bind(const unsigned short int port, const char *hostname)
00324 {
00325 struct hostent* h;
00326 struct ::sockaddr_in host;
00327
00328 h = gethostbyname(hostname);
00329 if ( ! h ) {
00330 throw SocketException("Cannot lookup hostname", h_errno);
00331 }
00332
00333 memset(&host, 0, sizeof(host));
00334 host.sin_family = AF_INET;
00335 memcpy(&host.sin_addr.s_addr, h->h_addr, h->h_length);
00336 host.sin_port = htons(port);
00337
00338 host.sin_family = AF_INET;
00339 host.sin_addr.s_addr = INADDR_ANY;
00340 host.sin_port = htons(port);
00341
00342 if (::bind(sock_fd, (struct sockaddr *) &host, sizeof(host)) < 0) {
00343 throw SocketException("Could not bind to port", errno);
00344 }
00345 }
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356 void
00357 Socket::listen(int backlog)
00358 {
00359 if ( ::listen(sock_fd, backlog) ) {
00360 throw SocketException("Cannot listen on socket", errno);
00361 }
00362 }
00363
00364
00365
00366
00367
00368
00369
00370 Socket *
00371 Socket::accept()
00372 {
00373 struct ::sockaddr_in tmp_client_addr;
00374 unsigned int tmp_client_addr_len = sizeof(struct ::sockaddr_in);
00375
00376 int a_sock_fd = -1;
00377
00378 a_sock_fd = ::accept(sock_fd, (sockaddr *)&tmp_client_addr, &tmp_client_addr_len);
00379 if ( a_sock_fd == -1 ) {
00380 if (errno != EWOULDBLOCK) {
00381 throw SocketException("Could not accept connection", errno);
00382 } else {
00383 return NULL;
00384 }
00385 }
00386
00387
00388
00389
00390
00391 Socket *s = clone();
00392 s->sock_fd = a_sock_fd;
00393
00394 if ( s->client_addr != NULL ) {
00395 free(s->client_addr);
00396 }
00397 struct ::sockaddr_in *tmp_client_addr_alloc = (struct ::sockaddr_in *)malloc(sizeof(struct ::sockaddr_in));
00398 memcpy(tmp_client_addr_alloc, &tmp_client_addr, sizeof(struct ::sockaddr_in));
00399 s->client_addr = tmp_client_addr_alloc;
00400 s->client_addr_len = tmp_client_addr_len;
00401
00402 return s;
00403 }
00404
00405
00406
00407
00408
00409
00410 bool
00411 Socket::available()
00412 {
00413 if (sock_fd == -1) return false;
00414
00415 fd_set rfds;
00416 struct timeval tv;
00417 int retval = 1;
00418
00419 FD_ZERO(&rfds);
00420 FD_SET(sock_fd, &rfds);
00421 tv.tv_sec = 0;
00422 tv.tv_usec = 0;
00423
00424 retval = select(sock_fd + 1, &rfds, NULL, NULL, &tv);
00425 if ( retval < 0 ) {
00426 perror("select() failed");
00427 }
00428
00429 return (retval > 0);
00430 }
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440
00441
00442
00443
00444
00445
00446
00447
00448
00449
00450
00451 short
00452 Socket::poll(int timeout, short what)
00453 {
00454 if ( sock_fd == -1 ) {
00455 return POLL_ERR;
00456 }
00457
00458 struct pollfd pfd;
00459 pfd.fd = sock_fd;
00460 pfd.events = what;
00461 pfd.revents = 0;
00462 if ( ::poll(&pfd, 1, timeout) == -1 ) {
00463 if ( errno == EINTR ) {
00464 throw InterruptedException();
00465 } else {
00466 throw SocketException("poll() failed", errno);
00467 }
00468 } else {
00469 return pfd.revents;
00470 }
00471 }
00472
00473
00474
00475
00476
00477
00478
00479
00480 void
00481 Socket::write(const void *buf, size_t count)
00482 {
00483 int retval = 0;
00484 unsigned int bytes_written = 0;
00485 struct timeval start, now;
00486
00487 gettimeofday(&start, NULL);
00488
00489 do {
00490 retval = ::write(sock_fd, (char *)buf + bytes_written, count - bytes_written);
00491 if (retval == -1) {
00492 if (errno != EAGAIN) {
00493 throw SocketException("Could not write data", errno);
00494 } else {
00495
00496 retval = 0;
00497 }
00498 } else {
00499 bytes_written += retval;
00500
00501 gettimeofday(&start, NULL);
00502 }
00503 gettimeofday(&now, NULL);
00504 usleep(0);
00505 } while ((bytes_written < count) && (time_diff_sec(now, start) < timeout) );
00506
00507 if ( bytes_written < count) {
00508 throw SocketException("Write timeout");
00509 }
00510 }
00511
00512
00513
00514
00515
00516
00517
00518
00519
00520
00521
00522
00523
00524 size_t
00525 Socket::read(void *buf, size_t count, bool read_all)
00526 {
00527 int retval = 0;
00528 unsigned int bytes_read = 0;
00529
00530 if ( timeout > 0 ) {
00531 struct timeval start, now;
00532
00533 gettimeofday(&start, NULL);
00534
00535 if ( read_all ) {
00536 do {
00537 retval = ::read(sock_fd, (char *)buf + bytes_read, count - bytes_read);
00538 if (retval == -1) {
00539 if (errno != EAGAIN) {
00540 throw SocketException("Could not read data", errno);
00541 } else {
00542
00543 retval = 0;
00544 }
00545 } else {
00546 bytes_read += retval;
00547
00548 gettimeofday(&start, NULL);
00549 }
00550 gettimeofday(&now, NULL);
00551 usleep(0);
00552 } while ((bytes_read < count) && (time_diff_sec(now, start) < timeout) );
00553 } else {
00554 do {
00555 retval = ::read(sock_fd, (char *)buf, count);
00556 if ( (retval == -1) && (errno != EAGAIN) ) {
00557 throw SocketException("Could not read data", errno);
00558 } else {
00559 bytes_read = retval;
00560 }
00561 usleep(0);
00562 } while (retval < 0);
00563 }
00564 } else {
00565 if ( read_all ) {
00566 do {
00567 retval = ::read(sock_fd, (char *)buf + bytes_read, count - bytes_read);
00568 if (retval == -1) {
00569 throw SocketException("Could not read data", errno);
00570 } else if (retval == 0) {
00571 throw SocketException("Could not read any data");
00572 } else {
00573 bytes_read += retval;
00574 }
00575 usleep(0);
00576 } while (bytes_read < count);
00577 } else {
00578 do {
00579 retval = ::read(sock_fd, (char *)buf, count);
00580 if ( (retval == -1) && (errno != EAGAIN) ) {
00581 throw SocketException("Could not read data", errno);
00582 } else {
00583 bytes_read = retval;
00584 }
00585 usleep(0);
00586 } while (retval < 0);
00587 }
00588 }
00589
00590 if ( read_all && (bytes_read < count)) {
00591 throw SocketException("Read timeout");
00592 }
00593
00594 return bytes_read;
00595 }
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606
00607 void
00608 Socket::send(void *buf, size_t buf_len)
00609 {
00610 try {
00611 write(buf, buf_len);
00612 } catch (SocketException &e) {
00613 throw;
00614 }
00615 }
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625
00626
00627 size_t
00628 Socket::recv(void *buf, size_t buf_len)
00629 {
00630 ssize_t rv;
00631 if ( (rv = ::recv(sock_fd, buf, buf_len, 0)) == -1 ) {
00632 throw SocketException("recv() failed", errno);
00633 } else if ( rv == 0 ) {
00634 throw SocketException("Other side closed the connection");
00635 }
00636 return rv;
00637 }
00638
00639
00640
00641
00642
00643
00644
00645
00646 void
00647 Socket::send(void *buf, size_t buf_len,
00648 const struct sockaddr *addr, socklen_t addr_len)
00649 {
00650 int retval = 0;
00651 unsigned int bytes_written = 0;
00652 struct timeval start, now;
00653
00654 gettimeofday(&start, NULL);
00655
00656 do {
00657 retval = ::sendto(sock_fd, (char *)buf + bytes_written, buf_len - bytes_written, 0,
00658 addr, addr_len);
00659 if (retval == -1) {
00660 if (errno != EAGAIN) {
00661 throw SocketException("Could not read data", errno);
00662 } else {
00663
00664 retval = 0;
00665 }
00666 } else {
00667 bytes_written += retval;
00668
00669 gettimeofday(&start, NULL);
00670 }
00671 gettimeofday(&now, NULL);
00672 usleep(0);
00673 } while ((bytes_written < buf_len) && (time_diff_sec(now, start) < timeout) );
00674
00675 if ( bytes_written < buf_len) {
00676 throw SocketException("Write timeout");
00677 }
00678 }
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689
00690
00691
00692 size_t
00693 Socket::recv(void *buf, size_t buf_len,
00694 struct sockaddr *addr, socklen_t *addr_len)
00695 {
00696 ssize_t rv = 0;
00697
00698 if ( (rv = ::recvfrom(sock_fd, buf, buf_len, 0, addr, addr_len)) == -1) {
00699 throw SocketException("recvfrom() failed", errno);
00700 } else if ( rv == 0 ) {
00701 throw SocketException("Peer has closed the connection");
00702 } else {
00703 return rv;
00704 }
00705 }
00706
00707
00708
00709
00710
00711 bool
00712 Socket::listening()
00713 {
00714 if ( sock_fd == -1 ) return false;
00715
00716 int i = 0;
00717 unsigned int len = sizeof(i);
00718 if ( getsockopt(sock_fd, SOL_SOCKET, SO_ACCEPTCONN, &i, &len) == -1 ) {
00719 throw SocketException("Socket::listening(): getsockopt failed", errno);
00720 }
00721 return ( i == 1 );
00722 }
00723
00724
00725
00726
00727
00728
00729 unsigned int
00730 Socket::mtu()
00731 {
00732 int m = 0;
00733
00734 if ( sock_fd == -1 ) throw SocketException("Cannot get MTU of disconnected socket");
00735
00736 #ifdef __linux__
00737 unsigned int len = sizeof(m);
00738 if ( getsockopt(sock_fd, IPPROTO_IP, IP_MTU, &m, &len) == -1 ) {
00739 throw SocketException("Socket::mtu(): getsockopt failed", errno);
00740 }
00741
00742 if ( m < 0 ) {
00743 throw SocketException("MTU < 0");
00744 }
00745 #elif defined __FreeBSD__
00746 struct ifreq ifr;
00747 if (ioctl(sock_fd, SIOCGIFMTU, &ifr) != -1)
00748 m = ifr.ifr_mtu;
00749 #endif
00750
00751 return m;
00752 }
00753
00754 }