ucommon  7.0.0
About: GNU uCommon C++ is a portable and optimized class framework for writing C++ applications that need to use threads and support concurrent synchronization, and that use sockets, XML parsing, object serialization, thread-optimized string and data structure classes, etc..
  Fossies Dox: ucommon-7.0.0.tar.gz  ("inofficial" and yet experimental doxygen-generated source code documentation)  

socket.cpp
Go to the documentation of this file.
1 // Copyright (C) 2006-2014 David Sugar, Tycho Softworks.
2 // Copyright (C) 2015 Cherokees of Idaho.
3 //
4 // This file is part of GNU uCommon C++.
5 //
6 // GNU uCommon C++ is free software: you can redistribute it and/or modify
7 // it under the terms of the GNU Lesser General Public License as published
8 // by the Free Software Foundation, either version 3 of the License, or
9 // (at your option) any later version.
10 //
11 // GNU uCommon C++ is distributed in the hope that it will be useful,
12 // but WITHOUT ANY WARRANTY; without even the implied warranty of
13 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 // GNU Lesser General Public License for more details.
15 //
16 // You should have received a copy of the GNU Lesser General Public License
17 // along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
18 
19 #include <ucommon-config.h>
20 #include <ucommon/export.h>
21 #include <ucommon/socket.h>
22 #include <ucommon/string.h>
23 #include <ucommon/typeref.h>
24 #include <ucommon/thread.h>
25 #include <ucommon/fsys.h>
26 #ifndef _MSWINDOWS_
27 #include <net/if.h>
28 #include <sys/un.h>
29 #include <sys/ioctl.h>
30 #include <arpa/inet.h>
31 #else
32 #define HAVE_GETADDRINFO 1
33 #endif
34 #ifdef HAVE_FCNTL_H
35 #include <fcntl.h>
36 #endif
37 #include <errno.h>
38 
39 #if defined(HAVE_POLL_H)
40 #include <poll.h>
41 #elif defined(HAVE_SYS_POLL_H)
42 #include <sys/poll.h>
43 #endif
44 
45 #if defined(HAVE_SYS_FILIO_H)
46 #include <sys/filio.h>
47 #endif
48 
49 #if defined(HAVE_POLL) && defined(POLLRDNORM)
50 #define USE_POLL
51 #endif
52 
53 #if defined(__linux__) && !defined(IP_MTU)
54 #define IP_MTU 14
55 #endif
56 
57 #ifndef MSG_DONTWAIT
58 #define MSG_DONTWAIT 0
59 #endif
60 
61 #ifndef MSG_NOSIGNAL
62 #define MSG_NOSIGNAL 0
63 #endif
64 
65 #ifdef __FreeBSD__
66 #ifdef AI_V4MAPPED
67 #undef AI_V4MAPPED
68 #endif
69 #endif
70 
71 typedef struct multicast_internet
72 {
73  union {
74  struct ip_mreq ipv4;
75 #ifdef AF_INET6
76  struct ipv6_mreq ipv6;
77 #endif
78  };
80 
81 #ifndef HAVE_GETADDRINFO
82 
83 struct addrinfo {
84  int ai_flags;
85  int ai_family;
88  size_t ai_addrlen;
89  char *ai_canonname;
90  struct sockaddr *ai_addr;
91  struct addrinfo *ai_next;
92 };
93 
94 #define NI_NUMERICHOST 0x0001
95 #define NI_NUMERICSERV 0x0002
96 #define NI_NAMEREQD 0x0004
97 #define NI_NOFQDN 0x0008
98 #define NI_DGRAM 0x0010
99 
100 #define AI_PASSIVE 0x0100
101 #define AI_CANONNAME 0x0200
102 #define AI_NUMERICHOST 0x0400
103 #define AI_NUMERICSERV 0x0800
104 
105 #endif
106 
107 namespace ucommon {
108 
109 typedef uint8_t bit_t;
110 
111 static int query_family = 0;
112 static int v6only = 0;
113 
114 static void socket_mapping(int family, socket_t so)
115 {
116  if(so == INVALID_SOCKET)
117  return;
118 
119 #if defined(IPV6_V6ONLY) && defined(IPPROTO_IPV6)
120  if(family == AF_INET6)
121  setsockopt (so, IPPROTO_IPV6, IPV6_V6ONLY, (char *) &v6only, sizeof (v6only));
122 #endif
123 }
124 
125 #ifndef HAVE_GETADDRINFO
126 
127 static mutex servmutex, hostmutex;
128 
129 static void freeaddrinfo(struct addrinfo *aip)
130 {
131  while(aip != NULL) {
132  struct addrinfo *next = aip->ai_next;
133  if(aip->ai_canonname != NULL)
134  free(aip->ai_canonname);
135  if(aip->ai_addr != NULL)
136  free(aip->ai_addr);
137  free(aip);
138  aip = next;
139  }
140 }
141 
142 static int getnameinfo(const struct sockaddr *addr, socklen_t len, char *host, size_t hostlen, char *service, size_t servlen, int flags)
143 {
144  char *cp;
145  struct hostent *hp;
146  struct servent *sp;
147  assert(addr != NULL);
148  assert(host != NULL || hostlen == 0);
149  assert(service != NULL || servlen == 0);
150 
151  short port = 0;
152 
153  switch(addr->sa_family) {
154 #ifdef AF_UNIX
155  case AF_UNIX:
156  if(hostlen > 0)
157  snprintf(host, hostlen, "%s", ((struct sockaddr_un *)addr)->sun_path);
158  if(servlen > 0)
159  snprintf(service, servlen, "%s", ((struct sockaddr_un *)addr)->sun_path);
160  return 0;
161 #endif
162 #ifdef AF_INET6
163  case AF_INET6:
164  port = ((struct sockaddr_in6 *)addr)->sin6_port;
165  break;
166 #endif
167  case AF_INET:
168  port = ((struct sockaddr_in *)addr)->sin_port;
169  break;
170  default:
171  return -1;
172  }
173  if(hostlen > 0) {
174  if(flags & NI_NUMERICHOST) {
175  if(inet_ntop(addr->sa_family, addr, host, hostlen) == NULL)
176  return -1;
177  }
178  else {
179  hostmutex.lock();
180  hp = gethostbyaddr((caddr_t)addr, len, addr->sa_family);
181  if(hp != NULL && hp->h_name != NULL) {
182  if(flags & NI_NOFQDN) {
183  cp = strchr(hp->h_name, '.');
184  if(cp)
185  *cp = 0;
186  }
187  snprintf(host, hostlen, "%s", hp->h_name);
188  hostmutex.unlock();
189  }
190  else {
191  hostmutex.unlock();
192  if(flags & NI_NAMEREQD)
193  return -1;
194  if(inet_ntop(addr->sa_family, addr, host, hostlen) != NULL)
195  return -1;
196  }
197  }
198  }
199  if(servlen > 0) {
200  if(flags & NI_NUMERICSERV)
201  snprintf(service, servlen, "%d", ntohs(port));
202  else {
203  servmutex.lock();
204  sp = getservbyport(port, (flags & NI_DGRAM) ? "udp" : NULL);
205  if(sp && sp->s_name)
206  snprintf(service, servlen, "%s", sp->s_name);
207  else
208  snprintf(service, servlen, "%d", ntohs(port));
209  servmutex.unlock();
210  }
211  }
212  return 0;
213 }
214 
215 static int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hintsp, struct addrinfo **res)
216 {
217  int family;
218  const char *servtype = "tcp";
219  struct hostent *hp;
220  struct servent *sp;
221  char **np;
222  struct addrinfo hints;
223  struct addrinfo *aip = NULL, *prior = NULL;
224  socklen_t len;
225  short port = 0;
226  struct sockaddr_in *ipv4;
227 #ifdef AF_INET6
228  struct sockaddr_in6 *ipv6;
229 #endif
230  if(hintsp == NULL) {
231  memset(&hints, 0, sizeof(hints));
232  hints.ai_family = AF_UNSPEC;
233  }
234  else
235  memcpy(&hints, hintsp, sizeof(hints));
236 
237  *res = NULL;
238 
239 #ifdef AF_UNIX
240  if(hints.ai_family == AF_UNIX || (hints.ai_family == AF_UNSPEC && hostname && *hostname == '/')) {
241  if(hints.ai_socktype == 0)
242  hints.ai_socktype = SOCK_STREAM;
243 
244  aip = (struct addrinfo *)malloc(sizeof(struct addrinfo));
245  memset(aip, 0, sizeof(struct addrinfo));
246  aip->ai_next = NULL;
247  aip->ai_canonname = NULL;
248  aip->ai_protocol = hints.ai_protocol;
249  struct sockaddr_un *unp;
250  if(strlen(hostname) >= sizeof(unp->sun_path))
251  return -1;
252  unp = (struct sockaddr_un *)malloc(sizeof(struct sockaddr_un));
253  memset(unp, 0, sizeof(struct sockaddr_un));
254  unp->sun_family = AF_UNIX;
255  String::set(unp->sun_path, sizeof(unp->sun_path), hostname);
256 #ifdef __SUN_LEN
257  len = sizeof(unp->sun_len) + strlen(unp->sun_path) +
258  sizeof(unp->sun_family) + 1;
259  unp->sun_len = len;
260 #else
261  len = strlen(unp->sun_path) + sizeof(unp->sun_family) + 1;
262 #endif
263  if(hints.ai_flags & AI_PASSIVE)
264  unlink(unp->sun_path);
265  aip->ai_addr = (struct sockaddr *)unp;
266  aip->ai_addrlen = len;
267  *res = aip;
268  return 0;
269  }
270 #endif
271 
272  if(servname && *servname) {
273  if(servname[0] >= '0' && servname[0] <= '9') {
274  port = htons(atoi(servname));
275  }
276  else {
277  if(hints.ai_socktype == SOCK_DGRAM)
278  servtype = "udp";
279  servmutex.lock();
280  sp = getservbyname(servname, servtype);
281  if(!sp) {
282  servmutex.unlock();
283  return -1;
284  }
285  port = sp->s_port;
286  servmutex.unlock();
287  }
288  }
289 
290  if((!hostname || !*hostname)) {
291  aip = (struct addrinfo *)malloc(sizeof(struct addrinfo));
292  memset(aip, 0, sizeof(struct addrinfo));
293  aip->ai_canonname = NULL;
294  aip->ai_socktype = hints.ai_socktype;
295  aip->ai_protocol = hints.ai_protocol;
296  aip->ai_next = NULL;
297 
298 #ifdef AF_INET6
299  if(hints.ai_family == AF_INET6) {
300  aip->ai_family = AF_INET6;
301  ipv6 = (struct sockaddr_in6 *)malloc(sizeof(struct sockaddr_in6));
302  memset(ipv6, 0, sizeof(struct sockaddr_in6));
303  if(!(hints.ai_flags & AI_PASSIVE))
304  inet_pton(AF_INET6, "::1", &ipv6->sin6_addr);
305  ipv6->sin6_family = AF_INET6;
306  ipv6->sin6_port = port;
307  aip->ai_addr = (struct sockaddr *)ipv6;
308  aip->ai_addrlen = sizeof(struct sockaddr_in6);
309  *res = aip;
310  return 0;
311  }
312 #endif
313  aip->ai_family = AF_INET;
314  ipv4 = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));
315  memset(ipv4, 0, sizeof(struct sockaddr_in));
316  ipv4->sin_family = AF_INET;
317  ipv4->sin_port = port;
318  if(!(hints.ai_flags & AI_PASSIVE))
319  inet_pton(AF_INET, "127.0.0.1", &ipv4->sin_addr);
320  aip->ai_addr = (struct sockaddr *)ipv4;
321  aip->ai_addrlen = sizeof(struct sockaddr_in);
322  *res = aip;
323  return 0;
324  }
325  family = hints.ai_family;
326 #ifdef AF_UNSPEC
327  if(family == AF_UNSPEC)
328  family = AF_INET;
329 #endif
330  hostmutex.lock();
331 #ifdef HAVE_GETHOSTBYNAME2
332  hp = gethostbyname2(hostname, family);
333 #else
334  hp = gethostbyname(hostname);
335 #endif
336  if(!hp) {
337  hostmutex.unlock();
338  return -1;
339  }
340 
341  for(np = hp->h_addr_list; *np != NULL; np++) {
342  aip = (struct addrinfo *)malloc(sizeof(struct addrinfo));
343  memset(aip, 0, sizeof(struct addrinfo));
344  if(hints.ai_flags & AI_CANONNAME)
345  aip->ai_canonname = strdup(hp->h_name);
346  else
347  aip->ai_canonname = NULL;
348  aip->ai_socktype = hints.ai_socktype;
349  aip->ai_protocol = hints.ai_protocol;
350  aip->ai_next = NULL;
351  if(prior)
352  prior->ai_next = aip;
353  else
354  *res = aip;
355  prior = aip;
356 
357 #ifdef AF_INET6
358  if(hints.ai_family == AF_INET6) {
359  aip->ai_family = AF_INET6;
360  ipv6 = (struct sockaddr_in6 *)malloc(sizeof(struct sockaddr_in6));
361  memset(ipv6, 0, sizeof(struct sockaddr_in6));
362  memcpy(&ipv6->sin6_addr, *np, sizeof(&ipv6->sin6_addr));
363  ipv6->sin6_family = AF_INET6;
364  ipv6->sin6_port = port;
365  aip->ai_addr = (struct sockaddr *)ipv6;
366  aip->ai_addrlen = sizeof(struct sockaddr_in6);
367  continue;
368  }
369 #endif
370  aip->ai_family = AF_INET;
371  ipv4 = (struct sockaddr_in*)malloc(sizeof(struct sockaddr_in));
372  memset(ipv4, 0, sizeof(struct sockaddr_in));
373  ipv4->sin_family = AF_INET;
374  ipv4->sin_port = port;
375  memcpy(&ipv4->sin_addr, *np, sizeof(&ipv4->sin_addr));
376  aip->ai_addr = (struct sockaddr *)ipv4;
377  aip->ai_addrlen = sizeof(struct sockaddr_in);
378  }
379 
380  hostmutex.unlock();
381  if(*res)
382  return 0;
383  else
384  return -1;
385 }
386 #endif
387 
388 #if defined(AF_UNIX) && !defined(_MSWINDOWS_)
389 
390 static socklen_t unixaddr(struct sockaddr_un *addr, const char *path)
391 {
392  assert(addr != NULL);
393  assert(path != NULL && *path != 0);
394 
395  socklen_t len;
396  unsigned slen = strlen(path);
397 
398  if(slen > sizeof(addr->sun_path))
399  slen = sizeof(addr->sun_path);
400 
401  memset(addr, 0, sizeof(*addr));
402  addr->sun_family = AF_UNIX;
403  memcpy(addr->sun_path, path, slen);
404 
405 #ifdef __SUN_LEN
406  len = sizeof(addr->sun_len) + strlen(addr->sun_path) +
407  sizeof(addr->sun_family) + 1;
408  addr->sun_len = len;
409 #else
410  len = strlen(addr->sun_path) + sizeof(addr->sun_family) + 1;
411 #endif
412  return len;
413 }
414 
415 #endif
416 
417 #ifndef AF_UNSPEC
418 #define AF_UNSPEC 0
419 #endif
420 
421 static int setfamily(int family, const char *host)
422 {
423  const char *hc = host;
424  if(!host)
425  return family;
426 
427  if(!family || family == AF_UNSPEC) {
428 #ifdef AF_INET6
429  if(strchr(host, ':'))
430  family = AF_INET6;
431 #endif
432 #ifdef AF_UNIX
433  if(*host == '/')
434  family = AF_UNIX;
435 #endif
436  while((*hc >= '0' && *hc <= '9') || *hc == '.')
437  ++hc;
438  if(!*hc)
439  family = AF_INET;
440  }
441 
442  if(!family || family == AF_UNSPEC)
443  family = query_family;
444 
445  return family;
446 }
447 
448 static void bitmask(bit_t *bits, bit_t *mask, unsigned len)
449 {
450  assert(bits != NULL);
451  assert(mask != NULL);
452 
453  while(len--)
454  *(bits++) &= *(mask++);
455 }
456 
457 static void bitimask(bit_t *bits, bit_t *mask, unsigned len)
458 {
459  assert(bits != NULL);
460  assert(mask != NULL);
461 
462  while(len--)
463  *(bits++) |= ~(*(mask++));
464 }
465 
466 static void bitset(bit_t *bits, unsigned blen)
467 {
468  assert(bits != NULL);
469 
470  bit_t mask;
471 
472  while(blen) {
473  mask = (bit_t)(1 << 7);
474  while(mask && blen) {
475  *bits |= mask;
476  mask >>= 1;
477  --blen;
478  }
479  ++bits;
480  }
481 }
482 
483 static unsigned bitcount(bit_t *bits, unsigned len)
484 {
485  assert(bits != NULL);
486 
487  unsigned count = 0;
488  bit_t mask, test;
489 
490  while(len--) {
491  mask = (bit_t)(1<<7);
492  test = *bits++;
493  while(mask) {
494  if(!(mask & test))
495  return count;
496  ++count;
497  mask >>= 1;
498  }
499  }
500  return count;
501 }
502 
503 #ifdef _MSWINDOWS_
504 
505 static bool _started = false;
506 
507 static void _socketcleanup(void)
508 {
509  if(_started)
510  WSACleanup();
511 }
512 
513 void Socket::init(void)
514 {
515  static bool initialized = false;
516  unsigned short version;
517  WSADATA status;
518 
519  if(initialized)
520  return;
521 
522  initialized = true;
523  version = MAKEWORD(2,2);
524  status.wVersion = 0;
525  if(WSAStartup(version, &status))
526  __THROW_RUNTIME("socket init failure");
527  atexit(_socketcleanup);
528  _started = true;
529 }
530 #else
531 void Socket::init(void)
532 {
533 }
534 #endif
535 
536 void Socket::v4mapping(bool enable)
537 {
538  if(enable)
539  v6only = 0;
540  else
541  v6only = 1;
542 }
543 
544 void Socket::query(int querymode)
545 {
546  query_family = querymode;
547 }
548 
550 LinkedObject()
551 {
552  Family = AF_UNSPEC;
553  memset(&Network, 0, sizeof(Network));
554  memset(&Netmask, 0, sizeof(Netmask));
555  Name[0] = 0;
556 }
557 
558 cidr::cidr(const char *cp) :
559 LinkedObject()
560 {
561  assert(cp != NULL && *cp != 0);
562  set(cp);
563  Name[0] = 0;
564 }
565 
566 cidr::cidr(policy **policy, const char *cp) :
568 {
569  assert(policy != NULL);
570  assert(cp != NULL && *cp != 0);
571 
572  set(cp);
573  Name[0] = 0;
574 }
575 
576 cidr::cidr(policy **policy, const char *cp, const char *id) :
578 {
579  assert(policy != NULL);
580  assert(cp != NULL && *cp != 0);
581  assert(id != NULL && *id != 0);
582 
583  set(cp);
584  String::set(Name, sizeof(Name), id);
585 }
586 
587 
589 LinkedObject()
590 {
591  Family = copy.Family;
592  memcpy(&Network, &copy.Network, sizeof(Network));
593  memcpy(&Netmask, &copy.Netmask, sizeof(Netmask));
594  memcpy(&Name, &copy.Name, sizeof(Name));
595 }
596 
597 unsigned cidr::mask(void) const
598 {
599  switch(Family)
600  {
601  case AF_INET:
602  return bitcount((bit_t *)&Netmask.ipv4, sizeof(struct in_addr));
603 #ifdef AF_INET6
604  case AF_INET6:
605  return bitcount((bit_t *)&Netmask.ipv6, sizeof(struct in6_addr));
606 #endif
607  default:
608  return 0;
609  }
610 }
611 
612 const cidr *cidr::find(const policy *policy, const struct sockaddr *s)
613 {
614  assert(policy != NULL);
615  assert(s != NULL);
616 
617  const cidr *member = NULL;
618  unsigned top = 0;
619 
621  while(p) {
622  if(p->is_member(s)) {
623  if(p->getMask() > top) {
624  top = p->getMask();
625  member = *p;
626  }
627  }
628  p.next();
629  }
630  return member;
631 }
632 
633 const cidr *cidr::container(const policy *policy, const struct sockaddr *s)
634 {
635  assert(policy != NULL);
636  assert(s != NULL);
637 
638  const cidr *member = NULL;
639  unsigned top = 128;
640 
642  while(p) {
643  if(p->is_member(s)) {
644  if(p->getMask() < top) {
645  top = p->getMask();
646  member = *p;
647  }
648  }
649  p.next();
650  }
651  return member;
652 }
653 
654 
655 bool cidr::is_member(const struct sockaddr *s) const
656 {
657  assert(s != NULL);
658 
659  struct hostaddr_internet host;
660  struct sockaddr_internet *addr = (struct sockaddr_internet *)s;
661 
662  if(addr->address.sa_family != Family)
663  return false;
664 
665  switch(Family) {
666  case AF_INET:
667  memcpy(&host.ipv4, &addr->ipv4.sin_addr, sizeof(host.ipv4));
668  bitmask((bit_t *)&host.ipv4, (bit_t *)&Netmask, sizeof(host.ipv4));
669  if(!memcmp(&host.ipv4, &Network.ipv4, sizeof(host.ipv4)))
670  return true;
671  return false;
672 #ifdef AF_INET6
673  case AF_INET6:
674  memcpy(&host.ipv6, &addr->ipv6.sin6_addr, sizeof(host.ipv6));
675  bitmask((bit_t *)&host.ipv6, (bit_t *)&Netmask, sizeof(host.ipv6));
676  if(!memcmp(&host.ipv6, &Network.ipv6, sizeof(host.ipv6)))
677  return true;
678  return false;
679 #endif
680  default:
681  return false;
682  }
683 }
684 
685 struct hostaddr_internet cidr::broadcast(void) const
686 {
687  struct hostaddr_internet bcast;
688 
689  switch(Family) {
690  case AF_INET:
691  memcpy(&bcast.ipv4, &Network.ipv4, sizeof(Network.ipv4));
692  bitimask((bit_t *)&bcast.ipv4, (bit_t *)&Netmask.ipv4, sizeof(bcast.ipv4));
693  return bcast;
694 #ifdef AF_INET6
695  case AF_INET6:
696  memcpy(&bcast.ipv6, &Network.ipv6, sizeof(Network.ipv6));
697  bitimask((bit_t *)&bcast.ipv6, (bit_t *)&Netmask.ipv6, sizeof(bcast.ipv6));
698  return bcast;
699 #endif
700  default:
701  memset(&bcast, 0, sizeof(bcast));
702  return bcast;
703  }
704 }
705 
706 unsigned cidr::mask(const char *cp) const
707 {
708  assert(cp != NULL && *cp != 0);
709 
710  unsigned count = 0, rcount = 0, dcount = 0;
711  const char *sp = strchr(cp, '/');
712  bool flag = false;
713  const char *gp = cp;
714  uint8_t dots[4];
715  uint32_t mask;
716 
717  switch(Family) {
718 #ifdef AF_INET6
719  case AF_INET6:
720  if(sp)
721  return atoi(++sp);
722  if(!strncmp(cp, "ff00:", 5))
723  return 8;
724  if(!strncmp(cp, "ff80:", 5))
725  return 10;
726  if(!strncmp(cp, "2002:", 5))
727  return 16;
728 
729  sp = strrchr(cp, ':');
730  while(*(++sp) == '0')
731  ++sp;
732  if(*sp)
733  return 128;
734 
735  while(*cp && count < 128) {
736  if(*(cp++) == ':') {
737  count += 16;
738  while(*cp == '0')
739  ++cp;
740  if(*cp == ':') {
741  if(!flag)
742  rcount = count;
743  flag = true;
744  }
745  else
746  flag = false;
747  }
748  }
749  return rcount;
750 #endif
751  case AF_INET:
752  if(sp) {
753  if(!strchr(++sp, '.'))
754  return atoi(sp);
755  mask = inet_addr(sp);
756  return bitcount((bit_t *)&mask, sizeof(mask));
757  }
758  memset(dots, 0, sizeof(dots));
759  dots[0] = atoi(cp);
760  while(*gp && dcount < 3) {
761  if(*(gp++) == '.')
762  dots[++dcount] = atoi(gp);
763  }
764  if(dots[3])
765  return 32;
766 
767  if(dots[2])
768  return 24;
769 
770  if(dots[1])
771  return 16;
772 
773  return 8;
774  default:
775  return 0;
776  }
777 }
778 
779 void cidr::set(const char *cp)
780 {
781  assert(cp != NULL && *cp != 0);
782 
783  char cbuf[128];
784  char *ep;
785  unsigned dots = 0;
786 
787 #ifdef _MSWINDOWS_
788  DWORD addr4;
789  int slen;
790  struct sockaddr_in6 *paddr;
791 #endif
792 
793 #ifdef AF_INET6
794  if(strchr(cp, ':'))
795  Family = AF_INET6;
796  else
797 #endif
798  Family = AF_INET;
799 
800  switch(Family) {
801  case AF_INET:
802  memset(&Netmask.ipv4, 0, sizeof(Netmask.ipv4));
803  bitset((bit_t *)&Netmask.ipv4, mask(cp));
804  String::set(cbuf, sizeof(cbuf), cp);
805  ep = (char *)strchr(cbuf, '/');
806  if(ep)
807  *ep = 0;
808 
809  cp = cbuf;
810  while(NULL != (cp = strchr(cp, '.'))) {
811  ++dots;
812  ++cp;
813  }
814 
815  while(dots++ < 3)
816  String::add(cbuf, sizeof(cbuf), ".0");
817 
818 #ifdef _MSWINDOWS_
819  addr4 = inet_addr(cp);
820  memcpy(&Network.ipv4, &addr4, sizeof(Network.ipv4));
821 #else
822  inet_aton(cbuf, &Network.ipv4);
823 #endif
824  bitmask((bit_t *)&Network.ipv4, (bit_t *)&Netmask.ipv4, sizeof(Network.ipv4));
825  break;
826 #ifdef AF_INET6
827  case AF_INET6:
828  memset(&Netmask.ipv6, 0, sizeof(Netmask));
829  bitset((bit_t *)&Netmask.ipv6, mask(cp));
830  String::set(cbuf, sizeof(cbuf), cp);
831  ep = (char *)strchr(cp, '/');
832  if(ep)
833  *ep = 0;
834 #ifdef _MSWINDOWS_
835  struct sockaddr saddr;
836  slen = sizeof(saddr);
837  paddr = (struct sockaddr_in6 *)&saddr;
838  WSAStringToAddress((LPSTR)cbuf, AF_INET6, NULL, &saddr, &slen);
839  Network.ipv6 = paddr->sin6_addr;
840 #else
841  inet_pton(AF_INET6, cbuf, &Network.ipv6);
842 #endif
843  bitmask((bit_t *)&Network.ipv6, (bit_t *)&Netmask.ipv6, sizeof(Network.ipv6));
844 #endif
845  default:
846  break;
847  }
848 }
849 
850 Socket::address::address(int family, const char *a, int type, int protocol)
851 {
852  assert(a != NULL && *a != 0);
853 
854  list = NULL;
855 #ifdef _MSWINDOWS_
856  Socket::init();
857 #endif
858  set(family, a, type, protocol);
859 }
860 
861 Socket::address::address(const char *host, in_port_t port)
862 {
863  assert(host != NULL && *host != 0);
864 
865  list = NULL;
866 #ifdef _MSWINDOWS_
867  Socket::init();
868 #endif
869  set(host, port);
870 }
871 
872 Socket::address::address(int family, const char *host, const char *svc)
873 {
874  assert(host != NULL && *host != 0);
875  assert(svc != NULL && *svc != 0);
876 
877  struct addrinfo hint;
878 
879 #ifdef _MSWINDOWS_
880  Socket::init();
881 #endif
882 
883  list = NULL;
884  memset(&hint, 0, sizeof(hint));
885  hint.ai_family = family;
886  getaddrinfo(host, svc, &hint, &list);
887 }
888 
889 Socket::address::address(const in_addr& address, in_port_t port) : list(NULL)
890 {
891  sockaddr_in addr;
892  addr.sin_family = AF_INET;
893  addr.sin_addr = address;
894  addr.sin_port = htons(port);
895  insert((const struct sockaddr *)&addr);
896 }
897 
898 Socket::address::address(const in6_addr& address, in_port_t port) : list(NULL)
899 {
900  sockaddr_in6 addr;
901  addr.sin6_family = AF_INET6;
902  addr.sin6_addr = address;
903  addr.sin6_port = htons(port);
904  insert((const struct sockaddr *)&addr);
905 }
906 
908 {
909  list = NULL;
910 }
911 
913 {
914  list = NULL;
915  copy(from.list);
916 }
917 
920 {
921  if (*this != rhs)
922  {
923  list = NULL;
924  copy(rhs.list);
925  }
926  return *this;
927 }
928 
929 Socket::address::address(const char *host, const char *service, int type)
930 {
931  list = NULL;
932  set(host, service, type);
933 }
934 
936 {
937  clear();
938 }
939 
941 {
942  if(list) {
943  freeaddrinfo(list);
944  list = NULL;
945  }
946 }
947 
948 void Socket::release(struct addrinfo *list)
949 {
950  if (list) {
951  freeaddrinfo(list);
952  list = NULL;
953  }
954 }
955 
956 struct ::addrinfo *Socket::query(const char *hp, const char *svc, int type, int protocol)
957 {
958  assert(hp != NULL && *hp != 0);
959 
960  int family = DEFAULT_FAMILY;
961  char hostbuf[256];
962  struct addrinfo hint;
963  String::set(hostbuf, sizeof(hostbuf), hp);
964  char *cp = strchr(hostbuf, '/');
965  char *host = hostbuf;
966 
967  memset(&hint, 0, sizeof(hint));
968 
969  hint.ai_socktype = type;
970  hint.ai_protocol = protocol;
971 
972 #ifdef PF_UNSPEC
973  hint.ai_family = PF_UNSPEC;
974  hint.ai_flags = AI_PASSIVE;
975 #endif
976 
977  if(cp)
978  *cp = 0;
979 
980  if(*host == '[') {
981  cp = strchr(++host, ']');
982  if(cp) {
983  *(cp++) = 0;
984  if(*cp == ':')
985  svc = ++cp;
986  }
987 #ifdef AF_INET6
988  family = AF_INET6;
989 #else
990  return NULL;
991 #endif
992  }
993  else if(((cp = strrchr(host, ':')) != NULL) && (strchr(host, ':') == cp)) {
994  *(cp++) = 0;
995  svc = cp;
996  }
997 
998  if(is_numeric(host)) {
999  hint.ai_flags |= AI_NUMERICHOST;
1000 
1001  if(strchr(host, ':')) {
1002 #ifdef AF_INET6
1003  family = AF_INET6;
1004 #else
1005  return NULL;
1006 #endif
1007  }
1008  else
1009  family = AF_INET;
1010  }
1011 
1012  if(family && family != AF_UNSPEC)
1013  hint.ai_family = family;
1014 
1015 #if defined(AF_INET6) && defined(AI_V4MAPPED)
1016  if(hint.ai_family == AF_INET6 && !v6only)
1017  hint.ai_flags |= AI_V4MAPPED;
1018 #endif
1019 #ifdef AI_NUMERICSERV
1020  if(svc && atoi(svc) > 0)
1021  hint.ai_flags |= AI_NUMERICSERV;
1022 #endif
1023 
1024  struct addrinfo *result = NULL;
1025  getaddrinfo(host, svc, &hint, &result);
1026  return result;
1027 }
1028 
1029 bool
1031 {
1032  struct addrinfo *node = list;
1033  struct addrinfo *node_o = other.list;
1034 
1035  while(node && node_o) {
1036  if(!equal(node->ai_addr, node_o->ai_addr))
1037  return false;
1038  node = node->ai_next;
1039  node_o = node_o->ai_next;
1040  }
1041  if(node || node_o)
1042  return false;
1043  return true;
1044 }
1045 
1046 void Socket::address::set(const char *host, in_port_t port)
1047 {
1048  assert(host != NULL && *host != 0);
1049 
1050  char buf[16];
1051 
1052  clear();
1053 
1054  if(port) {
1055  snprintf(buf, sizeof(buf), "%u", port);
1056  list = Socket::query(host, buf);
1057  }
1058  else
1059  list = Socket::query(host, NULL);
1060 }
1061 
1062 void Socket::address::set(int family, const char *a, int type, int protocol)
1063 {
1064  assert(a != NULL && *a != 0);
1065 
1066  char *addr = strdup(a);
1067  char *host = strchr(addr, '@');
1068  char *ep;
1069  char *svc = NULL;
1070  struct addrinfo hint;
1071 
1072  clear();
1073 
1074  memset(&hint, 0, sizeof(hint));
1075 #ifdef PF_UNSPEC
1076  hint.ai_family = PF_UNSPEC;
1077  hint.ai_socktype = SOCK_STREAM;
1078  hint.ai_flags = AI_PASSIVE;
1079 #endif
1080 
1081  if(!host)
1082  host = addr;
1083  else
1084  ++host;
1085 
1086  if(*host != '[') {
1087  ep = strchr(host, ':');
1088  if(ep) {
1089  *(ep++) = 0;
1090  svc = ep;
1091  }
1092  goto proc;
1093  }
1094 #ifdef AF_INET6
1095  if(*host == '[') {
1096  family = AF_INET6;
1097  ++host;
1098  ep = strchr(host, ']');
1099  if(ep) {
1100  *(ep++) = 0;
1101  if(*ep == ':')
1102  svc = ++ep;
1103  }
1104  }
1105 #endif
1106 proc:
1107  hint.ai_family = family;
1108  hint.ai_socktype = type;
1109  hint.ai_protocol = protocol;
1110 
1111 #if defined(AF_INET6) && defined(AI_V4MAPPED)
1112  if(hint.ai_family == AF_INET6 && !v6only)
1113  hint.ai_flags |= AI_V4MAPPED;
1114 #endif
1115 
1116  getaddrinfo(host, svc, &hint, &list);
1117  strfree(addr);
1118 }
1119 
1120 struct sockaddr *Socket::address::modify(void)
1121 {
1122  if(!list)
1123  return NULL;
1124 
1125  return list->ai_addr;
1126 }
1127 
1128 const struct sockaddr *Socket::address::get(void) const
1129 {
1130  if(!list)
1131  return NULL;
1132 
1133  return list->ai_addr;
1134 }
1135 
1137 {
1138  struct sockaddr *ap;
1139  if(!list)
1140  return 0;
1141 
1142  ap = list->ai_addr;
1143  if(!ap)
1144  return 0;
1145 
1146  return ap->sa_family;
1147 }
1148 
1150 {
1151  struct sockaddr *ap;
1152  struct addrinfo *lp;
1153 
1154  lp = list;
1155 
1156  while(lp) {
1157  ap = lp->ai_addr;
1158  setPort(ap, port);
1159  lp = lp->ai_next;
1160  }
1161 }
1162 
1164 {
1165  Socket::address copy = *this;
1166  copy.setPort(port);
1167  return copy;
1168 }
1169 
1170 struct sockaddr *Socket::address::modify(int family)
1171 {
1172  struct sockaddr *ap;
1173  struct addrinfo *lp;
1174 
1175  lp = list;
1176 
1177  while(lp) {
1178  ap = lp->ai_addr;
1179  if(ap && ap->sa_family == family)
1180  return ap;
1181  lp = lp->ai_next;
1182  }
1183  return NULL;
1184 }
1185 
1186 const struct sockaddr *Socket::address::get(int family) const
1187 {
1188  const struct sockaddr *ap;
1189  const struct addrinfo *lp;
1190 
1191  lp = list;
1192 
1193  while(lp) {
1194  ap = lp->ai_addr;
1195  if(ap && ap->sa_family == family)
1196  return ap;
1197  lp = lp->ai_next;
1198  }
1199  return NULL;
1200 }
1201 
1202 void Socket::address::set(struct sockaddr *addr)
1203 {
1204  clear();
1205  add(addr);
1206 }
1207 
1208 bool Socket::address::remove(const struct sockaddr *addr)
1209 {
1210  assert(addr != NULL);
1211  struct addrinfo *node = list, *prior = NULL;
1212 
1213  while(node) {
1214  if(node->ai_addr && equal(addr, node->ai_addr))
1215  break;
1216  prior = node;
1217  node = node->ai_next;
1218  }
1219 
1220  if(!node)
1221  return false;
1222 
1223  if(!prior)
1224  list = node->ai_next;
1225  else
1226  prior->ai_next = node->ai_next;
1227 
1228  node->ai_next = NULL;
1229  freeaddrinfo(node);
1230  return true;
1231 }
1232 
1233 unsigned Socket::address::insert(const struct addrinfo *alist)
1234 {
1235  unsigned count = 0;
1236  while(alist) {
1237  if(insert(alist->ai_addr))
1238  ++count;
1239  alist = alist->ai_next;
1240  }
1241  return count;
1242 }
1243 
1244 unsigned Socket::address::remove(const struct addrinfo *alist)
1245 {
1246  unsigned count = 0;
1247  while(alist) {
1248  if(remove(alist->ai_addr))
1249  ++count;
1250  alist = alist->ai_next;
1251  }
1252  return count;
1253 }
1254 
1255 bool Socket::address::insert(const struct sockaddr *addr)
1256 {
1257  assert(addr != NULL);
1258 
1259  struct addrinfo *node = list, hints;
1260 
1261  while(node && node->ai_addr) {
1262  if(node->ai_addr && equal(addr, node->ai_addr))
1263  return false;
1264  node = node->ai_next;
1265  }
1266 
1267  char buf[256], svc[16];
1268  query(addr, buf, sizeof(buf));
1269  snprintf(svc, sizeof(svc), "%d", port(addr));
1270  memset(&hints, 0, sizeof(hints));
1271  hints.ai_family = addr->sa_family;
1272  hints.ai_flags = AI_NUMERICHOST | AI_NUMERICSERV;
1273  node = NULL;
1274  getaddrinfo(buf, svc, &hints, &node);
1275  if (!node)
1276  return false;
1277 
1278  if (node->ai_next)
1279  freeaddrinfo(node->ai_next);
1280 
1281  node->ai_next = list;
1282  list = node;
1283  return true;
1284 }
1285 
1287 {
1288  clear();
1289  while (addr) {
1290  if (addr->ai_addr)
1291  insert(addr->ai_addr);
1292  addr = addr->ai_next;
1293  }
1294 }
1295 
1296 void Socket::address::setPort(struct sockaddr *address, in_port_t port)
1297 {
1298  if (address == NULL)
1299  return;
1300 
1301  switch (address->sa_family) {
1302  case AF_INET:
1303  reinterpret_cast<sockaddr_in* >(address)->sin_port = htons(port);
1304  break;
1305  case AF_INET6:
1306  reinterpret_cast<sockaddr_in6*>(address)->sin6_port = htons(port);
1307  break;
1308  }
1309 }
1310 
1311 bool Socket::address::isAny(const struct sockaddr *address)
1312 {
1313  if (address == NULL)
1314  return false;
1315 
1316  switch (address->sa_family) {
1317  case AF_INET:
1318  return reinterpret_cast<const sockaddr_in*>(address)->sin_addr.s_addr == INADDR_ANY;
1319  case AF_INET6:
1320  return memcmp(
1321  &reinterpret_cast<const sockaddr_in6*>(address)->sin6_addr,
1322  &in6addr_any,
1323  sizeof(in6addr_any)) == 0;
1324  default:
1325  return false;
1326  }
1327 }
1328 
1329 bool Socket::address::isLoopback(const struct sockaddr *address)
1330 {
1331  if (address == NULL)
1332  return false;
1333 
1334  switch (address->sa_family) {
1335  case AF_INET:
1336  return reinterpret_cast<const sockaddr_in*>(address)->sin_addr.s_addr == htonl(INADDR_LOOPBACK);
1337  case AF_INET6:
1338  return memcmp(
1339  &reinterpret_cast<const sockaddr_in6*>(address)->sin6_addr,
1340  &in6addr_loopback,
1341  sizeof(in6addr_loopback)) == 0;
1342  default:
1343  return false;
1344  }
1345 }
1346 
1347 void Socket::address::setAny(int sa_family)
1348 {
1349  if(sa_family == AF_UNSPEC)
1350  sa_family = family();
1351  clear();
1352  const sockaddr_storage sa = Socket::address::any(sa_family);
1353  insert(reinterpret_cast<const sockaddr*>(&sa));
1354 }
1355 
1356 void Socket::address::setLoopback(int sa_family)
1357 {
1358  if(sa_family == AF_UNSPEC)
1359  sa_family = family();
1360  clear();
1361  const sockaddr_storage sa = Socket::address::loopback(sa_family);
1362  insert(reinterpret_cast<const sockaddr*>(&sa));
1363 }
1364 
1365 void Socket::address::setAny(struct sockaddr *sa)
1366 {
1367  int family = sa->sa_family;
1368  memset(sa, 0, Socket::len(sa));
1369  sa->sa_family = family;
1370 }
1371 
1372 void Socket::address::setLoopback(struct sockaddr *sa)
1373 {
1374  switch (sa->sa_family) {
1375  case AF_INET:
1376  reinterpret_cast<sockaddr_in*>(sa)->sin_addr.s_addr = htonl(INADDR_LOOPBACK);
1377  break;
1378  case AF_INET6:
1379  memcpy(
1380  &reinterpret_cast<sockaddr_in6*>(sa)->sin6_addr,
1381  &in6addr_loopback,
1382  sizeof(in6addr_loopback));
1383  break;
1384  }
1385 }
1386 
1388 {
1389  sockaddr_storage sa;
1390  memset(&sa, 0, sizeof(sockaddr_storage));
1391  sa.ss_family = family;
1392  return sa;
1393 }
1394 
1396 {
1397  sockaddr_storage sa = any(family);
1398  setLoopback((struct sockaddr*)&sa);
1399  return sa;
1400 }
1401 
1402 struct sockaddr_in *Socket::address::ipv4(struct sockaddr *addr)
1403 {
1404  if(addr == NULL || addr->sa_family != AF_INET)
1405  return NULL;
1406 
1407  return (struct sockaddr_in*)addr;
1408 }
1409 
1410 #ifdef AF_INET6
1411 struct sockaddr_in6 *Socket::address::ipv6(struct sockaddr *addr)
1412 {
1413  if(addr == NULL || addr->sa_family != AF_INET6)
1414  return NULL;
1415 
1416  return (struct sockaddr_in6*)addr;
1417 }
1418 #endif
1419 
1420 struct sockaddr *Socket::address::dup(struct sockaddr *addr)
1421 {
1422  struct sockaddr *node;
1423 
1424  if(!addr)
1425  return NULL;
1426 
1427  size_t slen = len(addr);
1428  if(!slen)
1429  return NULL;
1430 
1431  node = (struct sockaddr *)malloc(slen);
1432  if (node)
1433  memcpy(node, addr, slen);
1434  return node;
1435 }
1436 
1437 void Socket::address::add(struct sockaddr *addr)
1438 {
1439  assert(addr != NULL);
1440 
1441  char buffer[80];
1442  char svc[8];
1443 
1444  Socket::query(addr, buffer, sizeof(buffer));
1445  snprintf(svc, sizeof(svc), "%d", Socket::port(addr));
1446  add(buffer, svc, addr->sa_family);
1447 }
1448 
1449 void Socket::address::set(const char *host, const char *svc, int socktype)
1450 {
1451  clear();
1452  add(host, svc, socktype);
1453 }
1454 
1455 void Socket::address::add(const char *host, const char *svc, int socktype)
1456 {
1457  assert(host != NULL && *host != 0);
1458  assert(svc != NULL && *svc != 0);
1459 
1460  struct addrinfo *join = NULL, *last = NULL;
1461 
1462  join = Socket::query(host, svc, socktype);
1463  if(!join)
1464  return;
1465 
1466  if(!list) {
1467  list = join;
1468  return;
1469  }
1470  last = list;
1471  while(last->ai_next)
1472  last = last->ai_next;
1473  last->ai_next = join;
1474 }
1475 
1476 struct sockaddr *Socket::address::find(const struct sockaddr *addr) const
1477 {
1478  assert(addr != NULL);
1479 
1480  struct addrinfo *node = list;
1481 
1482  while(node) {
1483  if(equal(addr, node->ai_addr))
1484  return node->ai_addr;
1485  node = node->ai_next;
1486  }
1487  return NULL;
1488 }
1489 
1490 size_t Socket::address::print(const sockaddr* addr, char *dst, size_t dst_sz, bool port, bool ipv6_brackets)
1491 {
1492  if(!addr || !dst || !dst_sz)
1493  return 0;
1494 
1495  memset(dst, 0, dst_sz);
1496  const char* ret = dst;
1497  const int af = addr->sa_family;
1498  const char *res = NULL;
1499 #if defined(AF_INET6)
1500  ipv6_brackets = (af == AF_INET6) ? ipv6_brackets || port : false;
1501  if(ipv6_brackets) {
1502  *dst++ = '[';
1503  dst_sz--;
1504  }
1505 #endif
1506  switch (af) {
1507 #ifdef _MSWINDOWS_
1508  case AF_INET:
1509  struct sockaddr_in in;
1510  memset(&in, 0, sizeof(in));
1511  in.sin_family = AF_INET;
1512  memcpy(&in.sin_addr, &reinterpret_cast<const struct sockaddr_in*>(addr)->sin_addr, sizeof(struct in_addr));
1513 
1514  if(!getnameinfo((struct sockaddr *)&in, (socklen_t)sizeof(struct sockaddr_in), dst, (socksize_t)dst_sz, NULL, 0, NI_NUMERICHOST)) {
1515  res = dst;
1516  }
1517  break;
1518  #ifdef AF_INET6
1519  case AF_INET6:
1520  struct sockaddr_in6 in6;
1521  memset(&in6, 0, sizeof(in6));
1522  in6.sin6_family = AF_INET6;
1523  memcpy(&in6.sin6_addr, &reinterpret_cast<const struct sockaddr_in6*>(addr)->sin6_addr, sizeof(struct in_addr6));
1524 
1525  if(!getnameinfo((struct sockaddr *)&in6, (socklen_t)sizeof(struct sockaddr_in6), dst, (socksize_t)dst_sz, NULL, 0, NI_NUMERICHOST)) {
1526  res = dst;
1527  }
1528  break;
1529  #endif
1530 #elif defined(HAVE_INET_NTOP)
1531  case AF_INET:
1532  res = ::inet_ntop(AF_INET, &reinterpret_cast<const sockaddr_in*>(addr)->sin_addr, dst, dst_sz);
1533  break;
1534  #ifdef AF_INET6
1535  case AF_INET6:
1536  res = ::inet_ntop(AF_INET6, &reinterpret_cast<const sockaddr_in6*>(addr)->sin6_addr, dst, dst_sz);
1537  break;
1538  #endif
1539 #else
1540  case AF_INET:
1541  ENTER_EXCLUSIVE
1542  String::set(dst, dst_sz, inet_ntoa(((const struct sockaddr_in *)(addr))->sin_addr));
1543  LEAVE_EXCLUSIVE
1544  break;
1545 #endif
1546  default:
1547  res = NULL;
1548  }
1549  if(!res)
1550  return 0;
1551  size_t addr_len = strlen(res);
1552  dst = dst + addr_len;
1553  dst_sz -= addr_len;
1554 
1555 #if defined(AF_INET6)
1556  if(ipv6_brackets && dst_sz) {
1557  *dst++ = ']';
1558  dst_sz--;
1559  }
1560 #endif
1561 
1562  if(port && dst_sz) {
1563  *dst++ = ':';
1564  dst_sz--;
1565  snprintf(dst, dst_sz, "%u", getPort(addr));
1566  }
1567  return strlen(ret);
1568 }
1569 
1571 {
1572 #ifdef _MSWINDOWS_
1573  HANDLE pidH = GetCurrentProcess();
1574  HANDLE dupH;
1575 
1576  init();
1577  if(DuplicateHandle(pidH, reinterpret_cast<HANDLE>(s.so), pidH, &dupH, 0, FALSE, DUPLICATE_SAME_ACCESS))
1578  so = reinterpret_cast<SOCKET>(dupH);
1579  else
1580  so = INVALID_SOCKET;
1581 #else
1582  so = ::dup(s.so);
1583 #endif
1584  iowait = s.iowait;
1585  ioerr = 0;
1586 }
1587 
1589 {
1590  so = INVALID_SOCKET;
1591  iowait = Timer::inf;
1592  ioerr = 0;
1593 }
1594 
1596 {
1597  so = s;
1598  iowait = Timer::inf;
1599  ioerr = 0;
1600 }
1601 
1603 {
1604 #ifdef _MSWINDOWS_
1605  init();
1606 #endif
1607  assert(addr != NULL);
1608 
1609  while(addr) {
1610  so = ::socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
1611  socket_mapping(addr->ai_family, so);
1612  if(so != INVALID_SOCKET) {
1613  if(!::connect(so, addr->ai_addr, (socklen_t)addr->ai_addrlen))
1614  return;
1615  }
1616  addr = addr->ai_next;
1617  }
1618  so = INVALID_SOCKET;
1619  iowait = Timer::inf;
1620  ioerr = 0;
1621 }
1622 
1623 Socket::Socket(int family, int type, int protocol)
1624 {
1625  so = create(family, type, protocol);
1626  iowait = Timer::inf;
1627  ioerr = 0;
1628 }
1629 
1630 Socket::Socket(const char *iface, const char *port, int family, int type, int protocol)
1631 {
1632  assert(iface != NULL && *iface != 0);
1633  assert(port != NULL && *port != 0);
1634 
1635 #ifdef _MSWINDOWS_
1636  init();
1637 #endif
1638  family = setfamily(family, iface);
1639  so = create(iface, port, family, type, protocol);
1640  iowait = Timer::inf;
1641  ioerr = 0;
1642 }
1643 
1645 {
1646  socket_t so;
1647  struct addrinfo *res = *address;
1648  if(!res)
1649  return INVALID_SOCKET;
1650 
1651  so = create(res->ai_family, res->ai_socktype, res->ai_protocol);
1652  if(so == INVALID_SOCKET)
1653  return INVALID_SOCKET;
1654 
1655  if(connectto(so, res)) {
1656  release(so);
1657  return INVALID_SOCKET;
1658  }
1659  return so;
1660 }
1661 
1662 socket_t Socket::create(const char *iface, const char *port, int family, int type, int protocol)
1663 {
1664  assert(iface != NULL && *iface != 0);
1665  assert(port != NULL && *port != 0);
1666 
1667  struct addrinfo hint, *res;
1668  socket_t so;
1669  int reuse = 1;
1670 
1671 #ifdef _MSWINDOWS_
1672  Socket::init();
1673 #endif
1674 
1675  memset(&hint, 0, sizeof(hint));
1677  hint.ai_family = setfamily(family, iface);
1678  hint.ai_socktype = type;
1679  hint.ai_protocol = protocol;
1680 
1681 #if defined(AF_INET6) && defined(AI_V4MAPPED)
1682  if(hint.ai_family == AF_INET6 && !v6only)
1683  hint.ai_flags |= AI_V4MAPPED;
1684 #endif
1685 
1686 #if defined(AF_UNIX) && !defined(_MSWINDOWS_)
1687  if(iface && strchr(iface, '/')) {
1688  struct sockaddr_storage uaddr;
1689  socklen_t len = unixaddr((struct sockaddr_un *)&uaddr, iface);
1690  if(!type)
1691  type = SOCK_STREAM;
1692  so = create(AF_UNIX, type, 0);
1693  if(so == INVALID_SOCKET)
1694  return INVALID_SOCKET;
1695  if(::bind(so, (struct sockaddr *)&uaddr, len)) {
1696  release(so);
1697  return INVALID_SOCKET;
1698  }
1699  return so;
1700  };
1701 #endif
1702 
1703  if(iface && !strcmp(iface, "*"))
1704  iface = NULL;
1705 
1706  getaddrinfo(iface, port, &hint, &res);
1707  if(res == NULL)
1708  return INVALID_SOCKET;
1709 
1710  so = create(res->ai_family, res->ai_socktype, res->ai_protocol);
1711  if(so == INVALID_SOCKET) {
1712  freeaddrinfo(res);
1713  return INVALID_SOCKET;
1714  }
1715  setsockopt(so, SOL_SOCKET, SO_REUSEADDR, (caddr_t)&reuse, sizeof(reuse));
1716  if(res->ai_addr) {
1717  if(::bind(so, res->ai_addr, (socklen_t)res->ai_addrlen)) {
1718  release(so);
1719  so = INVALID_SOCKET;
1720  }
1721  }
1722  freeaddrinfo(res);
1723  return so;
1724 }
1725 
1727 {
1728  release();
1729 }
1730 
1731 socket_t Socket::create(int family, int type, int protocol)
1732 {
1733  socket_t so;
1734 #ifdef _MSWINDOWS_
1735  init();
1736 #endif
1737  so = ::socket(family, type, protocol);
1739  return so;
1740 }
1741 
1742 void Socket::cancel(void)
1743 {
1744  if(so != INVALID_SOCKET)
1745  ::shutdown(so, SHUT_RDWR);
1746 }
1747 
1749 {
1750  if(so != INVALID_SOCKET)
1751  ::shutdown(so, SHUT_RDWR);
1752 }
1753 
1755 {
1756 #ifdef _MSWINDOWS_
1757  ::closesocket(so);
1758 #else
1759  if(!::shutdown(so, SHUT_RDWR))
1760  ::close(so);
1761 #endif
1762 }
1763 
1765 {
1766  if(so != INVALID_SOCKET) {
1767 #ifdef _MSWINDOWS_
1768  ::closesocket(so);
1769 #else
1770  ::shutdown(so, SHUT_RDWR);
1771  ::close(so);
1772 #endif
1773  so = INVALID_SOCKET;
1774  }
1775  iowait = Timer::inf;
1776  ioerr = 0;
1777 }
1778 
1779 #ifdef _MSWINDOWS_
1780 int Socket::error(void)
1781 {
1782  switch(WSAGetLastError())
1783  {
1784  case WSANOTINITIALISED:
1785  case WSAENETDOWN:
1786  case WSASYSNOTREADY:
1787  return ENETDOWN;
1788  case WSAEFAULT:
1789  return EFAULT;
1790  case WSAEINTR:
1791  case WSAECANCELLED:
1792  case WSA_OPERATION_ABORTED:
1793  case WSA_IO_INCOMPLETE:
1794  case WSASYSCALLFAILURE:
1795  case WSA_E_CANCELLED:
1796  return EINTR;
1797  case WSA_IO_PENDING:
1798  case WSAEINPROGRESS:
1799  return EINPROGRESS;
1800  case WSAEINVAL:
1801  return EINVAL;
1802  case WSAEMFILE:
1803  return EMFILE;
1804  case WSAENETUNREACH:
1805  return ENETUNREACH;
1806  case WSAENOBUFS:
1807  case WSAETOOMANYREFS:
1808  case WSA_NOT_ENOUGH_MEMORY:
1809  return ENOMEM;
1810  case WSAEACCES:
1811  return EACCES;
1812  case WSAEBADF:
1813  case WSAENOTSOCK:
1814  case WSA_INVALID_HANDLE:
1815  return EBADF;
1816  case WSAEOPNOTSUPP:
1817  return ENOSYS;
1818  case WSAEWOULDBLOCK:
1819  case WSAEALREADY:
1820  return EAGAIN;
1821  case WSAENOPROTOOPT:
1822  return ENOPROTOOPT;
1823  case WSAEADDRINUSE:
1824  return EADDRINUSE;
1825  case WSAENETRESET:
1826  return ENETRESET;
1827  case WSAECONNABORTED:
1828  return ECONNABORTED;
1829  case WSAECONNRESET:
1830  return ECONNRESET;
1831  case WSAEISCONN:
1832  return EISCONN;
1833  case WSAENOTCONN:
1834  return ENOTCONN;
1835  case WSAESHUTDOWN:
1836  return ESHUTDOWN;
1837  case WSAETIMEDOUT:
1838  return ETIMEDOUT;
1839  case WSAECONNREFUSED:
1840  return ECONNREFUSED;
1841  case WSAEHOSTDOWN:
1842  return EHOSTDOWN;
1843  case WSAEHOSTUNREACH:
1844  return EHOSTUNREACH;
1845  }
1846  return EINVAL;
1847 }
1848 #else
1849 int Socket::error(void)
1850 {
1851  return errno;
1852 }
1853 #endif
1854 
1855 Socket::operator bool() const
1856 {
1857  if(so == INVALID_SOCKET)
1858  return false;
1859  return true;
1860 }
1861 
1862 bool Socket::operator!() const
1863 {
1864  if(so == INVALID_SOCKET)
1865  return true;
1866  return false;
1867 }
1868 
1870 {
1871  release();
1872  so = s;
1873  return *this;
1874 }
1875 
1876 size_t Socket::peek(void *data, size_t len) const
1877 {
1878  assert(data != NULL);
1879  assert(len > 0);
1880 
1881  if(iowait && iowait != Timer::inf && !Socket::wait(so, iowait))
1882  return 0;
1883 
1884  ssize_t rtn = ::recv(so, (caddr_t)data, 1, MSG_DONTWAIT | MSG_PEEK);
1885  if(rtn < 1)
1886  return 0;
1887  return (size_t)rtn;
1888 }
1889 
1890 ssize_t Socket::recvfrom(socket_t so, void *data, size_t len, int flags, struct sockaddr_storage *addr)
1891 {
1892  assert(data != NULL);
1893  assert(len > 0);
1894 
1895  socklen_t slen = sizeof(struct sockaddr_storage);
1896  return ::recvfrom(so, (caddr_t)data, (socksize_t)len, flags, (struct sockaddr *)addr, (socklen_t *)&slen);
1897 }
1898 
1899 size_t Socket::readfrom(void *data, size_t len, struct sockaddr_storage *from)
1900 {
1901  assert(data != NULL);
1902  assert(len > 0);
1903 
1904  // wait for input by timer if possible...
1905  if(iowait && iowait != Timer::inf && !Socket::wait(so, iowait))
1906  return 0;
1907 
1908  socklen_t slen = sizeof(struct sockaddr_storage);
1909  ssize_t result = ::recvfrom(so, (caddr_t)data, (socksize_t)len, 0, (struct sockaddr *)from, (socklen_t *)&slen);
1910 
1911  if(result < 0) {
1912  ioerr = Socket::error();
1913  return 0;
1914  }
1915  return (size_t)result;
1916 }
1917 
1918 size_t Socket::writeto(const void *data, size_t dlen, const struct sockaddr *dest)
1919 {
1920  assert(data != NULL);
1921  assert(len > 0);
1922 
1923  socklen_t slen = 0;
1924  if(dest)
1925  slen = len(dest);
1926 
1927  ssize_t result = ::sendto(so, (caddr_t)data, (socksize_t)dlen, MSG_NOSIGNAL, dest, (socklen_t)slen);
1928 
1929  if(result < 0) {
1930  ioerr = Socket::error();
1931  return 0;
1932  }
1933  return (size_t)result;
1934 }
1935 
1936 ssize_t Socket::sendto(socket_t so, const void *data, size_t dlen, int flags, const struct sockaddr *dest)
1937 {
1938  assert(data != NULL);
1939  assert(len > 0);
1940 
1941  socklen_t slen = 0;
1942  if(dest)
1943  slen = len(dest);
1944 
1945  return ::sendto(so, (caddr_t)data, (socksize_t)dlen, MSG_NOSIGNAL | flags, dest, (socklen_t)slen);
1946 }
1947 
1948 size_t Socket::writes(const char *str)
1949 {
1950  if(!str)
1951  return 0;
1952 
1953  if(!*str)
1954  return 0;
1955 
1956  return writeto(str, strlen(str), NULL);
1957 }
1958 
1959 size_t Socket::readline(char *data, size_t max)
1960 {
1961  assert(data != NULL);
1962  assert(max > 0);
1963 
1964  *data = 0;
1965 
1966  ssize_t result = Socket::readline(so, data, max, iowait);
1967  if(result < 0) {
1968  ioerr = Socket::error();
1969  return 0;
1970  }
1971  return (size_t)result;
1972 }
1973 
1975 {
1976  if(!s.data())
1977  return 0;
1978 
1979  ssize_t result = Socket::readline(so, s.data(), s.size() + 1, iowait);
1980  if(result < 0) {
1981  ioerr = Socket::error();
1982  s.clear();
1983  return 0;
1984  }
1985  String::fix(s);
1986  return (size_t)result;
1987 }
1988 
1990 {
1992  if(!buf)
1993  return stringref_t();
1994 
1995  ssize_t result = Socket::readline(so, buf->get(), buf->max() + 1, iowait);
1996  if(result < 0)
1997  return stringref_t();
1998 
1999  stringref_t out;
2000  out.assign(buf);
2001  return out;
2002 }
2003 
2004 ssize_t Socket::readline(socket_t so, char *data, size_t max, timeout_t timeout)
2005 {
2006  assert(data != NULL);
2007  assert(max > 0);
2008 
2009  bool crlf = false;
2010  bool nl = false;
2011  size_t nleft = max - 1; // leave space for null byte
2012  int nstat, c;
2013 
2014  if(max < 1)
2015  return -1;
2016 
2017  data[0] = 0;
2018  while(nleft && !nl) {
2019  if(timeout) {
2020  if(!wait(so, timeout))
2021  return 0;
2022  }
2023  nstat = ::recv(so, data, (socksize_t)nleft, MSG_PEEK);
2024  if(nstat < 0)
2025  return -1;
2026 
2027  if(nstat == 0)
2028  return (ssize_t)(max - nleft - 1);
2029 
2030  for(c = 0; c < nstat; ++c) {
2031  if(data[c] == '\n') {
2032  if(c > 0 && data[c - 1] == '\r')
2033  crlf = true;
2034  ++c;
2035  nl = true;
2036  break;
2037  }
2038  }
2039 
2040  nstat = ::recv(so, (caddr_t)data, c, 0);
2041  if(nstat < 0)
2042  break;
2043 
2044  if(crlf) {
2045  --nstat;
2046  data[nstat - 1] = '\n';
2047  }
2048 
2049  data += nstat;
2050  nleft -= nstat;
2051  }
2052 
2053  if(nl)
2054  --data;
2055 
2056  *data = 0;
2057  return ssize_t(max - nleft - 1);
2058 }
2059 
2060 int Socket::loopback(socket_t so, bool enable)
2061 {
2062  union {
2063  struct sockaddr_storage saddr;
2064  struct sockaddr_in inaddr;
2065  } us;
2066 
2067  struct sockaddr *addr = (struct sockaddr *)&us.saddr;
2068  int family;
2069  socklen_t len = sizeof(us.saddr);
2070  int opt = 0;
2071 
2072  if(enable)
2073  opt = 1;
2074 
2075  if(so == INVALID_SOCKET)
2076  return EBADF;
2077 
2078  ::getsockname(so, addr, &len);
2079  family = us.inaddr.sin_family;
2080  switch(family) {
2081  case AF_INET:
2082  if(!setsockopt(so, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&opt, sizeof(opt)))
2083  return 0;
2084  break;
2085 #if defined(AF_INET6) && defined(IPROTO_IPV6)
2086  case AF_INET6:
2087  if(!setsockopt(so, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *)&opt, sizeof(opt)))
2088  return 0;
2089 #endif
2090  }
2091  int err = Socket::error();
2092  if(!err)
2093  err = EIO;
2094  return err;
2095 }
2096 
2097 int Socket::ttl(socket_t so, uint8_t t)
2098 {
2099  union {
2100  struct sockaddr_storage saddr;
2101  struct sockaddr_in inaddr;
2102  } us;
2103 
2104  struct sockaddr *addr = (struct sockaddr *)&us.saddr;
2105  int family;
2106  socklen_t len = sizeof(us.saddr);
2107 
2108  if(so == INVALID_SOCKET)
2109  return EBADF;
2110 
2111  ::getsockname(so, addr, &len);
2112  family = us.inaddr.sin_family;
2113  switch(family) {
2114  case AF_INET:
2115  if(!setsockopt(so, IPPROTO_IP, IP_TTL, (char *)&t, sizeof(t)))
2116  return 0;
2117  break;
2118 #if defined(AF_INET6) && defined(IPPROTO_IPV6)
2119  case AF_INET6:
2120  if(!setsockopt(so, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (char *)&t, sizeof(t)))
2121  return 0;
2122 #endif
2123  }
2124  int err = Socket::error();
2125  if(!err)
2126  err = EIO;
2127  return err;
2128 }
2129 
2131 {
2132  if(so == INVALID_SOCKET)
2133  return EBADF;
2134 #ifdef SO_PRIORITY
2135  if(!setsockopt(so, SOL_SOCKET, SO_PRIORITY, (char *)&pri, (socklen_t)sizeof(pri)))
2136  return 0;
2137  int err = Socket::error();
2138  if(!err)
2139  err = EIO;
2140  return err;
2141 #else
2142  return ENOSYS;
2143 #endif
2144 }
2145 
2147 {
2148  if(so == INVALID_SOCKET)
2149  return EBADF;
2150 
2151 #ifdef SOL_IP
2152  if(!setsockopt(so, SOL_IP, IP_TOS,(char *)&ts, (socklen_t)sizeof(ts)))
2153  return 0;
2154 
2155  int err = Socket::error();
2156  if(!err)
2157  err = EIO;
2158  return err;
2159 #else
2160  return ENOSYS;
2161 #endif
2162 }
2163 
2164 int Socket::broadcast(socket_t so, bool enable)
2165 {
2166  if(so == INVALID_SOCKET)
2167  return EBADF;
2168  int opt = (enable ? 1 : 0);
2169  if(!::setsockopt(so, SOL_SOCKET, SO_BROADCAST,
2170  (char *)&opt, (socklen_t)sizeof(opt)))
2171  return 0;
2172 
2173  int err = Socket::error();
2174  if(!err)
2175  err = EIO;
2176  return err;
2177 }
2178 
2180 {
2181  if(so == INVALID_SOCKET)
2182  return EBADF;
2183 #if defined(TCP_NODELAY)
2184  int opt = 1;
2185  if(!::setsockopt(so, IPPROTO_TCP, TCP_NODELAY,
2186  (char *)&opt, (socklen_t)sizeof(opt)))
2187  return 0;
2188 #else
2189  return ENOSYS;
2190 #endif
2191  int err = Socket::error();
2192  if(!err)
2193  err = EIO;
2194  return err;
2195 }
2196 
2197 int Socket::keepalive(socket_t so, bool enable)
2198 {
2199  if(so == INVALID_SOCKET)
2200  return EBADF;
2201 #if defined(SO_KEEPALIVE) || defined(_MSWINDOWS_)
2202  int opt = (enable ? ~0 : 0);
2203  if(!::setsockopt(so, SOL_SOCKET, SO_KEEPALIVE, (char *)&opt, (socklen_t)sizeof(opt)))
2204  return 0;
2205  int err = Socket::error();
2206  if(!err)
2207  err = EIO;
2208  return err;
2209 #else
2210  return ENOSYS;
2211 #endif
2212 }
2213 
2215 {
2216  struct sockaddr_internet addr;
2217  socklen_t len = sizeof(addr);
2218  bool enable;
2219  int rtn;
2220 
2221  if(so == INVALID_SOCKET)
2222  return EBADF;
2223 
2224  if(ttl)
2225  enable = true;
2226  else
2227  enable = false;
2228 
2229  ::getsockname(so, (struct sockaddr *)&addr, &len);
2230  if(!enable)
2231  switch(addr.address.sa_family)
2232  {
2233  case AF_INET:
2234  memset(&addr.ipv4.sin_addr, 0, sizeof(addr.ipv4.sin_addr));
2235  break;
2236 #ifdef AF_INET6
2237  case AF_INET6:
2238  memset(&addr.ipv6.sin6_addr, 0, sizeof(addr.ipv6.sin6_addr));
2239  break;
2240 #endif
2241  default:
2242  break;
2243  }
2244  switch(addr.address.sa_family) {
2245 #if defined(AF_INET6) && defined(IPPROTO_IPV6)
2246  case AF_INET6:
2247  rtn = ::setsockopt(so, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *)&addr.ipv6.sin6_addr, sizeof(addr.ipv6.sin6_addr));
2248  if(!rtn)
2249  rtn = ::setsockopt(so, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&ttl, sizeof(ttl));
2250  if(rtn) {
2251  rtn = Socket::error();
2252  if(!rtn)
2253  rtn = EIO;
2254  }
2255  return rtn;
2256 #endif
2257  case AF_INET:
2258 #ifdef IP_MULTICAST_IF
2259  rtn = ::setsockopt(so, IPPROTO_IP, IP_MULTICAST_IF, (char *)&addr.ipv4.sin_addr, sizeof(addr.ipv4.sin_addr));
2260  if(!rtn)
2261  rtn = ::setsockopt(so, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl));
2262  if(rtn) {
2263  rtn = Socket::error();
2264  if(!rtn)
2265  rtn = EIO;
2266  }
2267  return rtn;
2268 #else
2269  return ENOSYS;
2270 #endif
2271  default:
2272  return ENOSYS;
2273  }
2274 }
2275 
2276 int Socket::join(const struct addrinfo *addr, const int ifindex)
2277 {
2278  int rtn = Socket::join(so, addr, ifindex);
2279  if(rtn)
2280  ioerr = rtn;
2281  return rtn;
2282 }
2283 
2284 int Socket::drop(const struct addrinfo *addr, const int ifindex)
2285 {
2286  int rtn = Socket::drop(so, addr, ifindex);
2287  if(rtn)
2288  ioerr = rtn;
2289  return rtn;
2290 }
2291 
2293 {
2294  bool mode = true;
2295 
2296  if(timeout < Timer::inf)
2297  mode = false;
2298 
2299  int rtn = Socket::blocking(so, mode);
2300  if(!rtn)
2301  iowait = timeout;
2302  else
2303  ioerr = rtn;
2304 
2305  return rtn;
2306 }
2307 
2308 int Socket::blocking(socket_t so, bool enable)
2309 {
2310  if(so == INVALID_SOCKET)
2311  return EBADF;
2312 
2313 #if defined(_MSWINDOWS_)
2314  unsigned long flag = (enable ? 0 : 1);
2315  if(!ioctlsocket(so, FIONBIO, &flag))
2316  return 0;
2317 
2318 #else
2319  long flags = fcntl(so, F_GETFL);
2320  if(enable)
2321  flags &=~ O_NONBLOCK;
2322  else
2323  flags |= O_NONBLOCK;
2324  if(!fcntl(so, F_SETFL, flags))
2325  return 0;
2326 #endif
2327  int err = Socket::error();
2328  if(!err)
2329  err = EIO;
2330  return err;
2331 }
2332 
2334 {
2335  union {
2336  struct sockaddr_storage saddr;
2337  struct sockaddr_in inaddr;
2338  } us;
2339 
2340  struct sockaddr *addr = (struct sockaddr *)&us.saddr;
2341  socklen_t len = sizeof(us.saddr);
2342 
2343 #if defined(_MSWINDOWS_)
2344  ::getsockname(so, addr, &len);
2345  int family = us.inaddr.sin_family;
2346  memset(addr, 0, sizeof(us.saddr));
2347  us.inaddr.sin_family = family;
2348 #else
2349  memset(addr, 0, sizeof(us.saddr));
2350  us.inaddr.sin_family = AF_UNSPEC;
2351 #endif
2352  if((size_t)len > sizeof(us.saddr))
2353  len = sizeof(us.saddr);
2354  if(so == INVALID_SOCKET)
2355  return EBADF;
2356  if(!::connect(so, addr, len))
2357  return 0;
2358  int err = Socket::error();
2359  if(!err)
2360  err = EIO;
2361  return err;
2362 }
2363 
2364 int Socket::join(socket_t so, const struct addrinfo *node, const int ifindex)
2365 {
2366  assert(node != NULL);
2367 
2368  struct multicast_internet mcast;
2369  struct sockaddr_internet addr;
2370  socklen_t len = sizeof(addr);
2371  const struct sockaddr_internet *target;
2372  int family;
2373  int rtn = 0;
2374 
2375  if(so == INVALID_SOCKET)
2376  return EBADF;
2377 
2378  ::getsockname(so, (struct sockaddr *)&addr, &len);
2379  while(!rtn && node && node->ai_addr) {
2380  target = (const struct sockaddr_internet *)node->ai_addr;
2381  family = node->ai_family;
2382  node = node->ai_next;
2383  if(family != addr.address.sa_family)
2384  continue;
2385  switch(addr.address.sa_family) {
2386 #if defined(AF_INET6) && defined(IPV6_ADD_MEMBERSHIP) && defined(IPPROTO_IPV6)
2387  case AF_INET6:
2388  mcast.ipv6.ipv6mr_interface = ifindex;
2389  memcpy(&mcast.ipv6.ipv6mr_multiaddr, &target->ipv6.sin6_addr, sizeof(target->ipv6.sin6_addr));
2390  rtn = ::setsockopt(so, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&mcast, sizeof(mcast.ipv6));
2391  break;
2392 #endif
2393 #if defined(IP_ADD_MEMBERSHIP)
2394  case AF_INET:
2395  mcast.ipv4.imr_interface.s_addr = INADDR_ANY;
2396  memcpy(&mcast.ipv4.imr_multiaddr, &target->ipv4.sin_addr, sizeof(target->ipv4.sin_addr));
2397  rtn = ::setsockopt(so, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&mcast, sizeof(mcast.ipv4));
2398  break;
2399 #endif
2400  default:
2401  return ENOSYS;
2402  }
2403  }
2404  if(rtn) {
2405  rtn = Socket::error();
2406  if(!rtn)
2407  rtn = EIO;
2408  }
2409  return rtn;
2410 }
2411 
2412 int Socket::drop(socket_t so, const struct addrinfo *node, const int ifindex)
2413 {
2414  assert(node != NULL);
2415 
2416  struct multicast_internet mcast;
2417  struct sockaddr_internet addr;
2418  socklen_t len = sizeof(addr);
2419  const struct sockaddr_internet *target;
2420  int family;
2421  int rtn = 0;
2422 
2423  if(so == INVALID_SOCKET)
2424  return EBADF;
2425 
2426  ::getsockname(so, (struct sockaddr *)&addr, &len);
2427  while(!rtn && node && node->ai_addr) {
2428  target = (const struct sockaddr_internet *)node->ai_addr;
2429  family = node->ai_family;
2430  node = node->ai_next;
2431 
2432  if(family != addr.address.sa_family)
2433  continue;
2434 
2435  switch(addr.address.sa_family) {
2436 #if defined(AF_INET6) && defined(IPV6_DROP_MEMBERSHIP) && defined(IPPROTO_IPV6)
2437  case AF_INET6:
2438  mcast.ipv6.ipv6mr_interface = ifindex;
2439  memcpy(&mcast.ipv6.ipv6mr_multiaddr, &target->ipv6.sin6_addr, sizeof(target->ipv6.sin6_addr));
2440  rtn = ::setsockopt(so, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, (char *)&mcast, sizeof(mcast.ipv6));
2441  break;
2442 #endif
2443 #if defined(IP_DROP_MEMBERSHIP)
2444  case AF_INET:
2445  mcast.ipv4.imr_interface.s_addr = INADDR_ANY;
2446  memcpy(&mcast.ipv4.imr_multiaddr, &target->ipv4.sin_addr, sizeof(target->ipv4.sin_addr));
2447  rtn = ::setsockopt(so, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *)&mcast, sizeof(mcast.ipv4));
2448  break;
2449 #endif
2450  default:
2451  return ENOSYS;
2452  }
2453  }
2454  if(rtn) {
2455  rtn = Socket::error();
2456  if(!rtn)
2457  rtn = EIO;
2458  }
2459  return rtn;
2460 }
2461 
2462 socket_t Socket::create(const struct addrinfo *node, int stype, int sprotocol)
2463 {
2464  assert(node != NULL);
2465 
2467  int sfamily = AF_UNSPEC;
2468  int cprotocol, ctype;
2469 
2470  while(node) {
2471  if(stype && node->ai_socktype && node->ai_socktype != stype)
2472  goto next;
2473 
2474  if(sprotocol && node->ai_protocol && node->ai_protocol != sprotocol)
2475  goto next;
2476 
2477  if(node->ai_family != sfamily) {
2478  if(so != INVALID_SOCKET)
2480  sfamily = node->ai_family;
2481  if(stype)
2482  ctype = stype;
2483  else
2484  ctype = node->ai_socktype;
2485  if(sprotocol)
2486  cprotocol = sprotocol;
2487  else
2488  cprotocol = node->ai_protocol;
2489  so = Socket::create(sfamily, ctype, cprotocol);
2490  }
2491  if(so != INVALID_SOCKET) {
2492  if(!::connect(so, node->ai_addr, (socklen_t)node->ai_addrlen))
2493  return so;
2494  }
2495 next:
2496  node = node->ai_next;
2497  }
2498  if(so != INVALID_SOCKET)
2500  return INVALID_SOCKET;
2501 }
2502 
2503 int Socket::connectto(struct addrinfo *node)
2504 {
2505  return (ioerr = connectto(so, node));
2506 }
2507 
2509 {
2510  return (ioerr = disconnect(so));
2511 }
2512 
2514 {
2515  assert(node != NULL);
2516 
2517  int rtn = -1;
2518  int socket_family;
2519 
2520  if(so == INVALID_SOCKET)
2521  return EBADF;
2522 
2523  socket_family = family(so);
2524 
2525  while(node) {
2526  if(node->ai_family == socket_family) {
2527  if(!::connect(so, node->ai_addr, (socklen_t)node->ai_addrlen)) {
2528  rtn = 0;
2529  goto exit;
2530  }
2531  }
2532  node = node->ai_next;
2533  }
2534 
2535 exit:
2536 #ifndef _MSWINDOWS_
2537  if(!rtn || errno == EINPROGRESS)
2538  return 0;
2539 #endif
2540  if(rtn) {
2541  rtn = Socket::error();
2542  if(!rtn)
2543  rtn = EIO;
2544  }
2545  return rtn;
2546 }
2547 
2549 {
2550  assert(so != INVALID_SOCKET);
2551 
2552  int opt;
2553  socklen_t slen = sizeof(opt);
2554 
2555  if(getsockopt(so, SOL_SOCKET, SO_ERROR, (caddr_t)&opt, &slen))
2556  return ENOSYS;
2557 
2558  return opt;
2559 }
2560 
2561 int Socket::sendwait(socket_t so, unsigned size)
2562 {
2563  assert(so != INVALID_SOCKET);
2564 
2565 #ifdef SO_SNDLOWAT
2566  if(!setsockopt(so, SOL_SOCKET, SO_SNDLOWAT, (caddr_t)&size, sizeof(size)))
2567  return 0;
2568  int err = Socket::error();
2569  if(!err)
2570  err = EIO;
2571  return err;
2572 #else
2573  return ENOSYS;
2574 #endif
2575 }
2576 
2577 int Socket::sendsize(socket_t so, unsigned size)
2578 {
2579  assert(so != INVALID_SOCKET);
2580 
2581 #ifdef SO_SNDBUF
2582  if(!setsockopt(so, SOL_SOCKET, SO_SNDBUF, (caddr_t)&size, sizeof(size)))
2583  return 0;
2584  int err = Socket::error();
2585  if(!err)
2586  err = EIO;
2587  return err;
2588 #else
2589  return ENOSYS;
2590 #endif
2591 }
2592 
2593 int Socket::recvsize(socket_t so, unsigned size)
2594 {
2595 #ifdef SO_RCVBUF
2596  if(!setsockopt(so, SOL_SOCKET, SO_RCVBUF, (caddr_t)&size, sizeof(size)))
2597  return 0;
2598  int err = Socket::error();
2599  if(!err)
2600  err = EIO;
2601  return err;
2602 #else
2603  return ENOSYS;
2604 #endif
2605 }
2606 
2607 bool Socket::connected(void) const
2608 {
2609  char buf;
2610 
2611  if(so == INVALID_SOCKET)
2612  return false;
2613 
2614  if(!wait())
2615  return true;
2616 
2617  if(::recv(so, &buf, 1, MSG_DONTWAIT | MSG_PEEK) < 1)
2618  return false;
2619 
2620  return true;
2621 }
2622 
2623 bool Socket::is_pending(unsigned qio)
2624 {
2625  if(pending() >= qio)
2626  return true;
2627 
2628  return false;
2629 }
2630 
2631 #ifdef _MSWINDOWS_
2632 unsigned Socket::pending(socket_t so)
2633 {
2634  u_long opt = 0;
2635  if(so == INVALID_SOCKET)
2636  return 0;
2637 
2638  ioctlsocket(so, FIONREAD, &opt);
2639  return (unsigned)opt;
2640 }
2641 
2642 #else
2644 {
2645  int opt;
2646  if(so == INVALID_SOCKET)
2647  return 0;
2648 
2649  if(::ioctl(so, FIONREAD, &opt))
2650  return 0;
2651  return (unsigned)opt;
2652 }
2653 
2654 #endif
2655 
2657 {
2658  socklen_t len = sizeof(struct sockaddr_storage);
2659  if(addr)
2660  return ::accept(so, (struct sockaddr *)addr, &len);
2661  else
2662  return ::accept(so, NULL, NULL);
2663 }
2664 
2666 {
2667  return wait(so, timeout);
2668 }
2669 
2671 {
2672  int status;
2673 
2674 #ifdef USE_POLL
2675  struct pollfd pfd;
2676 
2677  pfd.fd = so;
2678  pfd.revents = 0;
2679  pfd.events = POLLIN;
2680 
2681  if(so == INVALID_SOCKET)
2682  return false;
2683 
2684  status = 0;
2685  while(status < 1) {
2686  if(timeout == Timer::inf)
2687  status = ::poll(&pfd, 1, -1);
2688  else
2689  status = ::poll(&pfd, 1, timeout);
2690  if(status == -1 && errno == EINTR)
2691  continue;
2692  if(status < 0)
2693  return false;
2694  }
2695  if(pfd.revents & POLLIN)
2696  return true;
2697  return false;
2698 #else
2699  struct timeval tv;
2700  struct timeval *tvp = &tv;
2701  unsigned long to = (unsigned long)timeout;
2702  fd_set grp;
2703 
2704  if(so == INVALID_SOCKET)
2705  return false;
2706 
2707  if(timeout == Timer::inf)
2708  tvp = NULL;
2709  else {
2710  tv.tv_usec = (to % 1000) * 1000;
2711  tv.tv_sec = (to / 1000);
2712  }
2713 
2714  FD_ZERO(&grp);
2715  FD_SET(so, &grp);
2716  status = ::select((int)(so + 1), &grp, NULL, NULL, tvp);
2717  if(status < 1)
2718  return false;
2719  if(FD_ISSET(so, &grp))
2720  return true;
2721  return false;
2722 #endif
2723 }
2724 
2726 {
2727  int status;
2728 #ifdef USE_POLL
2729  struct pollfd pfd;
2730 
2731  pfd.fd = so;
2732  pfd.revents = 0;
2733  pfd.events = POLLOUT;
2734 
2735  if(so == INVALID_SOCKET)
2736  return false;
2737 
2738  status = 0;
2739  while(status < 1) {
2740  if(timeout == Timer::inf)
2741  status = ::poll(&pfd, 1, -1);
2742  else
2743  status = ::poll(&pfd, 1, timeout);
2744  if(status == -1 && errno == EINTR)
2745  continue;
2746  if(status < 0)
2747  return false;
2748  }
2749  if(pfd.revents & POLLOUT)
2750  return true;
2751  return false;
2752 #else
2753  struct timeval tv;
2754  struct timeval *tvp = &tv;
2755  unsigned long to = (unsigned long)timeout;
2756  fd_set grp;
2757 
2758  if(so == INVALID_SOCKET)
2759  return false;
2760 
2761  if(timeout == Timer::inf)
2762  tvp = NULL;
2763  else {
2764  tv.tv_usec = (to % 1000) * 1000;
2765  tv.tv_sec = to / 1000;
2766  }
2767 
2768  FD_ZERO(&grp);
2769  FD_SET(so, &grp);
2770  status = ::select((int)(so + 1), NULL, &grp, NULL, tvp);
2771  if(status < 1)
2772  return false;
2773  if(FD_ISSET(so, &grp))
2774  return true;
2775  return false;
2776 #endif
2777 }
2778 
2779 ListenSocket::ListenSocket(const char *iface, const char *svc, unsigned backlog, int family, int type, int protocol) :
2780 Socket()
2781 {
2782  if(!iface)
2783  iface = "*";
2784 
2785  assert(iface != NULL && *iface != 0);
2786  assert(svc != NULL && *svc != 0);
2787  assert(backlog > 0);
2788 
2789  so = create(iface, svc, backlog, family, type, protocol);
2790 }
2791 
2792 socket_t ListenSocket::create(const char *iface, const char *svc, unsigned backlog, int family, int type, int protocol)
2793 {
2794  if(!type)
2795  type = SOCK_STREAM;
2796 
2797  socket_t so = Socket::create(iface, svc, family, type, protocol);
2798 
2799  if(so == INVALID_SOCKET)
2800  return so;
2801 
2802  if(::listen(so, backlog)) {
2803  release(so);
2804  return INVALID_SOCKET;
2805  }
2806  return so;
2807 }
2808 
2810 {
2811  socklen_t len = sizeof(struct sockaddr_storage);
2812  if(addr)
2813  return ::accept(so, (struct sockaddr *)addr, &len);
2814  else
2815  return ::accept(so, NULL, NULL);
2816 }
2817 
2818 TCPServer::TCPServer(const char *address, const char *service, unsigned backlog) :
2819 ListenSocket(address, service, backlog)
2820 {
2821 }
2822 
2823 #ifdef _MSWINDOWS_
2824 #undef AF_UNIX
2825 #endif
2826 
2828 {
2829  assert(hint != NULL);
2830 
2831  union {
2832  struct sockaddr_storage st;
2833  struct sockaddr_in in;
2834  } us;
2835  struct sockaddr *sa = (struct sockaddr *)&us.st;
2836  socklen_t slen = sizeof(us.st);
2837 
2838  memset(hint, 0, sizeof(struct addrinfo));
2839  memset(sa, 0, sizeof(us.st));
2840  if(::getsockname(so, sa, &slen))
2841  return NULL;
2842  hint->ai_family = us.in.sin_family;
2843  slen = sizeof(hint->ai_socktype);
2844  getsockopt(so, SOL_SOCKET, SO_TYPE, (caddr_t)&hint->ai_socktype, &slen);
2845  return hint;
2846 }
2847 
2848 int Socket::type(const socket_t so)
2849 {
2850  int sotype;
2851  socklen_t slen = sizeof(sotype);
2852  if(getsockopt(so, SOL_SOCKET, SO_TYPE, (caddr_t)&sotype, &slen))
2853  return 0;
2854  return sotype;
2855 }
2856 
2857 bool Socket::ccid(socket_t so, uint8_t ccid)
2858 {
2859  uint8_t ccids[4];
2860  socklen_t len = sizeof(ccids);
2861  bool supported = false;
2862 
2863  // maybe also not dccp socket...
2864  if(getsockopt(so, SOL_DCCP, DCCP_SOCKOPT_AVAILABLE_CCIDS, (char *)&ccids, &len) < 0)
2865  return false;
2866 
2867  for(unsigned pos = 0; pos < sizeof(ccids); ++pos) {
2868  if(ccid == ccids[pos]) {
2869  supported = true;
2870  break;
2871  }
2872  }
2873 
2874  if(!supported)
2875  return false;
2876 
2877  if(setsockopt(so, SOL_DCCP, DCCP_SOCKOPT_CCID, (char *)&ccid, sizeof(ccid)) < 0)
2878  return false;
2879 
2880  return true;
2881 }
2882 
2883 unsigned Socket::segsize(socket_t so, unsigned size)
2884 {
2885 #ifdef IP_MTU
2886  socklen_t alen = sizeof(size);
2887 #endif
2888 
2889  switch(type(so)) {
2890  case SOCK_STREAM:
2891 #ifdef TCP_MAXSEG
2892  if(size)
2893  setsockopt(so, IPPROTO_TCP, TCP_MAXSEG, (char *)&size, sizeof(size));
2894 #endif
2895  break;
2896  case SOCK_DCCP:
2897 #ifdef DCCP_MAXSEG
2898  if(size)
2899  setsockopt(so, IPPROTO_DCCP, DCCP_MAXSEG, (char *)&size, sizeof(size));
2900 #endif
2901  break;
2902  }
2903 #ifdef IP_MTU
2904  getsockopt(so, IPPROTO_IP, IP_MTU, &size, &alen);
2905 #else
2906  size = 0;
2907 #endif
2908  return size;
2909 }
2910 
2911 char *Socket::hostname(const struct sockaddr *sa, char *buf, size_t max)
2912 {
2913  assert(sa != NULL);
2914  assert(buf != NULL);
2915  assert(max > 0);
2916 
2917  socklen_t sl;
2918 
2919 #ifdef AF_UNIX
2920  const struct sockaddr_un *un = (const struct sockaddr_un *)sa;
2921 #endif
2922 
2923  switch(sa->sa_family) {
2924 #ifdef AF_UNIX
2925  case AF_UNIX:
2926  if(max > sizeof(un->sun_path))
2927  max = sizeof(un->sun_path);
2928  else
2929  --max;
2930  strncpy(buf, un->sun_path, max);
2931  buf[max] = 0;
2932  return buf;
2933 #endif
2934  case AF_INET:
2935  sl = sizeof(struct sockaddr_in);
2936  break;
2937 #ifdef AF_INET6
2938  case AF_INET6:
2939  sl = sizeof(struct sockaddr_in6);
2940  break;
2941 #endif
2942  default:
2943  return NULL;
2944  }
2945 
2946  if(getnameinfo(sa, (socklen_t)sl, buf, (socksize_t)max, NULL, 0, NI_NOFQDN))
2947  return NULL;
2948 
2949  return buf;
2950 }
2951 
2952 socklen_t Socket::query(socket_t so, struct sockaddr_storage *sa, const char *host, const char *svc)
2953 {
2954  assert(sa != NULL);
2955  assert(host != NULL && *host != 0);
2956  assert(svc != NULL && *svc != 0);
2957 
2958  socklen_t len = 0;
2959  struct addrinfo hint, *res = NULL;
2960 
2961 #ifdef AF_UNIX
2962  if(strchr(host, '/'))
2963  return unixaddr((struct sockaddr_un *)sa, host);
2964 #endif
2965 
2966  if(!hinting(so, &hint) || !svc)
2967  return 0;
2968 
2969  if(getaddrinfo(host, svc, &hint, &res) || !res)
2970  goto exit;
2971 
2972  memcpy(sa, res->ai_addr, res->ai_addrlen);
2973  len = (socklen_t)res->ai_addrlen;
2974 
2975 exit:
2976  if(res)
2977  freeaddrinfo(res);
2978  return len;
2979 }
2980 
2981 int Socket::bindto(socket_t so, const struct sockaddr *iface)
2982 {
2983  if(!::bind(so, iface, len(iface)))
2984  return 0;
2985  return Socket::error();
2986 }
2987 
2988 int Socket::listento(socket_t so, const struct sockaddr *iface, int backlog)
2989 {
2990  if(::bind(so, iface, len(iface)))
2991  return Socket::error();
2992  if(::listen(so, backlog))
2993  return Socket::error();
2994  return 0;
2995 }
2996 
2997 int Socket::bindto(socket_t so, const char *host, const char *svc, int protocol)
2998 {
2999  assert(so != INVALID_SOCKET);
3000  assert(host != NULL && *host != 0);
3001  assert(svc != NULL && *svc != 0);
3002 
3003  int rtn = -1;
3004  int reuse = 1;
3005 
3006  struct addrinfo hint, *res = NULL;
3007 
3008  setsockopt(so, SOL_SOCKET, SO_REUSEADDR, (caddr_t)&reuse, sizeof(reuse));
3009 
3010 #ifdef AF_UNIX
3011  if(host && strchr(host, '/')) {
3012  struct sockaddr_storage uaddr;
3013  socklen_t len = unixaddr((struct sockaddr_un *)&uaddr, host);
3014  rtn = ::bind(so, (struct sockaddr *)&uaddr, len);
3015  goto exit;
3016  };
3017 #endif
3018 
3019  if(!hinting(so, &hint) || !svc)
3020  return ENOSYS;
3021 
3022  hint.ai_protocol = protocol;
3023  if(host && !strcmp(host, "*"))
3024  host = NULL;
3025 
3026 #if defined(SO_BINDTODEVICE) && !defined(__QNX__)
3027  if(host && !strchr(host, '.') && !strchr(host, ':')) {
3028  struct ifreq ifr;
3029  memset(&ifr, 0, sizeof(ifr));
3030  strncpy(ifr.ifr_ifrn.ifrn_name, host, IFNAMSIZ);
3031  ifr.ifr_name[IFNAMSIZ - 1] = '\0';
3032  setsockopt(so, SOL_SOCKET, SO_BINDTODEVICE, &ifr, sizeof(ifr));
3033  host = NULL;
3034  }
3035 #endif
3036 
3038 
3039 #if defined(AF_INET6) && defined(AI_V4MAPPED)
3040  if(hint.ai_family == AF_INET6 && !v6only)
3041  hint.ai_flags |= AI_V4MAPPED;
3042 #endif
3043 
3044  rtn = getaddrinfo(host, svc, &hint, &res);
3045  if(rtn)
3046  goto exit;
3047 
3048  rtn = ::bind(so, res->ai_addr, (socklen_t)res->ai_addrlen);
3049 exit:
3050  if(res)
3051  freeaddrinfo(res);
3052  if(rtn)
3053  rtn = Socket::error();
3054  return rtn;
3055 }
3056 
3057 unsigned Socket::keyhost(const struct sockaddr *addr, unsigned keysize)
3058 {
3059  assert(addr != NULL);
3060  assert(keysize > 0);
3061 
3062  unsigned key = 0;
3063  caddr_t cp = NULL;
3064  unsigned len;
3065 switch(addr->sa_family) {
3066 #ifdef AF_INET6
3067  case AF_INET6:
3068  cp = (caddr_t)(&((const struct sockaddr_in6 *)(addr))->sin6_addr);
3069  len = 16;
3070  break;
3071 #endif
3072  case AF_INET:
3073  cp = (caddr_t)(&((const struct sockaddr_in *)(addr))->sin_addr);
3074  len = 4;
3075  break;
3076  default:
3077  return 0;
3078  }
3079  while(len--) {
3080  key = key << 1;
3081  key ^= cp[len];
3082  }
3083  return key % keysize;
3084 }
3085 
3086 unsigned Socket::keyindex(const struct sockaddr *addr, unsigned keysize)
3087 {
3088  assert(addr != NULL);
3089  assert(keysize > 0);
3090 
3091  unsigned key = 0;
3092  caddr_t cp = NULL;
3093  unsigned len;
3094 switch(addr->sa_family) {
3095 #ifdef AF_INET6
3096  case AF_INET6:
3097  cp = (caddr_t)(&((const struct sockaddr_in6 *)(addr))->sin6_addr);
3098  len = 16;
3099  key = port(addr);
3100  break;
3101 #endif
3102  case AF_INET:
3103  cp = (caddr_t)(&((const struct sockaddr_in *)(addr))->sin_addr);
3104  len = 4;
3105  key = port(addr);
3106  break;
3107  default:
3108  return 0;
3109  }
3110  while(len--) {
3111  key = key << 1;
3112  key ^= cp[len];
3113  }
3114  return key % keysize;
3115 }
3116 
3117 in_port_t Socket::port(const struct sockaddr *addr)
3118 {
3119  if(!addr)
3120  return 0;
3121 
3122  switch(addr->sa_family) {
3123 #ifdef AF_INET6
3124  case AF_INET6:
3125  return ntohs(((const struct sockaddr_in6 *)(addr))->sin6_port);
3126 #endif
3127  case AF_INET:
3128  return ntohs(((const struct sockaddr_in *)(addr))->sin_port);
3129  }
3130  return 0;
3131 }
3132 
3133 char *Socket::query(const struct sockaddr *addr, char *name, socklen_t size)
3134 {
3135  assert(addr != NULL);
3136  assert(name != NULL);
3137 
3138 #ifdef _MSWINDOWS_
3139  DWORD slen = size;
3140 #endif
3141 
3142  *name = 0;
3143  if(!addr)
3144  return NULL;
3145 
3146  switch(addr->sa_family) {
3147 #ifdef AF_UNIX
3148  case AF_UNIX:
3149  String::set(name, size, ((const struct sockaddr_un *)(addr))->sun_path);
3150  return name;
3151 #endif
3152 #ifdef _MSWINDOWS_
3153 #ifdef AF_INET6
3154  case AF_INET6:
3155  struct sockaddr_in6 saddr6;
3156  memcpy(&saddr6, addr, sizeof(saddr6));
3157  saddr6.sin6_port = 0;
3158  WSAAddressToString((struct sockaddr *)&saddr6, sizeof(saddr6), NULL, name, &slen);
3159  return name;
3160 #endif
3161  case AF_INET:
3162  struct sockaddr_in saddr;
3163  memcpy(&saddr, addr, sizeof(saddr));
3164  saddr.sin_port = 0;
3165  WSAAddressToString((struct sockaddr *)&saddr, sizeof(saddr), NULL, name, &slen);
3166  return name;
3167 #else
3168 #ifdef HAVE_INET_NTOP
3169 #ifdef AF_INET6
3170  case AF_INET6:
3171  inet_ntop(addr->sa_family, &((const struct sockaddr_in6 *)(addr))->sin6_addr, name, size);
3172  return name;
3173 #endif
3174  case AF_INET:
3175  inet_ntop(addr->sa_family, &((const struct sockaddr_in *)(addr))->sin_addr, name, size);
3176  return name;
3177 #else
3178  case AF_INET:
3179  ENTER_EXCLUSIVE
3180  String::set(name, size, inet_ntoa(((const struct sockaddr_in *)(addr))->sin_addr));
3181  LEAVE_EXCLUSIVE
3182  return name;
3183 #endif
3184 #endif
3185  }
3186  return NULL;
3187 }
3188 
3189 int Socket::via(struct sockaddr *iface, const struct sockaddr *dest, socklen_t size)
3190 {
3191  assert(iface != NULL);
3192  assert(dest != NULL);
3193 
3194  int rtn = -1;
3196  socklen_t slen = len(dest);
3197 
3198  if(size)
3199  memset(iface, 0, size);
3200 
3201  if(size && size < slen)
3202  return ENOMEM;
3203 
3204  iface->sa_family = AF_UNSPEC;
3205  switch(dest->sa_family) {
3206 #ifdef AF_INET6
3207  case AF_INET6:
3208 #endif
3209  case AF_INET:
3210  so = ::socket(dest->sa_family, SOCK_DGRAM, 0);
3211  if((socket_t)so == INVALID_SOCKET)
3212  return -1;
3213  socket_mapping(dest->sa_family, so);
3214  if(!::connect(so, dest, slen))
3215  rtn = ::getsockname(so, iface, &slen);
3216  break;
3217  default:
3218  return ENOSYS;
3219  }
3220  switch(iface->sa_family) {
3221  case AF_INET:
3222  ((struct sockaddr_in*)(iface))->sin_port = 0;
3223  break;
3224 #ifdef AF_INET6
3225  case AF_INET6:
3226  ((struct sockaddr_in6*)(iface))->sin6_port = 0;
3227  break;
3228 #endif
3229  }
3230 
3231  if((socket_t)so != INVALID_SOCKET) {
3232 #ifdef _MSWINDOWS_
3233  ::closesocket(so);
3234 #else
3235  ::shutdown(so, SHUT_RDWR);
3236  ::close(so);
3237 #endif
3238  }
3239  if(rtn)
3240  rtn = Socket::error();
3241  return rtn;
3242 }
3243 
3244 bool Socket::eq_subnet(const struct sockaddr *s1, const struct sockaddr *s2)
3245 {
3246  assert(s1 != NULL && s2 != NULL);
3247 
3248  uint8_t *a1, *a2;
3249  if(s1->sa_family != s2->sa_family)
3250  return false;
3251 
3252  if(s1->sa_family != AF_INET)
3253  return true;
3254 
3255  a1 = (uint8_t *)&(((const struct sockaddr_in *)(s1))->sin_addr);
3256  a2 = (uint8_t *)&(((const struct sockaddr_in *)(s1))->sin_addr);
3257 
3258  if(*a1 == *a2 && *a1 < 128)
3259  return true;
3260 
3261  if(*a1 != *a2)
3262  return false;
3263 
3264  if(*a1 > 127 && *a1 < 192 && a1[1] == a2[1])
3265  return true;
3266 
3267  if(a1[1] != a2[1])
3268  return false;
3269 
3270  if(a1[2] != a2[2])
3271  return false;
3272 
3273  return true;
3274 }
3275 
3276 unsigned Socket::store(struct sockaddr_storage *storage, const struct sockaddr *address)
3277 {
3278  if(storage == NULL || address == NULL)
3279  return 0;
3280 
3281  memset(storage, 0, sizeof(struct sockaddr_storage));
3282  return copy((struct sockaddr *)storage, address);
3283 }
3284 
3285 unsigned Socket::store(struct sockaddr_internet *storage, const struct sockaddr *address)
3286 {
3287  if(storage == NULL || address == NULL)
3288  return 0;
3289 
3290  memset(storage, 0, sizeof(struct sockaddr_internet));
3291  socklen_t slen = len(address);
3292  memcpy(storage, address, slen);
3293  return slen;
3294 }
3295 
3296 unsigned Socket::copy(struct sockaddr *s1, const struct sockaddr *s2)
3297 {
3298  if(s1 == NULL || s2 == NULL)
3299  return 0;
3300 
3301  socklen_t slen = len(s1);
3302  if(slen > 0) {
3303  memcpy(s1, s2, slen);
3304  return slen;
3305  }
3306  return 0;
3307 }
3308 
3309 bool Socket::eq_host(const struct sockaddr *s1, const struct sockaddr *s2)
3310 {
3311  assert(s1 != NULL && s2 != NULL);
3312 
3313  if(s1->sa_family != s2->sa_family)
3314  return false;
3315 
3316  switch(s1->sa_family) {
3317  case AF_INET:
3318  if(memcmp(&(((const struct sockaddr_in *)s1)->sin_addr),
3319  &(((const struct sockaddr_in *)s2)->sin_addr), 4))
3320  return false;
3321 
3322  return true;
3323 #ifdef AF_INET6
3324  case AF_INET6:
3325  if(memcmp(&(((const struct sockaddr_in6 *)s1)->sin6_addr),
3326  &(((const struct sockaddr_in6 *)s2)->sin6_addr), 4))
3327  return false;
3328 
3329  return true;
3330 #endif
3331  default:
3332  if(memcmp(s1, s2, len(s1)))
3333  return false;
3334  return true;
3335  }
3336  return false;
3337 }
3338 
3339 
3340 bool Socket::equal(const struct sockaddr *s1, const struct sockaddr *s2)
3341 {
3342  assert(s1 != NULL && s2 != NULL);
3343 
3344  if(s1->sa_family != s2->sa_family)
3345  return false;
3346 
3347  switch(s1->sa_family) {
3348  case AF_INET:
3349  if(memcmp(&(((const struct sockaddr_in *)s1)->sin_addr),
3350  &(((const struct sockaddr_in *)s2)->sin_addr), 4))
3351  return false;
3352 
3353  if(!((const struct sockaddr_in *)s1)->sin_port || !((const struct sockaddr_in *)s2)->sin_port)
3354  return true;
3355 
3356  if(((const struct sockaddr_in *)s1)->sin_port != ((const struct sockaddr_in *)s2)->sin_port)
3357  return false;
3358 
3359  return true;
3360 #ifdef AF_INET6
3361  case AF_INET6:
3362  if(memcmp(&(((const struct sockaddr_in6 *)s1)->sin6_addr),
3363  &(((const struct sockaddr_in6 *)s2)->sin6_addr), 4))
3364  return false;
3365 
3366  if(!((const struct sockaddr_in6 *)s1)->sin6_port || !((const struct sockaddr_in6 *)s2)->sin6_port)
3367  return true;
3368 
3369  if(((const struct sockaddr_in6 *)s1)->sin6_port != ((const struct sockaddr_in6 *)s2)->sin6_port)
3370  return false;
3371 
3372  return true;
3373 #endif
3374  default:
3375  if(memcmp(s1, s2, len(s1)))
3376  return false;
3377  return true;
3378  }
3379  return false;
3380 }
3381 
3382 size_t Socket::printf(const char *format, ...)
3383 {
3384  assert(format != NULL);
3385 
3386  char buf[1024];
3387  va_list args;
3388 
3389  va_start(args, format);
3390  vsnprintf(buf, sizeof(buf), format, args);
3391  va_end(args);
3392 
3393  return writes(buf);
3394 }
3395 
3396 ssize_t Socket::printf(socket_t so, const char *format, ...)
3397 {
3398  assert(format != NULL);
3399 
3400  char buf[536];
3401  va_list args;
3402 
3403  va_start(args, format);
3404  vsnprintf(buf, sizeof(buf), format, args);
3405  va_end(args);
3406 
3407  return sendto(so, buf, strlen(buf), 0, NULL);
3408 }
3409 
3410 socklen_t Socket::len(const struct sockaddr *sa)
3411 {
3412  if(!sa)
3413  return 0;
3414 
3415  switch(sa->sa_family)
3416  {
3417  case AF_INET:
3418  return sizeof(sockaddr_in);
3419 #ifdef AF_INET6
3420  case AF_INET6:
3421  return sizeof(sockaddr_in6);
3422 #endif
3423  default:
3424  return sizeof(sockaddr_storage);
3425  }
3426 }
3427 
3429 {
3430  assert(so != INVALID_SOCKET);
3431 
3432 #ifndef _MSWINDOWS_
3433  union {
3434  struct sockaddr_storage saddr;
3435  struct sockaddr_in inaddr;
3436  } us;
3437 
3438  socklen_t len = sizeof(us.saddr);
3439  struct sockaddr *addr = (struct sockaddr *)(&us.saddr);
3440  if(::getsockname(so, addr, &len))
3441  return AF_UNSPEC;
3442 
3443  return us.inaddr.sin_family;
3444 #else
3445  // getsockname doesn't work on unbound windows sockets
3446  WSAPROTOCOL_INFO info;
3447  socklen_t len = sizeof(info);
3448  if(getsockopt(so, SOL_SOCKET, SO_PROTOCOL_INFO, (char *) &info, &len))
3449  return AF_UNSPEC;
3450 
3451  return info.iAddressFamily;
3452 #endif
3453 }
3454 
3455 bool Socket::is_null(const char *str)
3456 {
3457  assert(str != NULL);
3458 
3459  while(*str && strchr("0:.*", *str) != NULL)
3460  ++str;
3461 
3462  // allow field separation...
3463  if(*str <= ' ')
3464  return true;
3465 
3466  if(*str)
3467  return false;
3468 
3469  return true;
3470 }
3471 
3472 bool Socket::is_numeric(const char *str)
3473 {
3474  assert(str != NULL);
3475 
3476  // if raw ipv6, then we can just exit, no chance to confuse with names
3477  if(strchr(str, ':'))
3478  return true;
3479 
3480  while(*str && strchr("0123456789.", *str) != NULL)
3481  ++str;
3482 
3483  // allow field separators
3484  if(*str <= ' ')
3485  return true;
3486 
3487  if(*str)
3488  return false;
3489 
3490  return true;
3491 }
3492 
3494 {
3495  socklen_t slen = sizeof(sockaddr_storage);
3496  memset(addr, 0, slen);
3497  return ::getsockname(sock, (struct sockaddr *)addr, &slen);
3498 }
3499 
3501 {
3502  socklen_t slen = sizeof(sockaddr_storage);
3503  memset(addr, 0, slen);
3504  return ::getpeername(sock, (struct sockaddr *)addr, &slen);
3505 }
3506 
3507 String str(Socket& so, size_t size)
3508 {
3509  String s(size);
3510  so.readline(s.data(), s.size());
3511  String::fix(s);
3512  return s;
3513 }
3514 
3515 const struct sockaddr *linked_sockaddr_operations::_getaddrinfo(const struct addrinfo *list) const
3516 {
3517  return list->ai_addr;
3518 }
3519 
3520 const struct addrinfo *linked_sockaddr_operations::_nextaddrinfo(const struct addrinfo *list) const
3521 {
3522  if(!list)
3523  return NULL;
3524 
3525  return list->ai_next;
3526 }
3527 
3529 {
3530  if(!list)
3531  return INVALID_SOCKET;
3532 
3533  return ::socket(list->ai_family, list->ai_socktype, list->ai_protocol);
3534 }
3535 
3536 } // namespace ucommon
ucommon::Socket::keyindex
static unsigned keyindex(const struct sockaddr *address, unsigned size)
Definition: socket.cpp:3086
ucommon::Socket::iowait
timeout_t iowait
Definition: socket.h:332
ucommon::Socket::segsize
static unsigned segsize(socket_t socket, unsigned size=0)
Definition: socket.cpp:2883
O_NONBLOCK
#define O_NONBLOCK
Definition: socket.cpp:64
ucommon::getnameinfo
static int getnameinfo(const struct sockaddr *addr, socklen_t len, char *host, size_t hostlen, char *service, size_t servlen, int flags)
Definition: socket.cpp:142
ucommon::Socket::type
int type(void) const
Definition: socket.h:1093
ucommon::String::clear
void clear(size_t offset)
Definition: string.cpp:933
ucommon::Socket::address::find
struct sockaddr * find(const struct sockaddr *addr) const
Definition: socket.cpp:1476
ucommon::Socket::sendwait
int sendwait(unsigned size)
Definition: socket.h:1053
ucommon::Socket::join
int join(const struct addrinfo *list, const int ifindex=0)
Definition: socket.cpp:2276
ucommon::Socket::eq_subnet
static bool eq_subnet(const struct sockaddr *address1, const struct sockaddr *address2)
Definition: socket.cpp:3244
ucommon::Socket::local
static int local(socket_t socket, struct sockaddr_storage *address)
Definition: socket.cpp:3493
INADDR_LOOPBACK
#define INADDR_LOOPBACK
Definition: socket.cpp:74
ucommon::Socket::error
static int error(void)
Definition: socket.cpp:1849
export.h
ucommon::freeaddrinfo
static void freeaddrinfo(struct addrinfo *aip)
Definition: socket.cpp:129
ucommon::LinkedObject::count
static unsigned count(const LinkedObject *root)
Definition: linked.cpp:226
ucommon::Socket::address::loopback
static sockaddr_storage loopback(int family)
Definition: socket.cpp:1395
SOCK_DCCP
#define SOCK_DCCP
Definition: socket.h:75
ucommon::Socket
Definition: socket.h:327
ucommon::bitcount
static unsigned bitcount(bit_t *bits, unsigned len)
Definition: socket.cpp:483
ucommon::stringref_t
typeref< Type::Chars > stringref_t
Definition: typeref.h:743
ucommon::Socket::tos
int tos(int type)
Definition: socket.h:1123
ucommon::Socket::disconnect
int disconnect(void)
Definition: socket.cpp:2508
out
static shell::stringopt out('o', "--output", _TEXT("output file"), "filename", "-")
ucommon::Socket::address::list
struct addrinfo * list
Definition: socket.h:367
AI_NUMERICHOST
#define AI_NUMERICHOST
Definition: socket.cpp:102
ucommon::Socket::Socket
Socket()
Definition: socket.cpp:1588
AI_NUMERICSERV
#define AI_NUMERICSERV
Definition: socket.cpp:103
ucommon::Socket::err
int err(void) const
Definition: socket.h:919
ucommon::Socket::ttl
int ttl(uint8_t time)
Definition: socket.h:1035
ucommon::String::fix
static void fix(String &object)
Definition: string.cpp:1375
ucommon
Definition: access.cpp:23
ucommon::Socket::address::setPort
void setPort(in_port_t port)
Definition: socket.cpp:1149
ucommon::Socket::address::any
static sockaddr_storage any(int family)
Definition: socket.cpp:1387
ucommon::hostmutex
static mutex hostmutex
Definition: socket.cpp:127
ucommon::Socket::address::set
void set(const char *hostname, const char *service=NULL, int type=SOCK_STREAM)
Definition: socket.cpp:1449
addrinfo::ai_addrlen
size_t ai_addrlen
Definition: socket.cpp:88
DCCP_SOCKOPT_CCID
#define DCCP_SOCKOPT_CCID
Definition: socket.h:84
ucommon::Socket::keyhost
static unsigned keyhost(const struct sockaddr *address, unsigned size)
Definition: socket.cpp:3057
sockaddr_storage
Definition: socket.h:129
ucommon::Socket::~Socket
virtual ~Socket()
Definition: socket.cpp:1726
ucommon::Socket::sendsize
int sendsize(unsigned size)
Definition: socket.h:1044
ucommon::bit_t
uint8_t bit_t
Definition: socket.cpp:109
ucommon::String
Definition: string.h:78
result
static void result(const char *path, int code)
Definition: mdsum.cpp:35
ucommon::Socket::bindto
static int bindto(socket_t socket, const char *address, const char *service, int protocol=0)
Definition: socket.cpp:2997
timeout_t
unsigned long timeout_t
Definition: platform.h:453
NI_NUMERICHOST
#define NI_NUMERICHOST
Definition: socket.cpp:94
ucommon::Socket::keepalive
int keepalive(bool enable)
Definition: socket.h:991
IPPROTO_DCCP
#define IPPROTO_DCCP
Definition: socket.h:78
MSG_NOSIGNAL
#define MSG_NOSIGNAL
Definition: socket.cpp:62
ucommon::Socket::address::operator=
address & operator=(const address &rhs)
Definition: socket.cpp:919
ucommon::Socket::operator=
Socket & operator=(socket_t socket)
Definition: socket.cpp:1869
ucommon::Socket::recvfrom
static ssize_t recvfrom(socket_t socket, void *buffer, size_t size, int flags=0, struct sockaddr_storage *address=NULL)
Definition: socket.cpp:1890
ucommon::linked_sockaddr_operations::_getaddrinfo
const struct sockaddr * _getaddrinfo(const struct addrinfo *addrinfo) const
Definition: socket.cpp:3515
ucommon::cidr
Definition: socket.h:167
ucommon::Socket::remote
static int remote(socket_t socket, struct sockaddr_storage *address)
Definition: socket.cpp:3500
ucommon::Socket::store
static unsigned store(struct sockaddr_storage *storage, const struct sockaddr *address)
Definition: socket.cpp:3276
DCCP_SOCKOPT_AVAILABLE_CCIDS
#define DCCP_SOCKOPT_AVAILABLE_CCIDS
Definition: socket.h:83
ucommon::setfamily
static int setfamily(int family, const char *host)
Definition: socket.cpp:421
ucommon::copy
T copy(const T &src)
Definition: generics.h:395
caddr_t
#define caddr_t
Definition: file.h:86
multicast_internet
Definition: socket.cpp:71
ucommon::typeref::value
Definition: typeref.h:329
socket_t
int socket_t
Definition: platform.h:414
ucommon::Socket::blocking
int blocking(bool enable)
Definition: socket.h:1000
__THROW_RUNTIME
#define __THROW_RUNTIME(x)
Definition: platform.h:51
ucommon::Socket::so
socket_t so
Definition: socket.h:330
port
static shell::numericopt port('p', "--port", _TEXT("port to use"), "port", 0)
ucommon::Socket::operator!
bool operator!() const
Definition: socket.cpp:1862
ucommon::Socket::connectto
int connectto(struct addrinfo *list)
Definition: socket.cpp:2503
ucommon::clear
T & clear(T &o)
Definition: generics.h:416
AI_PASSIVE
#define AI_PASSIVE
Definition: socket.cpp:100
ucommon::Socket::ccid
static bool ccid(socket_t socket, uint8_t id)
Definition: socket.cpp:2857
ucommon::Socket::v4mapping
static void v4mapping(bool enable)
Definition: socket.cpp:536
ucommon::Socket::sendto
static ssize_t sendto(socket_t socket, const void *buffer, size_t size, int flags=0, const struct sockaddr *address=NULL)
Definition: socket.cpp:1936
AI_CANONNAME
#define AI_CANONNAME
Definition: socket.cpp:101
ost::info
__EXPORT AppLog & info(AppLog &sl)
Definition: applog.h:576
ucommon::Socket::pending
unsigned pending(void) const
Definition: socket.h:973
DEFAULT_FAMILY
#define DEFAULT_FAMILY
Definition: socket.h:81
ucommon::query_family
static int query_family
Definition: socket.cpp:111
inetmulticast_t
struct multicast_internet inetmulticast_t
ucommon::Socket::printf
size_t printf(const char *format,...) __PRINTF(2
Definition: socket.cpp:3382
ucommon::max
T &() max(T &o1, T &o2)
Definition: generics.h:445
ucommon::cidr::is_member
bool is_member(const struct sockaddr *address) const
Definition: socket.cpp:655
ucommon::ListenSocket::accept
socket_t accept(struct sockaddr_storage *address=NULL) const
Definition: socket.cpp:2809
ucommon::String::size
size_t size(void) const
Definition: string.cpp:137
ucommon::linked_sockaddr_operations::_getaddrsock
socket_t _getaddrsock(const struct addrinfo *addrinfo) const
Definition: socket.cpp:3528
NI_DGRAM
#define NI_DGRAM
Definition: socket.cpp:98
ucommon::Socket::listento
static int listento(socket_t socket, const struct sockaddr *address, int backlog=5)
Definition: socket.cpp:2988
ucommon::Socket::broadcast
int broadcast(bool enable)
Definition: socket.h:982
thread.h
ucommon::Socket::loopback
int loopback(bool enable)
Definition: socket.h:1018
addrinfo::ai_canonname
char * ai_canonname
Definition: socket.cpp:89
ucommon::String::data
int int size_t size_t char * data(void)
Definition: string.cpp:281
ucommon::Socket::create
static socket_t create(int family, int type, int protocol)
Definition: socket.cpp:1731
ucommon::Socket::address::setAny
void setAny(int family=AF_UNSPEC)
Definition: socket.cpp:1347
ucommon::Socket::ioerr
int ioerr
Definition: socket.h:331
ucommon::Socket::writeto
size_t writeto(const void *data, size_t number, const struct sockaddr *address=NULL)
Definition: socket.cpp:1918
sockaddr_internet
Definition: socket.h:121
ucommon::v6only
static int v6only
Definition: socket.cpp:112
ucommon::Socket::address::print
size_t print(char *dst, size_t dst_sz, bool port=false, bool force_brackets=false) const
Definition: socket.h:597
ucommon::Socket::address::isAny
bool isAny() const
Definition: socket.h:634
addrinfo::ai_addr
struct sockaddr * ai_addr
Definition: socket.cpp:90
ucommon::Socket::waitSending
bool waitSending(timeout_t timeout=0) const
Definition: socket.cpp:2725
ucommon::Socket::readfrom
size_t readfrom(void *data, size_t number, struct sockaddr_storage *address=NULL)
Definition: socket.cpp:1899
SOL_DCCP
#define SOL_DCCP
Definition: socket.h:81
ucommon::cidr::Network
struct hostaddr_internet Netmask Network
Definition: socket.h:171
ucommon::ListenSocket
Definition: socket.h:1820
addrinfo::ai_family
int ai_family
Definition: socket.cpp:85
ucommon::dup
T * dup(const T &object)
Definition: generics.h:324
ucommon::String::set
void set(const char *text)
Definition: string.cpp:802
cbuf
static uint8_t cbuf[48]
Definition: car.cpp:41
ucommon::Socket::is_null
static bool is_null(const char *string)
Definition: socket.cpp:3455
ucommon::addrinfo
struct addrinfo * addrinfo(Socket::address &address)
Definition: socket.h:2079
ucommon::linked_pointer
Definition: linked.h:991
addrinfo::ai_protocol
int ai_protocol
Definition: socket.cpp:87
ucommon::bitimask
static void bitimask(bit_t *bits, bit_t *mask, unsigned len)
Definition: socket.cpp:457
INVALID_SOCKET
#define INVALID_SOCKET
Definition: platform.h:416
NI_NOFQDN
#define NI_NOFQDN
Definition: socket.cpp:97
ucommon::Socket::writes
static ssize_t size_t writes(const char *string)
Definition: socket.cpp:1948
ucommon::Socket::address::clear
void clear(void)
Definition: socket.cpp:940
hostaddr_internet::ipv4
struct in_addr ipv4
Definition: socket.h:95
strfree
void strfree(char *str)
Definition: platform.h:563
ucommon::Socket::release
void release(void)
Definition: socket.cpp:1764
sockaddr_internet::ipv4
struct sockaddr_in ipv4
Definition: socket.h:124
ucommon::Socket::address::ipv4
static struct sockaddr_in * ipv4(struct sockaddr *address)
Definition: socket.cpp:1402
u_long
#define u_long
Definition: fsys.cpp:34
ucommon::Socket::address
friend class address
Definition: socket.h:850
ucommon::cidr::container
static const cidr * container(const policy *policy, const struct sockaddr *address)
Definition: socket.cpp:633
ucommon::cidr::cidr
cidr()
Definition: socket.cpp:549
ucommon::getaddrinfo
static int getaddrinfo(const char *hostname, const char *servname, const struct addrinfo *hintsp, struct addrinfo **res)
Definition: socket.cpp:215
addrinfo::ai_next
struct addrinfo * ai_next
Definition: socket.cpp:91
fsys.h
ucommon::Socket::address::add
void add(const char *hostname, const char *service=NULL, int type=SOCK_STREAM)
Definition: socket.cpp:1455
ucommon::LinkedObject
Definition: linked.h:55
ucommon::str
String str(Socket &so, size_t size)
Definition: socket.cpp:3507
ucommon::Socket::address::~address
~address()
Definition: socket.cpp:935
ucommon::Socket::init
static void init(void)
Definition: socket.cpp:531
ucommon::Socket::hinting
static struct addrinfo * hinting(socket_t socket, struct addrinfo *hint)
Definition: socket.cpp:2827
ucommon::linked_sockaddr_operations::_nextaddrinfo
const struct addrinfo * _nextaddrinfo(const struct addrinfo *addrinfo) const
Definition: socket.cpp:3520
ucommon::cidr::mask
unsigned mask(void) const
Definition: socket.cpp:597
ucommon::linked_pointer::next
void next(void)
Definition: linked.h:1106
ucommon::Socket::address::address
address()
Definition: socket.cpp:907
buffer
static uint8_t buffer[65536]
Definition: zerofill.cpp:27
ucommon::typeref
Definition: typeref.h:326
ucommon::Socket::connected
bool connected(void) const
Definition: socket.cpp:2607
ucommon::String::add
void add(const char *text)
Definition: string.cpp:992
ucommon::Socket::cancel
void cancel(void)
Definition: socket.cpp:1742
AF_UNSPEC
#define AF_UNSPEC
Definition: socket.cpp:418
ucommon::Socket::is_pending
bool is_pending(unsigned value)
Definition: socket.cpp:2623
ucommon::Socket::copy
static unsigned copy(struct sockaddr *target, const struct sockaddr *origin)
Definition: socket.cpp:3296
ucommon::stringref::create
static value * create(size_t size)
Definition: typeref.h:673
socksize_t
size_t socksize_t
Definition: platform.h:296
MSG_DONTWAIT
#define MSG_DONTWAIT
Definition: socket.cpp:58
ucommon::Socket::family
static int family(socket_t socket)
Definition: socket.cpp:3428
multicast_internet::ipv4
struct ip_mreq ipv4
Definition: socket.cpp:74
ucommon::Socket::address::dup
static struct sockaddr * dup(struct sockaddr *address)
Definition: socket.cpp:1420
ucommon::Socket::drop
int drop(const struct addrinfo *list, const int ifindex=0)
Definition: socket.cpp:2284
ucommon::Socket::address
Definition: socket.h:364
ucommon::Socket::nodelay
int nodelay(void) const
Definition: socket.h:948
NI_NUMERICSERV
#define NI_NUMERICSERV
Definition: socket.cpp:95
ucommon::servmutex
static mutex servmutex
Definition: socket.cpp:127
ucommon::ListenSocket::create
static socket_t create(const char *address, const char *service, unsigned backlog=5, int family=AF_UNSPEC, int type=0, int protocol=0)
Definition: socket.cpp:2792
ucommon::bitmask
static void bitmask(bit_t *bits, bit_t *mask, unsigned len)
Definition: socket.cpp:448
ucommon::ListenSocket::ListenSocket
ListenSocket(const char *address, const char *service, unsigned backlog=5, int family=AF_UNSPEC, int type=0, int protocol=0)
Definition: socket.cpp:2779
timeout
static shell::numericopt timeout('t', "--timeout", _TEXT("optional keyboard input timeout"), "seconds", 0)
ucommon::bitset
static void bitset(bit_t *bits, unsigned blen)
Definition: socket.cpp:466
ucommon::socket_mapping
static void socket_mapping(int family, socket_t so)
Definition: socket.cpp:114
addrinfo::ai_socktype
int ai_socktype
Definition: socket.cpp:86
ucommon::Socket::priority
int priority(int scheduling)
Definition: socket.h:1133
string.h
ucommon::cidr::find
static const cidr * find(const policy *policy, const struct sockaddr *address)
Definition: socket.cpp:612
ucommon::Socket::recvsize
int recvsize(unsigned size)
Definition: socket.h:1062
ucommon::Socket::address::withPort
address withPort(in_port_t port) const
Definition: socket.cpp:1163
ucommon::cidr::Name
char Name[16]
Definition: socket.h:172
ucommon::Socket::equal
static bool equal(const struct sockaddr *address1, const struct sockaddr *address2)
Definition: socket.cpp:3340
addrinfo::ai_flags
int ai_flags
Definition: socket.cpp:84
ucommon::Socket::eq_host
static bool eq_host(const struct sockaddr *address1, const struct sockaddr *address2)
Definition: socket.cpp:3309
ucommon::Socket::len
static socklen_t len(const struct sockaddr *address)
Definition: socket.cpp:3410
ucommon::cidr::set
void set(const char *string)
Definition: socket.cpp:779
ucommon::Socket::address::family
int family(void) const
Definition: socket.cpp:1136
ucommon::Timer::inf
static const timeout_t inf
Definition: timers.h:80
ucommon::Socket::wait
bool wait(timeout_t timeout=0) const
Definition: socket.cpp:2665
socket.h
ucommon::Socket::peek
size_t peek(void *data, size_t number) const
Definition: socket.cpp:1876
ucommon::Socket::shutdown
void shutdown(void)
Definition: socket.h:1140
NI_NAMEREQD
#define NI_NAMEREQD
Definition: socket.cpp:96
ucommon::Socket::address::insert
unsigned insert(const struct addrinfo *address)
Definition: socket.cpp:1233
ucommon::Socket::multicast
int multicast(unsigned ttl=1)
Definition: socket.h:1009
ucommon::Socket::address::setLoopback
void setLoopback(int family=AF_UNSPEC)
Definition: socket.cpp:1356
ucommon::Socket::hostname
static char * hostname(const struct sockaddr *address, char *buffer, size_t size)
Definition: socket.cpp:2911
ucommon::cidr::Family
int Family
Definition: socket.h:170
ucommon::Socket::via
static int via(struct sockaddr *address, const struct sockaddr *target, socklen_t size=0)
Definition: socket.cpp:3189
ucommon::cidr::policy
LinkedObject policy
Definition: socket.h:184
ucommon::Socket::address::remove
unsigned remove(const struct addrinfo *address)
Definition: socket.cpp:1244
ucommon::Socket::address::get
const struct sockaddr * get(void) const
Definition: socket.cpp:1128
ucommon::Socket::query
static struct addrinfo * query(const char *host, const char *service, int type=SOCK_STREAM, int protocol=0)
Definition: socket.cpp:956
ucommon::Socket::address::modify
struct sockaddr * modify(void)
Definition: socket.cpp:1120
ucommon::addr
const struct sockaddr * addr(Socket::address &address)
Definition: socket.h:2089
addrinfo
Definition: socket.cpp:83
ucommon::Socket::address::operator==
bool operator==(const address &other) const
Definition: socket.cpp:1030
ucommon::TCPServer::TCPServer
TCPServer(const char *address, const char *service, unsigned backlog=5)
Definition: socket.cpp:2818
ucommon::Socket::readline
size_t readline(char *data, size_t size)
Definition: socket.cpp:1959
ucommon::Socket::port
static in_port_t port(const struct sockaddr *address)
Definition: socket.cpp:3117
typeref.h
ucommon::Socket::acceptfrom
static socket_t acceptfrom(socket_t socket, struct sockaddr_storage *address=NULL)
Definition: socket.cpp:2656
hostaddr_internet
Definition: socket.h:91
ucommon::Socket::address::isLoopback
bool isLoopback() const
Definition: socket.h:655
ucommon::Socket::address::copy
void copy(const struct addrinfo *address)
Definition: socket.cpp:1286
ucommon::Socket::is_numeric
static bool is_numeric(const char *string)
Definition: socket.cpp:3472