IBR-DTNSuite  0.10
socket.cpp
Go to the documentation of this file.
1 /*
2  * socket.cpp
3  *
4  * Copyright (C) 2011 IBR, TU Braunschweig
5  *
6  * Written-by: Johannes Morgenroth <morgenroth@ibr.cs.tu-bs.de>
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  */
21 
22 #include "ibrcommon/config.h"
23 #include "ibrcommon/net/socket.h"
24 #include "ibrcommon/net/vsocket.h"
25 #include "ibrcommon/Logger.h"
26 
27 #include <arpa/inet.h>
28 #include <sys/select.h>
29 #include <string.h>
30 #include <fcntl.h>
31 #include <netinet/tcp.h>
32 #include <sys/un.h>
33 #include <sys/socket.h>
34 #include <sys/time.h>
35 #include <netdb.h>
36 #include <unistd.h>
37 
38 #include <sstream>
39 
40 #include <cassert>
41 
42 #ifndef HAVE_BZERO
43 #define bzero(s,n) (memset((s), '\0', (n)), (void) 0)
44 #endif
45 
46 namespace ibrcommon
47 {
48  int basesocket::DEFAULT_SOCKET_FAMILY = AF_INET6;
50 
52  : _state(SOCKET_DOWN), _fd(-1), _family(PF_UNSPEC)
53  {
54  }
55 
57  : _state(SOCKET_UNMANAGED), _fd(fd), _family(PF_UNSPEC)
58  {
59  }
60 
62  {
63 #ifdef __DEVELOPMENT_ASSERTIONS__
64  assert((_state == SOCKET_DOWN) || (_state == SOCKET_DESTROYED));
65  assert(_fd == -1);
66 #endif
67  }
68 
69  int basesocket::fd() const throw (socket_exception)
70  {
71  if ((_state == SOCKET_DOWN) || (_state == SOCKET_DESTROYED) || (_fd == -1)) throw socket_exception("fd not available");
72  return _fd;
73  }
74 
76  {
77  if ((_state == SOCKET_DOWN) || (_state == SOCKET_DESTROYED)) throw socket_exception("fd not available");
78  int fd = _fd;
79  _fd = -1;
80 
81  if (_state == SOCKET_UP)
83  else
85 
86  return fd;
87  }
88 
90  {
91  int ret = ::close(this->fd());
92  if (ret == -1)
93  throw socket_exception("close error");
94 
95  _fd = -1;
96 
97  if (_state == SOCKET_UNMANAGED)
99  else
101  }
102 
104  {
105  int ret = ::shutdown(this->fd(), how);
106  if (ret == -1)
107  throw socket_exception("shutdown error");
108 
109  if (_state == SOCKET_UNMANAGED)
110  _state = SOCKET_DESTROYED;
111  else
112  _state = SOCKET_DOWN;
113  }
114 
115  bool basesocket::ready() const
116  {
117  return ((_state == SOCKET_UP) || (_state == SOCKET_UNMANAGED));
118  }
119 
120  void basesocket::set_blocking_mode(bool val, int fd) const throw (socket_exception)
121  {
122  int opts;
123  opts = fcntl((fd == -1) ? _fd : fd, F_GETFL);
124  if (opts < 0) {
125  throw socket_exception("cannot set non-blocking");
126  }
127 
128  if (val)
129  opts &= ~(O_NONBLOCK);
130  else
131  opts |= O_NONBLOCK;
132 
133  if (fcntl((fd == -1) ? _fd : fd, F_SETFL, opts) < 0) {
134  throw socket_exception("cannot set non-blocking");
135  }
136  }
137 
138  void basesocket::set_keepalive(bool val, int fd) const throw (socket_exception)
139  {
140  /* Set the option active */
141  int optval = (val ? 1 : 0);
142  if (::setsockopt((fd == -1) ? _fd : fd, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)) < 0) {
143  throw ibrcommon::socket_exception("can not activate keepalives");
144  }
145  }
146 
147  void basesocket::set_linger(bool val, int l, int fd) const throw (socket_exception)
148  {
149  // set linger option to the socket
150  struct linger linger;
151 
152  linger.l_onoff = (val ? 1 : 0);
153  linger.l_linger = l;
154  if (::setsockopt((fd == -1) ? _fd : fd, SOL_SOCKET, SO_LINGER, &linger, sizeof(linger)) < 0) {
155  throw ibrcommon::socket_exception("can not set linger option");
156  }
157  }
158 
159  void basesocket::set_reuseaddr(bool val, int fd) const throw (socket_exception)
160  {
161  int on = (val ? 1: 0);
162  if (::setsockopt((fd == -1) ? _fd : fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) < 0)
163  {
164  throw socket_exception("setsockopt(SO_REUSEADDR) failed");
165  }
166  }
167 
168  void basesocket::set_nodelay(bool val, int fd) const throw (socket_exception)
169  {
170  int set = (val ? 1 : 0);
171  if (::setsockopt((fd == -1) ? _fd : fd, IPPROTO_TCP, TCP_NODELAY, (char *)&set, sizeof(set)) < 0) {
172  throw socket_exception("set no delay option failed");
173  }
174  }
175 
176  sa_family_t basesocket::get_family() const throw (socket_exception)
177  {
178  return _family;
179  }
180 
181  sa_family_t basesocket::get_family(int fd) throw (socket_exception)
182  {
183  struct sockaddr_storage bound_addr;
184  socklen_t bound_len = sizeof(bound_addr);
185  ::memset(&bound_addr, 0, bound_len);
186 
187  // get the socket family
188  int ret = ::getsockname(fd, (struct sockaddr*)&bound_addr, &bound_len);
189  if (ret == -1) {
190  throw socket_exception("socket is not bound");
191  }
192 
193  return bound_addr.ss_family;
194  }
195 
196  bool basesocket::hasSupport(const sa_family_t family, const int type, const int protocol) throw ()
197  {
198  int fd = 0;
199  if ((fd = ::socket(family, type, protocol)) < 0) {
200  return false;
201  }
202  ::close(fd);
203  return true;
204  }
205 
206  void basesocket::init_socket(const vaddress &addr, int type, int protocol) throw (socket_exception)
207  {
208  try {
209  _family = addr.family();
210  if ((_fd = ::socket(_family, type, protocol)) < 0) {
211  throw socket_raw_error(errno, "cannot create socket");
212  }
213  } catch (const vaddress::address_exception&) {
214  // if not address is set use DEFAULT_SOCKET_FAMILY
215  if ((_fd = ::socket(DEFAULT_SOCKET_FAMILY, type, protocol)) > -1) {
216  _family = static_cast<sa_family_t>(DEFAULT_SOCKET_FAMILY);
217  }
218  // if that fails switch to the alternative SOCKET_FAMILY
219  else if ((_fd = ::socket(DEFAULT_SOCKET_FAMILY_ALTERNATIVE, type, protocol)) > -1) {
220  _family = static_cast<sa_family_t>(DEFAULT_SOCKET_FAMILY_ALTERNATIVE);
221 
222  // set the alternative socket family as default
223  DEFAULT_SOCKET_FAMILY = DEFAULT_SOCKET_FAMILY_ALTERNATIVE;
224  }
225  else
226  {
227  throw socket_raw_error(errno, "cannot create socket");
228  }
229  }
230  }
231 
232  void basesocket::init_socket(int domain, int type, int protocol) throw (socket_exception)
233  {
234  _family = static_cast<sa_family_t>(domain);
235  if ((_fd = ::socket(domain, type, protocol)) < 0) {
236  throw socket_raw_error(errno, "cannot create socket");
237  }
238  }
239 
240  void basesocket::bind(int fd, struct sockaddr *addr, socklen_t len) throw (socket_exception)
241  {
242  int ret = ::bind(fd, addr, len);
243 
244  if (ret < 0) {
245  // error
246  int bind_err = errno;
247 
248  char addr_str[256];
249  char serv_str[256];
250  ::getnameinfo(addr, len, (char*)&addr_str, 256, (char*)&serv_str, 256, NI_NUMERICHOST | NI_NUMERICSERV);
251  std::stringstream ss;
252  vaddress vaddr(addr_str, serv_str, addr->sa_family);
253  ss << "with address " << vaddr.toString();
254 
255  check_bind_error(bind_err, ss.str());
256  }
257  }
258 
260  {
261  }
262 
264  : basesocket(fd)
265  {
266  }
267 
269  {
270  try {
271  down();
272  } catch (const socket_exception&) { }
273  }
274 
276  {
277  if (_state != SOCKET_DOWN)
278  throw socket_exception("socket is already up");
279 
280  _state = SOCKET_UP;
281  }
282 
284  {
285  if ((_state == SOCKET_DOWN) || (_state == SOCKET_DESTROYED))
286  throw socket_exception("socket is not up");
287 
288  this->close();
289  }
290 
291  ssize_t clientsocket::send(const char *data, size_t len, int flags) throw (socket_error)
292  {
293  ssize_t ret = ::send(this->fd(), data, len, flags);
294  if (ret == -1) {
295  switch (errno)
296  {
297  case EPIPE:
298  // connection has been reset
299  throw socket_error(ERROR_EPIPE, "connection has been reset");
300 
301  case ECONNRESET:
302  // Connection reset by peer
303  throw socket_error(ERROR_RESET, "Connection reset by peer");
304 
305  case EAGAIN:
306  // sent failed but we should retry again
307  throw socket_error(ERROR_AGAIN, "sent failed but we should retry again");
308 
309  default:
310  throw socket_error(ERROR_WRITE, "send error");
311  }
312  }
313  return ret;
314  }
315 
316  ssize_t clientsocket::recv(char *data, size_t len, int flags) throw (socket_error)
317  {
318  ssize_t ret = ::recv(this->fd(), data, len, flags);
319  if (ret == -1) {
320  switch (errno)
321  {
322  case EPIPE:
323  // connection has been reset
324  throw socket_error(ERROR_EPIPE, "connection has been reset");
325 
326  default:
327  throw socket_error(ERROR_READ, "read error");
328  }
329  }
330 
331  return ret;
332  }
333 
334  void clientsocket::set(CLIENT_OPTION opt, bool val) throw (socket_error)
335  {
336  switch (opt) {
337  case NO_DELAY:
338  set_nodelay(val);
339  break;
340  case BLOCKING:
341  set_blocking_mode(val);
342  break;
343  default:
344  break;
345  }
346  }
347 
349  {
350  }
351 
353  : basesocket(fd)
354  {
355  }
356 
358  {
359  }
360 
361  void serversocket::listen(int connections) throw (socket_exception)
362  {
363  int ret = ::listen(_fd, connections);
364  if (ret == -1)
365  throw socket_exception("listen failed");
366  }
367 
369  {
370  struct sockaddr_storage cliaddr;
371  socklen_t len = sizeof(cliaddr);
372  ::memset(&cliaddr, 0, len);
373 
374  int new_fd = ::accept(this->fd(), (struct sockaddr *) &cliaddr, &len);
375 
376  if (new_fd <= 0) {
377  throw socket_exception("accept failed");
378  }
379 
380  // set source to addr
381  char address[256];
382  char service[256];
383  if (::getnameinfo((struct sockaddr *) &cliaddr, len, address, sizeof address, service, sizeof service, NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
384  addr = ibrcommon::vaddress(std::string(address), std::string(service), cliaddr.ss_family);
385  }
386 
387  return new_fd;
388  }
389 
390  void serversocket::set(SERVER_OPTION opt, bool val)
391  {
392  switch (opt) {
393  case BLOCKING:
394  set_blocking_mode(val);
395  break;
396  }
397  }
398 
400  {
401  }
402 
404  : basesocket(fd)
405  {
406  }
407 
409  {
410  }
411 
412  ssize_t datagramsocket::recvfrom(char *buf, size_t buflen, int flags, ibrcommon::vaddress &addr) throw (socket_exception)
413  {
414  struct sockaddr_storage clientAddress;
415  socklen_t clientAddressLength = sizeof(clientAddress);
416  ::memset(&clientAddress, 0, clientAddressLength);
417 
418  // data waiting
419  ssize_t ret = ::recvfrom(this->fd(), buf, buflen, flags, (struct sockaddr *) &clientAddress, &clientAddressLength);
420 
421  if (ret == -1) {
422  throw socket_exception("recvfrom error");
423  }
424 
425  char address[256];
426  char service[256];
427  if (::getnameinfo((struct sockaddr *) &clientAddress, clientAddressLength, address, sizeof address, service, sizeof service, NI_NUMERICHOST | NI_NUMERICSERV) == 0) {
428  addr = ibrcommon::vaddress(std::string(address), std::string(service), clientAddress.ss_family);
429  }
430 
431  return ret;
432  }
433 
434  void datagramsocket::sendto(const char *buf, size_t buflen, int flags, const ibrcommon::vaddress &addr) throw (socket_exception)
435  {
436  int ret = 0;
437  struct addrinfo hints, *res;
438  memset(&hints, 0, sizeof hints);
439 
440  hints.ai_family = _family;
441  hints.ai_socktype = SOCK_DGRAM;
442  hints.ai_flags = AI_ADDRCONFIG;
443 
444  const char *address = NULL;
445  const char *service = NULL;
446 
447  try {
448  address = addr.address().c_str();
449  } catch (const vaddress::address_not_set&) {
450  throw socket_exception("need at least an address to send to");
451  };
452 
453  try {
454  service = addr.service().c_str();
455  } catch (const vaddress::address_not_set&) { };
456 
457  if ((ret = ::getaddrinfo(address, service, &hints, &res)) != 0)
458  {
459  throw socket_exception("getaddrinfo(): " + std::string(gai_strerror(ret)));
460  }
461 
462  ssize_t len = 0;
463  len = ::sendto(this->fd(), buf, buflen, flags, res->ai_addr, res->ai_addrlen);
464 
465  // free the addrinfo struct
466  freeaddrinfo(res);
467 
468  if (len == -1) {
469  throw socket_raw_error(errno);
470  }
471  }
472 
474  : clientsocket(fd)
475  {
476  }
477 
479  : _filename(file)
480  {
481  }
482 
484  {
485  try {
486  down();
487  } catch (const socket_exception&) { }
488  }
489 
491  {
492  if (_state != SOCKET_DOWN)
493  throw socket_exception("socket is already up");
494 
495  size_t len = 0;
496  struct sockaddr_un saun;
497 
498  /*
499  * Get a socket to work with. This socket will
500  * be in the UNIX domain, and will be a
501  * stream socket.
502  */
503  init_socket(AF_UNIX, SOCK_STREAM, 0);
504 
505  /*
506  * Create the address we will be connecting to.
507  */
508  saun.sun_family = AF_UNIX;
509  ::strcpy(saun.sun_path, _filename.getPath().c_str());
510 
511  /*
512  * Try to connect to the address. For this to
513  * succeed, the server must already have bound
514  * this address, and must have issued a listen()
515  * request.
516  *
517  * The third argument indicates the "length" of
518  * the structure, not just the length of the
519  * socket name.
520  */
521  len = sizeof(saun.sun_family) + strlen(saun.sun_path);
522 
523  if (::connect(_fd, (struct sockaddr *)&saun, static_cast<socklen_t>(len)) < 0) {
524  this->close();
525  throw socket_exception("Could not connect to the named socket.");
526  }
527 
528  _state = SOCKET_UP;
529  }
530 
532  {
533  if ((_state == SOCKET_DOWN) || (_state == SOCKET_DESTROYED))
534  throw socket_exception("socket is not up");
535 
536  this->close();
537  }
538 
540  : _filename(file), _listen(listen)
541  {
542  }
543 
545  {
546  try {
547  down();
548  } catch (const socket_exception&) { }
549  }
550 
552  {
553  if (_state != SOCKET_DOWN)
554  throw socket_exception("socket is already up");
555 
556  /*
557  * Get a socket to work with. This socket will
558  * be in the UNIX domain, and will be a
559  * stream socket.
560  */
561  init_socket(AF_UNIX, SOCK_STREAM, 0);
562 
563  try {
564  this->bind(_filename);
565  this->listen(_listen);
566  } catch (const socket_exception&) {
567  // clean-up socket
568  ::close(_fd);
569  _fd = -1;
570  throw;
571  };
572 
573  _state = SOCKET_UP;
574  }
575 
577  {
578  if ((_state == SOCKET_DOWN) || (_state == SOCKET_DESTROYED))
579  throw socket_exception("socket is not up");
580 
581  this->close();
582  }
583 
585  {
586  return new filesocket(_accept_fd(addr));
587  }
588 
589  void fileserversocket::bind(const File &file) throw (socket_exception)
590  {
591  // remove old sockets
592  unlink(file.getPath().c_str());
593 
594  struct sockaddr_un address;
595  size_t address_length;
596 
597  address.sun_family = AF_UNIX;
598  strcpy(address.sun_path, file.getPath().c_str());
599  address_length = sizeof(address.sun_family) + strlen(address.sun_path);
600 
601  // bind to the socket
602  basesocket::bind(_fd, (struct sockaddr *) &address, static_cast<socklen_t>(address_length));
603  }
604 
605  tcpserversocket::tcpserversocket(const int port, int listen)
606  : _address(port), _listen(listen)
607  {
608  }
609 
611  : _address(address), _listen(listen)
612  {
613  }
614 
616  {
617  try {
618  down();
619  } catch (const socket_exception&) { }
620  }
621 
623  {
624  if (_state != SOCKET_DOWN)
625  throw socket_exception("socket is already up");
626 
627  init_socket(_address, SOCK_STREAM, 0);
628 
629  // enable reuse to avoid delay on process restart
630  this->set_reuseaddr(true);
631 
632  try {
633  // try to bind on port and/or address
634  this->bind(_address);
635  this->listen(_listen);
636  } catch (const socket_exception&) {
637  // clean-up socket
638  ::close(_fd);
639  _fd = -1;
640  throw;
641  };
642 
643  _state = SOCKET_UP;
644  }
645 
647  {
648  if ((_state == SOCKET_DOWN) || (_state == SOCKET_DESTROYED))
649  throw socket_exception("socket is not up");
650 
651  this->close();
652  }
653 
655  {
656  struct addrinfo hints, *res;
657  memset(&hints, 0, sizeof hints);
658 
659  hints.ai_family = _family;
660  hints.ai_socktype = SOCK_STREAM;
661  hints.ai_flags = 0;
662 
663  const char *address = NULL;
664  const char *service = NULL;
665 
666  if (addr.isAny()) {
667  hints.ai_flags |= AI_PASSIVE;
668  address = NULL;
669  } else if (addr.isLocal()) {
670  address = NULL;
671  } else {
672  hints.ai_flags |= AI_PASSIVE;
673  try {
674  address = addr.address().c_str();
675  } catch (const vaddress::address_not_set&) { };
676  }
677 
678  try {
679  service = addr.service().c_str();
680  } catch (const vaddress::address_not_set&) { };
681 
682  if (0 != ::getaddrinfo(address, service, &hints, &res))
683  throw socket_exception("failed to getaddrinfo with address: " + addr.toString());
684 
685  try {
686  basesocket::bind(_fd, res->ai_addr, res->ai_addrlen);
687  freeaddrinfo(res);
688  } catch (const socket_exception&) {
689  freeaddrinfo(res);
690  throw;
691  }
692  }
693 
695  {
696  return new tcpsocket(_accept_fd(addr));
697  }
698 
700  {
701  return _address;
702  }
703 
705  : clientsocket(fd)
706  {
707  timerclear(&_timeout);
708  }
709 
710  tcpsocket::tcpsocket(const ibrcommon::vaddress &destination, const timeval *timeout)
711  : _address(destination)
712  {
713  if (timeout == NULL) {
714  timerclear(&_timeout);
715  } else {
716  ::memcpy(&_timeout, timeout, sizeof _timeout);
717  }
718  }
719 
721  {
722  try {
723  down();
724  } catch (const socket_exception&) { }
725  }
726 
728  {
729  if (_state != SOCKET_DOWN)
730  throw socket_exception("socket is already up");
731 
732  struct addrinfo hints;
733  struct addrinfo *walk;
734  memset(&hints, 0, sizeof(struct addrinfo));
735  hints.ai_family = PF_UNSPEC;
736  hints.ai_socktype = SOCK_STREAM;
737  hints.ai_flags = 0;
738 
739  struct addrinfo *res = NULL;
740  int ret = 0;
741 
742  const char *address = NULL;
743  const char *service = NULL;
744 
745  try {
746  address = _address.address().c_str();
747  } catch (const vaddress::address_not_set&) {
748  throw socket_exception("need at least an address to connect to");
749  };
750 
751  try {
752  service = _address.service().c_str();
753  } catch (const vaddress::service_not_set&) { };
754 
755  if ((ret = ::getaddrinfo(address, service, &hints, &res)) != 0)
756  {
757  throw socket_exception("getaddrinfo(): " + std::string(gai_strerror(ret)));
758  }
759 
760  if (res == NULL)
761  {
762  throw socket_exception("Could not connect to the server.");
763  }
764 
765  // create a vsocket for concurrent connection setup
766  ibrcommon::vsocket probesocket;
767 
768  try {
769  // walk through all the returned addresses and try to connect to all of them
770  for (walk = res; walk != NULL; walk = walk->ai_next) {
771  // mark the socket as invalid first
772  int fd = -1;
773 
774  // create a matching socket
775  fd = ::socket(walk->ai_family, walk->ai_socktype, walk->ai_protocol);
776 
777  // if the socket is invalid we proceed with the next address
778  if (fd < 0) {
779  /* Hier kann eine Fehlermeldung hin, z.B. mit warn() */
780 
781  if ((walk->ai_next == NULL) && (probesocket.size() == 0))
782  {
783  throw socket_exception("Could not create a socket.");
784  }
785  continue;
786  }
787 
788  // set the socket to non-blocking
789  this->set_blocking_mode(false, fd);
790 
791  // connect to the current address using the created socket
792  if (::connect(fd, walk->ai_addr, walk->ai_addrlen) != 0) {
793  if (errno != EINPROGRESS) {
794  // the connect failed, so we close the socket immediately
795  ::close(fd);
796 
797  /* Hier kann eine Fehlermeldung hin, z.B. mit warn() */
798  if ((walk->ai_next == NULL) && (probesocket.size() == 0))
799  {
800  throw socket_raw_error(errno);
801  }
802  continue;
803  }
804  }
805 
806  // add the current socket to the probe-socket for later select-call
807  probesocket.add( new tcpsocket(fd) );
808  }
809 
810  // bring probesocket into UP state
811  probesocket.up();
812 
813  // create a probe set
814  socketset probeset;
815 
816  timeval timeout_value;
817  ::memcpy(&timeout_value, &_timeout, sizeof timeout_value);
818 
819  bool fastest_found = false;
820 
821  while (!fastest_found) {
822  // clear the probe-set
823  probeset.clear();
824 
825  if (timerisset(&_timeout)) {
826  // check timeout value
827  if (!timerisset(&timeout_value)) {
828  // timeout reached abort this
829  break;
830  }
831 
832  // probe for the first open socket using a timer value
833  probesocket.select(NULL, &probeset, NULL, &timeout_value);
834  } else {
835  // probe for the first open socket without any timer
836  probesocket.select(NULL, &probeset, NULL, NULL);
837  }
838 
839  // error checking for all returned sockets
840  for (socketset::iterator iter = probeset.begin(); iter != probeset.end(); ++iter) {
841  basesocket *current = (*iter);
842  int err = 0;
843  socklen_t len = sizeof(err);
844  ::getsockopt(current->fd(), SOL_SOCKET, SO_ERROR, &err, &len);
845 
846  switch (err) {
847  case 0:
848  // we got a winner!
849  fastest_found = true;
850 
851  // assign the fasted fd
852  _fd = current->release();
853 
854  // switch back to standard blocking mode
855  this->set_blocking_mode(true);
856  break;
857 
858  case EINPROGRESS:
859  // wait another round
860  break;
861 
862  default:
863  // error, remove the socket out of the probeset
864  probesocket.remove(current);
865  current->close();
866  delete current;
867 
868  // if this was the last socket then abort with an exception
869  if (probesocket.size() == 0) {
870  throw socket_raw_error(err);
871  }
872  break;
873  }
874 
875  if (fastest_found) break;
876  }
877  }
878 
879  if (fastest_found == false) {
880  throw socket_exception("connection setup timed out");
881  }
882 
883  // free the address
884  freeaddrinfo(res);
885 
886  // set the current state to UP
887  _state = SOCKET_UP;
888  } catch (const std::exception&) {
889  freeaddrinfo(res);
890  probesocket.destroy();
891  throw;
892  }
893 
894  // bring all other sockets down and clean-up
895  probesocket.destroy();
896  }
897 
899  {
900  if ((_state == SOCKET_DOWN) || (_state == SOCKET_DESTROYED))
901  throw socket_exception("socket is not up");
902 
903  this->close();
904  }
905 
907  {
908  }
909 
911  : _address(address)
912  {
913  }
914 
916  {
917  try {
918  down();
919  } catch (const socket_exception&) { }
920  }
921 
923  {
924  return _address;
925  }
926 
928  {
929  if (_state != SOCKET_DOWN)
930  throw socket_exception("socket is already up");
931 
932  init_socket(_address, SOCK_DGRAM, 0);
933 
934  try {
935  // test if the service is defined
936  _address.service();
937 
938  // service is defined, enable reuseaddr option
939  this->set_reuseaddr(true);
940  } catch (const vaddress::address_exception&) { }
941 
942  try {
943  // try to bind on port and/or address
944  this->bind(_address);
945  } catch (const socket_exception&) {
946  // clean-up socket
947  ::close(_fd);
948  _fd = -1;
949  throw;
950  };
951 
952  _state = SOCKET_UP;
953  }
954 
956  {
957  if ((_state == SOCKET_DOWN) || (_state == SOCKET_DESTROYED))
958  throw socket_exception("socket is not up");
959 
960  this->close();
961  }
962 
963  void udpsocket::bind(const vaddress &addr) throw (socket_exception)
964  {
965  struct addrinfo hints, *res;
966  memset(&hints, 0, sizeof hints);
967 
968  hints.ai_family = _family;
969  hints.ai_socktype = SOCK_DGRAM;
970  hints.ai_flags = 0;
971 
972  const char *address = NULL;
973  const char *service = NULL;
974 
975  if (addr.isAny()) {
976  hints.ai_flags |= AI_PASSIVE;
977  address = NULL;
978  } else if (addr.isLocal()) {
979  address = NULL;
980  } else {
981  hints.ai_flags |= AI_PASSIVE;
982  try {
983  address = addr.address().c_str();
984  } catch (const vaddress::address_not_set&) { };
985  }
986 
987  try {
988  service = addr.service().c_str();
989  } catch (const vaddress::service_not_set&) { };
990 
991  if (0 != ::getaddrinfo(address, service, &hints, &res))
992  throw socket_exception("failed to getaddrinfo with address: " + addr.toString());
993 
994  try {
995  basesocket::bind(_fd, res->ai_addr, res->ai_addrlen);
996  freeaddrinfo(res);
997  } catch (const socket_exception&) {
998  freeaddrinfo(res);
999  throw;
1000  }
1001  }
1002 
1004  : udpsocket(address)
1005  {
1006  }
1007 
1009  {
1010  }
1011 
1013  {
1014  udpsocket::up();
1015 
1016  try {
1017  switch (get_family()) {
1018  case AF_INET: {
1019 #ifdef HAVE_FEATURES_H
1020  int val = 1;
1021  if ( ::setsockopt(_fd, IPPROTO_IP, IP_MULTICAST_LOOP, (const char *)&val, sizeof(val)) < 0 )
1022  {
1023  throw socket_exception("setsockopt(IP_MULTICAST_LOOP)");
1024  }
1025 
1026  unsigned char ttl = 255; // Multicast TTL
1027  if ( ::setsockopt(_fd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl, sizeof(ttl)) < 0 )
1028  {
1029  throw socket_exception("setsockopt(IP_MULTICAST_TTL)");
1030  }
1031 #endif
1032 // unsigned char ittl = 255; // IP TTL
1033 // if ( ::setsockopt(this->fd(), IPPROTO_IP, IP_TTL, &ittl, sizeof(ittl)) < 0 )
1034 // {
1035 // throw socket_exception("setsockopt(IP_TTL)");
1036 // }
1037  break;
1038  }
1039 
1040  case AF_INET6: {
1041 #ifdef HAVE_FEATURES_H
1042  int val = 1;
1043  if ( ::setsockopt(_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (const char *)&val, sizeof(val)) < 0 )
1044  {
1045  throw socket_exception("setsockopt(IPV6_MULTICAST_LOOP)");
1046  }
1047 
1048 // unsigned char ttl = 255; // Multicast TTL
1049 // if ( ::setsockopt(this_fd, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, &ttl, sizeof(ttl)) < 0 )
1050 // {
1051 // throw socket_exception("setsockopt(IPV6_MULTICAST_HOPS)");
1052 // }
1053 #endif
1054 
1055 // unsigned char ittl = 255; // IP TTL
1056 // if ( ::setsockopt(_fd, IPPROTO_IPV6, IPV6_HOPLIMIT, &ittl, sizeof(ittl)) < 0 )
1057 // {
1058 // throw socket_exception("setsockopt(IPV6_HOPLIMIT)");
1059 // }
1060  break;
1061  }
1062  }
1063  } catch (const socket_exception&) {
1064  udpsocket::down();
1065  throw;
1066  }
1067  }
1068 
1070  {
1071  switch (get_family()) {
1072  case AF_INET: {
1073 #ifdef HAVE_FEATURES_H
1074  int val = 0;
1075  if ( ::setsockopt(_fd, IPPROTO_IP, IP_MULTICAST_LOOP, (const char *)&val, sizeof(val)) < 0 )
1076  {
1077  throw socket_exception("setsockopt(IP_MULTICAST_LOOP)");
1078  }
1079 #endif
1080  break;
1081  }
1082 
1083  case AF_INET6: {
1084 #ifdef HAVE_FEATURES_H
1085  int val = 0;
1086  if ( ::setsockopt(_fd, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (const char *)&val, sizeof(val)) < 0 )
1087  {
1088  throw socket_exception("setsockopt(IPV6_MULTICAST_LOOP)");
1089  }
1090 #endif
1091  break;
1092  }
1093  }
1094 
1095  udpsocket::down();
1096  }
1097 
1099  {
1100 #ifndef MCAST_JOIN_GROUP
1101  if (group.family() == AF_INET6) {
1102  mcast_op(IPV6_JOIN_GROUP, group, iface);
1103  } else {
1104  mcast_op(IP_ADD_MEMBERSHIP, group, iface);
1105  }
1106 #else
1107  mcast_op(MCAST_JOIN_GROUP, group, iface);
1108 #endif
1109  }
1110 
1112  {
1113 #ifndef MCAST_LEAVE_GROUP
1114  if (group.family() == AF_INET6) {
1115  mcast_op(IPV6_LEAVE_GROUP, group, iface);
1116  } else {
1117  mcast_op(IP_DROP_MEMBERSHIP, group, iface);
1118  }
1119 #else
1120  mcast_op(MCAST_LEAVE_GROUP, group, iface);
1121 #endif
1122  }
1123 
1124 #ifndef MCAST_JOIN_GROUP
1125  void __copy_device_address(struct in_addr *inaddr, const vinterface &iface) {
1126  ssize_t ret = 0;
1127  struct addrinfo hints, *res;
1128  memset(&hints, 0, sizeof hints);
1129 
1130  hints.ai_family = AF_INET;
1131  hints.ai_socktype = SOCK_DGRAM;
1132 
1133  // determine interface address
1134  struct sockaddr_storage iface_addr;
1135  ::memset(&iface_addr, 0, sizeof(iface_addr));
1136 
1137  const std::list<vaddress> iface_addrs = iface.getAddresses();
1138  for (std::list<vaddress>::const_iterator iter = iface_addrs.begin(); iter != iface_addrs.end(); ++iter) {
1139  const vaddress &addr = (*iter);
1140 
1141  if ((ret = ::getaddrinfo(addr.address().c_str(), NULL, &hints, &res)) == 0) {
1142  // address found
1143  ::memcpy(inaddr, &((struct sockaddr_in*)res->ai_addr)->sin_addr, sizeof(struct sockaddr_in));
1144 
1145  // free the addrinfo struct
1146  freeaddrinfo(res);
1147 
1148  break;
1149  }
1150  }
1151  }
1152 #endif
1153 
1154  void multicastsocket::mcast_op(int optname, const vaddress &group, const vinterface &iface) throw (socket_exception)
1155  {
1156  struct sockaddr_storage mcast_addr;
1157  ::memset(&mcast_addr, 0, sizeof(mcast_addr));
1158 
1159  int level = 0;
1160  int ret = 0;
1161 
1162  struct addrinfo hints, *res;
1163  memset(&hints, 0, sizeof hints);
1164 
1165  hints.ai_family = PF_UNSPEC;
1166  hints.ai_socktype = SOCK_DGRAM;
1167  hints.ai_flags = 0;
1168 
1169  if ((ret = ::getaddrinfo(group.address().c_str(), NULL, &hints, &res)) != 0) {
1170  throw socket_exception("getaddrinfo(): " + std::string(gai_strerror(ret)));
1171  }
1172 
1173  switch (res->ai_family) {
1174  case AF_INET:
1175  level = IPPROTO_IP;
1176  break;
1177 
1178  case AF_INET6:
1179  level = IPPROTO_IPV6;
1180  break;
1181 
1182  default:
1183  // free the addrinfo struct
1184  freeaddrinfo(res);
1185 
1186  throw socket_exception("address family not supported");
1187  }
1188 
1189 #ifndef MCAST_JOIN_GROUP
1190  if (res->ai_family == AF_INET) {
1191  struct ip_mreq req;
1192  ::memset(&req, 0, sizeof(req));
1193 
1194  // copy the address to the group request
1195  req.imr_multiaddr = ((struct sockaddr_in*)res->ai_addr)->sin_addr;
1196 
1197  // free the addrinfo struct
1198  freeaddrinfo(res);
1199 
1200  // set the right interface
1201  __copy_device_address(&req.imr_interface, iface);
1202 
1203  if ( ::setsockopt(this->fd(), level, optname, &req, sizeof(req)) == -1 )
1204  {
1205  throw socket_raw_error(errno, "setsockopt()");
1206  }
1207  } else {
1208  struct ipv6_mreq req;
1209  ::memset(&req, 0, sizeof(req));
1210 
1211  // copy the address to the group request
1212  req.ipv6mr_multiaddr = ((struct sockaddr_in6*)res->ai_addr)->sin6_addr;
1213 
1214  // free the addrinfo struct
1215  freeaddrinfo(res);
1216 
1217  // set the right interface
1218  req.ipv6mr_interface = iface.getIndex();
1219 
1220  if ( ::setsockopt(this->fd(), level, optname, &req, sizeof(req)) == -1 )
1221  {
1222  throw socket_raw_error(errno, "setsockopt()");
1223  }
1224  }
1225 #else
1226  struct group_req req;
1227  ::memset(&req, 0, sizeof(req));
1228 
1229  // copy the address to the group request
1230  ::memcpy(&req.gr_group, res->ai_addr, res->ai_addrlen);
1231 
1232  // free the addrinfo struct
1233  freeaddrinfo(res);
1234 
1235  // set the right interface here
1236  req.gr_interface = iface.getIndex();
1237 
1238  if ( ::setsockopt(this->fd(), level, optname, &req, sizeof(req)) == -1 )
1239  {
1240  throw socket_raw_error(errno, "setsockopt()");
1241  }
1242 #endif
1243 
1244  // successful!
1245  IBRCOMMON_LOGGER_DEBUG_TAG("multicastsocket", 70) << "multicast operation (" << optname << ") successful with " << group.toString() << " on " << iface.toString() << IBRCOMMON_LOGGER_ENDL;
1246  }
1247 
1248  void basesocket::check_socket_error(const int err) const throw (socket_exception)
1249  {
1250  switch (err)
1251  {
1252  case EACCES:
1253  throw socket_exception("Permission to create a socket of the specified type and/or protocol is denied.");
1254 
1255  case EAFNOSUPPORT:
1256  throw socket_exception("The implementation does not support the specified address family.");
1257 
1258  case EINVAL:
1259  throw socket_exception("Unknown protocol, or protocol family not available.");
1260 
1261  case EMFILE:
1262  throw socket_exception("Process file table overflow.");
1263 
1264  case ENFILE:
1265  throw socket_exception("The system limit on the total number of open files has been reached.");
1266 
1267  case ENOBUFS:
1268  case ENOMEM:
1269  throw socket_exception("Insufficient memory is available. The socket cannot be created until sufficient resources are freed.");
1270 
1271  case EPROTONOSUPPORT:
1272  throw socket_exception("The protocol type or the specified protocol is not supported within this domain.");
1273 
1274  default:
1275  throw socket_exception("cannot create socket");
1276  }
1277  }
1278 
1279  void basesocket::check_bind_error(const int err, const std::string &msg) const throw (socket_exception)
1280  {
1281  switch ( err )
1282  {
1283  case EBADF:
1284  throw socket_exception("sockfd ist kein gueltiger Deskriptor.");
1285 
1286  // Die folgenden Fehlermeldungen sind spezifisch fr UNIX-Domnensockets (AF_UNIX)
1287 
1288  case EINVAL:
1289  throw socket_exception("Die addr_len war falsch oder der Socket gehrte nicht zur AF_UNIX Familie.");
1290 
1291  case EROFS:
1292  throw socket_exception("Die Socket \"Inode\" sollte auf einem schreibgeschtzten Dateisystem residieren.");
1293 
1294  case EFAULT:
1295  throw socket_exception("my_addr weist auf eine Adresse auerhalb des erreichbaren Adressraumes zu.");
1296 
1297  case ENAMETOOLONG:
1298  throw socket_exception("my_addr ist zu lang.");
1299 
1300  case ENOENT:
1301  throw socket_exception("Die Datei existiert nicht.");
1302 
1303  case ENOMEM:
1304  throw socket_exception("Nicht genug Kernelspeicher vorhanden.");
1305 
1306  case ENOTDIR:
1307  throw socket_exception("Eine Komponente des Pfad-Prfixes ist kein Verzeichnis.");
1308 
1309  case EACCES:
1310  throw socket_exception("Keine berechtigung um eine Komponente des Pfad-prefixes zu durchsuchen.");
1311 
1312  case ELOOP:
1313  throw socket_exception("my_addr enthlt eine Kreis-Referenz (zum Beispiel durch einen symbolischen Link)");
1314 
1315  default:
1316  throw socket_exception("cannot bind socket " + msg);
1317  }
1318  }
1319 }