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 size_t
00524 Socket::read(void *buf, size_t count, bool read_all)
00525 {
00526 int retval = 0;
00527 unsigned int bytes_read = 0;
00528
00529 if ( timeout > 0 ) {
00530 struct timeval start, now;
00531
00532 gettimeofday(&start, NULL);
00533
00534 if ( read_all ) {
00535 do {
00536 retval = ::read(sock_fd, (char *)buf + bytes_read, count - bytes_read);
00537 if (retval == -1) {
00538 if (errno != EAGAIN) {
00539 throw SocketException("Could not read data", errno);
00540 } else {
00541
00542 retval = 0;
00543 }
00544 } else {
00545 bytes_read += retval;
00546
00547 gettimeofday(&start, NULL);
00548 }
00549 gettimeofday(&now, NULL);
00550 usleep(0);
00551 } while ((bytes_read < count) && (time_diff_sec(now, start) < timeout) );
00552 } else {
00553 do {
00554 retval = ::read(sock_fd, (char *)buf, count);
00555 if ( (retval == -1) && (errno != EAGAIN) ) {
00556 throw SocketException("Could not read data", errno);
00557 } else {
00558 bytes_read = retval;
00559 }
00560 usleep(0);
00561 } while (retval < 0);
00562 }
00563 } else {
00564 if ( read_all ) {
00565 do {
00566 retval = ::read(sock_fd, (char *)buf + bytes_read, count - bytes_read);
00567 if (retval == -1) {
00568 throw SocketException("Could not read data", errno);
00569 } else if (retval == 0) {
00570 throw SocketException("Could not read any data");
00571 } else {
00572 bytes_read += retval;
00573 }
00574 usleep(0);
00575 } while (bytes_read < count);
00576 } else {
00577 do {
00578 retval = ::read(sock_fd, (char *)buf, count);
00579 if ( (retval == -1) && (errno != EAGAIN) ) {
00580 throw SocketException("Could not read data", errno);
00581 } else {
00582 bytes_read = retval;
00583 }
00584 usleep(0);
00585 } while (retval < 0);
00586 }
00587 }
00588
00589 if ( read_all && (bytes_read < count)) {
00590 throw SocketException("Read timeout");
00591 }
00592
00593 return bytes_read;
00594 }
00595
00596
00597
00598
00599
00600
00601
00602
00603
00604
00605
00606 void
00607 Socket::send(void *buf, size_t buf_len)
00608 {
00609 try {
00610 write(buf, buf_len);
00611 } catch (SocketException &e) {
00612 throw;
00613 }
00614 }
00615
00616
00617
00618
00619
00620
00621
00622
00623
00624
00625 size_t
00626 Socket::recv(void *buf, size_t buf_len)
00627 {
00628 ssize_t rv;
00629 if ( (rv = ::recv(sock_fd, buf, buf_len, 0)) == -1 ) {
00630 throw SocketException("recv() failed", errno);
00631 } else if ( rv == 0 ) {
00632 throw SocketException("Other side closed the connection");
00633 }
00634 return rv;
00635 }
00636
00637
00638
00639
00640
00641
00642
00643
00644 void
00645 Socket::send(void *buf, size_t buf_len,
00646 const struct sockaddr *addr, socklen_t addr_len)
00647 {
00648 int retval = 0;
00649 unsigned int bytes_written = 0;
00650 struct timeval start, now;
00651
00652 gettimeofday(&start, NULL);
00653
00654 do {
00655 retval = ::sendto(sock_fd, (char *)buf + bytes_written, buf_len - bytes_written, 0,
00656 addr, addr_len);
00657 if (retval == -1) {
00658 if (errno != EAGAIN) {
00659 throw SocketException("Could not read data", errno);
00660 } else {
00661
00662 retval = 0;
00663 }
00664 } else {
00665 bytes_written += retval;
00666
00667 gettimeofday(&start, NULL);
00668 }
00669 gettimeofday(&now, NULL);
00670 usleep(0);
00671 } while ((bytes_written < buf_len) && (time_diff_sec(now, start) < timeout) );
00672
00673 if ( bytes_written < buf_len) {
00674 throw SocketException("Write timeout");
00675 }
00676 }
00677
00678
00679
00680
00681
00682
00683
00684
00685
00686
00687
00688
00689 size_t
00690 Socket::recv(void *buf, size_t buf_len,
00691 struct sockaddr *addr, socklen_t *addr_len)
00692 {
00693 ssize_t rv = 0;
00694
00695 if ( (rv = ::recvfrom(sock_fd, buf, buf_len, 0, addr, addr_len)) == -1) {
00696 throw SocketException("recvfrom() failed", errno);
00697 } else if ( rv == 0 ) {
00698 throw SocketException("Peer has closed the connection");
00699 } else {
00700 return rv;
00701 }
00702 }
00703
00704
00705
00706
00707
00708 bool
00709 Socket::listening()
00710 {
00711 if ( sock_fd == -1 ) return false;
00712
00713 int i = 0;
00714 unsigned int len = sizeof(i);
00715 if ( getsockopt(sock_fd, SOL_SOCKET, SO_ACCEPTCONN, &i, &len) == -1 ) {
00716 throw SocketException("Socket::listening(): getsockopt failed", errno);
00717 }
00718 return ( i == 1 );
00719 }
00720
00721
00722
00723
00724
00725
00726 unsigned int
00727 Socket::mtu()
00728 {
00729 int m = 0;
00730
00731 if ( sock_fd == -1 ) throw SocketException("Cannot get MTU of disconnected socket");
00732
00733 #ifdef __linux__
00734 unsigned int len = sizeof(m);
00735 if ( getsockopt(sock_fd, IPPROTO_IP, IP_MTU, &m, &len) == -1 ) {
00736 throw SocketException("Socket::mtu(): getsockopt failed", errno);
00737 }
00738
00739 if ( m < 0 ) {
00740 throw SocketException("MTU < 0");
00741 }
00742 #elif defined __FreeBSD__
00743 struct ifreq ifr;
00744 if (ioctl(sock_fd, SIOCGIFMTU, &ifr) != -1)
00745 m = ifr.ifr_mtu;
00746 #endif
00747
00748 return m;
00749 }
00750
00751 }