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) 1999-2005 Open Source Telecom Corporation.
2 // Copyright (C) 2006-2013 David Sugar, Tycho Softworks.
3 // Copyright (C) 2014 David Sugar, Tycho Softworks, Savoir-Faire Linux Inc.
4 // Copyright (C) 2015 Cherokees of Idaho, Savoir-Faire Linux Inc.
5 //
6 // This program is free software; you can redistribute it and/or modify
7 // it under the terms of the GNU General Public License as published by
8 // the Free Software Foundation; either version 2 of the License, or
9 // (at your option) any later version.
10 //
11 // This program 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 General Public License for more details.
15 //
16 // You should have received a copy of the GNU General Public License
17 // along with this program; if not, write to the Free Software
18 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
19 //
20 // As a special exception, you may use this file as part of a free software
21 // library without restriction. Specifically, if other files instantiate
22 // templates or use macros or inline functions from this file, or you compile
23 // this file and link it with other files to produce an executable, this
24 // file does not by itself cause the resulting executable to be covered by
25 // the GNU General Public License. This exception does not however
26 // invalidate any other reasons why the executable file might be covered by
27 // the GNU General Public License.
28 //
29 // This exception applies only to the code released under the name GNU
30 // Common C++. If you copy code from other releases into a copy of GNU
31 // Common C++, as the General Public License permits, the exception does
32 // not apply to the code that you add in this way. To avoid misleading
33 // anyone as to the status of such modified files, you must delete
34 // this exception notice from them.
35 //
36 // If you write modifications of your own for GNU Common C++, it is your choice
37 // whether to permit this exception to apply to your modifications.
38 // If you do not wish that, delete this exception notice.
39 //
40 
41 #include <ucommon-config.h>
42 #include <commoncpp/config.h>
43 #include <commoncpp/export.h>
44 #include <commoncpp/address.h>
45 #include <commoncpp/socket.h>
46 
47 #include <fcntl.h>
48 
49 #ifdef _MSWINDOWS_
50 #include <io.h>
51 #define _IOLEN64 (unsigned)
52 #define _IORET64 (int)
53 typedef int socklen_t;
54 
55 #define socket_errno WSAGetLastError()
56 #else
57 #include <sys/ioctl.h>
58 #include <netinet/tcp.h>
59 #ifdef HAVE_NET_IP6_H
60 #include <netinet/ip6.h>
61 #endif
62 #define socket_errno errno
63 # ifndef O_NONBLOCK
64 # define O_NONBLOCK O_NDELAY
65 # endif
66 # ifdef IPPROTO_IP
67 # ifndef SOL_IP
68 # define SOL_IP IPPROTO_IP
69 # endif // !SOL_IP
70 # endif // IPPROTO_IP
71 #endif // !WIN32
72 
73 #ifndef INADDR_LOOPBACK
74 #define INADDR_LOOPBACK (in_addr_t)0x7f000001
75 #endif
76 
77 #ifdef HAVE_NETINET_IN_H
78 #include <netinet/in.h>
79 #endif
80 
81 #if defined(__hpux)
82 #define _XOPEN_SOURCE_EXTENDED
83 #endif
84 
85 #ifdef HAVE_NET_IF_H
86 #include <net/if.h>
87 #endif
88 
89 #ifndef _IOLEN64
90 #define _IOLEN64
91 #endif
92 
93 #ifndef _IORET64
94 #define _IORET64
95 #endif
96 
97 namespace ost {
98 
99 #if defined(_MSWINDOWS_) && !defined(__MINGW32__)
101 {
102  if (state == Socket::STREAM)
103  return dup((int)so);
104 
105  HANDLE pidHandle = GetCurrentProcess();
106  HANDLE dupHandle;
107  if(DuplicateHandle(pidHandle, reinterpret_cast<HANDLE>(so), pidHandle, &dupHandle, 0, FALSE, DUPLICATE_SAME_ACCESS))
108  return reinterpret_cast<socket_t>(dupHandle);
109  return (socket_t)(-1);
110 }
111 # define DUP_SOCK(s,state) dupSocket(s,state)
112 #else
114 {
115  return dup(so);
116 }
117 #endif
118 
120 {
121  flags.thrown = false;
122  flags.broadcast = false;
123  flags.route = true;
124  flags.keepalive = false;
125  flags.loopback = true;
126  flags.multicast = false;
127  flags.linger = false;
128  flags.ttl = 1;
129  errid = errSuccess;
130  errstr = NULL;
131  syserr = 0;
132  state = INITIAL;
133  so = INVALID_SOCKET;
134 }
135 
137 {
138  if(Socket::state == STREAM) {
139  state = INITIAL;
140  if(so != INVALID_SOCKET) {
141  SOCKET sosave = so;
142  so = INVALID_SOCKET;
143  release(sosave);
144  }
145  return;
146  }
147 
148  state = INITIAL;
149  if(so == INVALID_SOCKET)
150  return;
151 
152 #ifdef SO_LINGER
153  struct linger linger;
154 
155  if(flags.linger) {
156  linger.l_onoff = 1;
157  linger.l_linger = 60;
158  }
159  else
160  linger.l_onoff = linger.l_linger = 0;
161  setsockopt(so, SOL_SOCKET, SO_LINGER, (char *)&linger,
162  (socklen_t)sizeof(linger));
163 #endif
164 // shutdown(so, 2);
166 }
167 
169 {
170  setSocket();
171 }
172 
173 Socket::Socket(int domain, int type, int protocol) : ucommon::Socket()
174 {
175  setSocket();
176  so = socket(domain, type, protocol);
177  if(so == INVALID_SOCKET) {
178  error(errCreateFailed,(char *)"Could not create socket",socket_errno);
179  return;
180  }
181 #ifdef SO_NOSIGPIPE
182  int opt = 1;
183  setsockopt(so, SOL_SOCKET, SO_NOSIGPIPE, (char *)&opt, sizeof(opt));
184 #endif
185  state = AVAILABLE;
186 }
187 
189 {
190  setSocket();
191  if (fd == INVALID_SOCKET) {
192  error(errCreateFailed,(char *)"Invalid socket handle passed",0);
193  return;
194  }
195  so = fd;
196  state = AVAILABLE;
197 }
198 
200 {
201  setSocket();
202  so = dupSocket(orig.so,orig.state);
203  if(so == INVALID_SOCKET)
204  error(errCopyFailed,(char *)"Could not duplicate socket handle",socket_errno);
205  state = orig.state;
206 }
207 
209 {
210  endSocket();
211 }
212 
213 Socket::Error Socket::error(Error err, const char *errs, long systemError) const
214 {
215  errid = err;
216  errstr = errs;
217  syserr = systemError;
218  if(!err)
219  return err;
220 
221  if(flags.thrown)
222  return err;
223 
224  // prevents recursive throws
225 
226  flags.thrown = true;
227 #ifdef CCXX_EXCEPTIONS
228  switch(Thread::getException()) {
229  case Thread::throwObject:
230  THROW((Socket *)this);
232  if(!errs)
233  errs = (char *)"";
234  THROW(SockException(String(errs), err, systemError));
236  break;
237  }
238 #endif
239  return err;
240 }
241 
242 #ifdef _MSWINDOWS_
244 {
245  const char* str = "Could not connect to remote host";
246  switch(WSAGetLastError()) {
247  case WSAENETDOWN:
249  case WSAEINPROGRESS:
251  case WSAEADDRNOTAVAIL:
253  case WSAECONNREFUSED:
255  case WSAENETUNREACH:
257  default:
259  }
260 }
261 #else
263 {
264  char* str = (char *)"Could not connect to remote host";
265  switch(errno) {
266 #ifdef EHOSTUNREACH
267  case EHOSTUNREACH:
269 #endif
270 #ifdef ENETUNREACH
271  case ENETUNREACH:
273 #endif
274  case EINPROGRESS:
276 #ifdef EADDRNOTAVAIL
277  case EADDRNOTAVAIL:
279 #endif
280  case ECONNREFUSED:
282  case ETIMEDOUT:
284  default:
286  }
287 }
288 #endif
289 
291 {
292 #ifdef SO_SNDLOWAT
293  if(setsockopt(so, SOL_SOCKET, SO_SNDLOWAT, (char *)&limit, sizeof(limit)))
294  return errInvalidValue;
295 
296  return errSuccess;
297 
298 #else
299  return errServiceUnavailable;
300 #endif
301 }
302 
304 {
305 #ifdef SO_RCVLOWAT
306  if(setsockopt(so, SOL_SOCKET, SO_RCVLOWAT, (char *)&limit, sizeof(limit)))
307  return errInvalidValue;
308 
309  return errSuccess;
310 
311 #else
312  return errServiceUnavailable;
313 #endif
314 }
315 
317 {
318 #ifdef SO_SNDTIMEO
319  struct timeval tv;
320 
321  tv.tv_sec = to / 1000;
322  tv.tv_usec = (to % 1000) * 1000;
323 
324  if(setsockopt(so, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv)))
325  return errInvalidValue;
326 
327  return errSuccess;
328 
329 #else
330  return errServiceUnavailable;
331 #endif
332 }
333 
335 {
336 #ifdef SO_RCVTIMEO
337  struct timeval tv;
338 
339  tv.tv_sec = to / 1000;
340  tv.tv_usec = (to % 1000) * 1000;
341 
342  if(setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)))
343  return errInvalidValue;
344 
345  return errSuccess;
346 #else
347  return errServiceUnavailable;
348 #endif
349 }
350 
352 {
353 #ifdef SO_SNDBUF
354  if(setsockopt(so, SOL_SOCKET, SO_SNDBUF, (char *)&bufsize, sizeof(bufsize)))
355  return errInvalidValue;
356  return errSuccess;
357 #else
358  return errServiceUnavailable;
359 #endif
360 }
361 
363 {
364  Error err = receiveBuffer(bufsize);
365  if(err == errSuccess)
366  err = sendBuffer(bufsize);
367 
368  return err;
369 }
370 
372 {
373 #ifdef SO_RCVBUF
374  if(setsockopt(so, SOL_SOCKET, SO_RCVBUF, (char *)&bufsize, sizeof(bufsize)))
375  return errInvalidValue;
376  return errSuccess;
377 #else
378  return errServiceUnavailable;
379 #endif
380 }
381 
383 {
384  int opt = (enable ? 1 : 0);
385  if(setsockopt(so, SOL_SOCKET, SO_BROADCAST,
386  (char *)&opt, (socklen_t)sizeof(opt)))
387  return error(errBroadcastDenied,(char *)"Could not set socket broadcast option",socket_errno);
388  flags.broadcast = enable;
389  return errSuccess;
390 }
391 
393 {
394  socklen_t len;
395 
396  switch(family) {
397 #ifdef CCXX_IPV6
398  case IPV6:
399  struct sockaddr_in6 addr;
400  len = sizeof(addr);
401 
402  if(enable == flags.multicast)
403  return errSuccess;
404 
405  flags.multicast = enable;
406  if(enable)
407  getsockname(so, (struct sockaddr *)&addr, &len);
408  else
409  memset(&addr.sin6_addr, 0, sizeof(addr.sin6_addr));
410 
411  setsockopt(so, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *)&addr.sin6_addr, sizeof(addr.sin6_addr));
412  return errSuccess;
413 #endif
414  case IPV4:
415 #ifdef IP_MULTICAST_IF
416  struct sockaddr_in addr4;
417  len = sizeof(addr4);
418 
419  if(enable == flags.multicast)
420  return errSuccess;
421 
422  flags.multicast = enable;
423  if(enable)
424  getsockname(so, (struct sockaddr *)&addr4, &len);
425  else
426  memset(&addr4.sin_addr, 0, sizeof(addr4.sin_addr));
427 
428  setsockopt(so, IPPROTO_IP, IP_MULTICAST_IF, (char *)&addr4.sin_addr, sizeof(addr4.sin_addr));
429  return errSuccess;
430 #endif
431  default:
432  return error(errServiceUnavailable,(char *)"Multicast not supported");
433  }
434 }
435 
437 {
438  if(!flags.multicast)
439  return error(errMulticastDisabled,(char *)"Multicast not enabled on socket");
440 
441  switch(fam) {
442 #ifdef CCXX_IPV6
443  case IPV6:
444  flags.ttl = ttl;
445  setsockopt(so, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&ttl, sizeof(ttl));
446  return errSuccess;
447 #endif
448  case IPV4:
449 #ifdef IP_MULTICAST_TTL
450  flags.ttl = ttl;
451  setsockopt(so, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl));
452  return errSuccess;
453 #endif
454  default:
455  return error(errServiceUnavailable, (char *)"Multicast not supported");
456  }
457 }
458 
460 {
461  uint8_t loop;
462 
463  if(!flags.multicast)
464  return error(errMulticastDisabled,(char *)"Multicast not enabled on socket");
465 
466  if(enable)
467  loop = 1;
468  else
469  loop = 0;
470  flags.loopback = enable;
471 
472  switch(family) {
473 #ifdef CCXX_IPV6
474  case IPV6:
475  setsockopt(so, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *)&loop, sizeof(loop));
476  return errSuccess;
477 #endif
478  case IPV4:
479 #ifdef IP_MULTICAST_LOOP
480  setsockopt(so, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loop, sizeof(loop));
481  return errSuccess;
482 #endif
483  default:
484  return error(errServiceUnavailable,(char *)"Multicast not supported");
485  }
486 }
487 
489 {
490  switch(ucommon::Socket::join(ia, iface)) {
491  case 0:
492  return errSuccess;
493  case ENOSYS:
494  return error(errMulticastDisabled,(char *)"Multicast not enabled on socket");
495  case EIO:
496  return error(errServiceUnavailable,(char *)"Multicast not supported");
497  case EBADF:
498  default:
499  return error(errNotConnected,(char *)"Invalid socket operation");
500  }
501 }
502 
504 {
505  switch(ucommon::Socket::drop(ia, iface)) {
506  case 0:
507  return errSuccess;
508  case ENOSYS:
509  return error(errMulticastDisabled,(char *)"Multicast not enabled on socket");
510  case EIO:
511  return error(errServiceUnavailable,(char *)"Multicast not supported");
512  case EBADF:
513  default:
514  return error(errNotConnected,(char *)"Invalid socket operation");
515  }
516 }
517 
519 {
520  int opt = (enable ? 1 : 0);
521 
522 #ifdef SO_DONTROUTE
523  if(setsockopt(so, SOL_SOCKET, SO_DONTROUTE,
524  (char *)&opt, (socklen_t)sizeof(opt)))
525  return error(errRoutingDenied,(char *)"Could not set dont-route socket option",socket_errno);
526 #endif
527  flags.route = enable;
528  return errSuccess;
529 }
530 
532 {
533  int opt = (enable ? 1 : 0);
534 
535  if(setsockopt(so, IPPROTO_TCP, TCP_NODELAY,
536  (char *)&opt, (socklen_t)sizeof(opt)))
537  return error(errNoDelay,(char *)"Could not set tcp-nodelay socket option",socket_errno);
538 
539 
540  return errSuccess;
541 }
542 
543 ssize_t Socket::readLine(char *str, size_t request, timeout_t timeout)
544 {
545  bool crlf = false;
546  bool nl = false;
547  size_t nleft = request - 1; // leave also space for terminator
548  int nstat,c;
549 
550  if(request < 1)
551  return 0;
552 
553  str[0] = 0;
554 
555  while(nleft && !nl) {
556  if(timeout) {
558  error(errTimeout,(char *)"Read timeout", 0);
559  return -1;
560  }
561  }
562  nstat = ::recv(so, str, _IOLEN64 nleft, MSG_PEEK);
563  if(nstat <= 0) {
564  error(errInput,(char *)"Could not read from socket", socket_errno);
565  return -1;
566  }
567 
568  // FIXME: if unique char in buffer is '\r' return "\r"
569  // if buffer end in \r try to read another char?
570  // and if timeout ??
571  // remember last \r
572 
573  for(c=0; c < nstat; ++c) {
574  if(str[c] == '\n') {
575  if (c > 0 && str[c-1] == '\r')
576  crlf = true;
577  ++c;
578  nl = true;
579  break;
580  }
581  }
582  nstat = ::recv(so, str, _IOLEN64 c, 0);
583  // TODO: correct ???
584  if(nstat < 0)
585  break;
586 
587  // adjust ending \r\n in \n
588  if(crlf) {
589  --nstat;
590  str[nstat - 1] = '\n';
591  }
592 
593  str += nstat;
594  nleft -= nstat;
595  }
596  *str = 0;
597  return (ssize_t)(request - nleft - 1);
598 }
599 
600 ssize_t Socket::readData(void *Target, size_t Size, char Separator, timeout_t timeout)
601 {
602  if ((Separator == 0x0D) || (Separator == 0x0A))
603  return (readLine ((char *) Target, Size, timeout));
604 
605  if (Size < 1)
606  return (0);
607 
608  ssize_t nstat;
609 
610  if (Separator == 0) { // Flat-out read for a number of bytes.
611  if (timeout) {
612  if (!isPending (pendingInput, timeout)) {
613  error(errTimeout);
614  return (-1);
615  }
616  }
617  nstat =::recv (so, (char *)Target, _IOLEN64 Size, 0);
618 
619  if (nstat < 0) {
620  error (errInput);
621  return (-1);
622  }
623  return (nstat);
624  }
626  // Otherwise, we have a special char separator to use
628  bool found = false;
629  size_t nleft = Size;
630  int c;
631  char *str = (char *) Target;
632 
633  memset (str, 0, Size);
634 
635  while (nleft && !found) {
636  if (timeout) {
637  if (!isPending (pendingInput, timeout)) {
638  error(errTimeout);
639  return (-1);
640  }
641  }
642  nstat =::recv (so, str, _IOLEN64 nleft, MSG_PEEK);
643  if (nstat <= 0) {
644  error (errInput);
645  return (-1);
646  }
647 
648  for (c = 0; (c < nstat) && !found; ++c) {
649  if (str[c] == Separator)
650  found = true;
651  }
652 
653  memset (str, 0, nleft);
654  nstat =::recv (so, str, c, 0);
655  if (nstat < 0)
656  break;
657 
658  str += nstat;
659  nleft -= nstat;
660  }
661  return (ssize_t)(Size - (ssize_t) nleft);
662 }
663 
664 ssize_t Socket::writeData(const void *Source, size_t Size, timeout_t timeout)
665 {
666  if (Size < 1)
667  return (0);
668 
669  ssize_t nstat;
670  const char *Slide = (const char *) Source;
671 
672  while (true) {
673  if (timeout) {
674  if (!isPending (pendingOutput, timeout)) {
675  error(errOutput);
676  return (-1);
677  }
678  }
679  nstat =::send (so, Slide, _IOLEN64 Size, MSG_NOSIGNAL);
680 
681  if (nstat <= 0) {
682  error(errOutput);
683  return (-1);
684  }
685  Size -= nstat;
686  Slide += nstat;
687 
688 
689  if (Size <= 0)
690  break;
691  }
692  return (nstat);
693 }
694 
695 const char *Socket::getSystemErrorString(void) const
696 {
697 #ifdef CCXX_EXCEPTIONS
698  SockException e(errstr, errid, syserr);
699  return e.getSystemErrorString();
700 #else
701  return NULL;
702 #endif
703 }
704 
706 {
707  int status = 0;
708 #ifdef USE_POLL
709  struct pollfd pfd;
710 
711  pfd.fd = so;
712  pfd.revents = 0;
713 
714  if(so == INVALID_SOCKET)
715  return true;
716 
717  switch(pending) {
718  case pendingInput:
719  pfd.events = POLLIN;
720  break;
721  case pendingOutput:
722  pfd.events = POLLOUT;
723  break;
724  case pendingError:
725  pfd.events = POLLERR | POLLHUP;
726  break;
727  }
728 
729  status = 0;
730  while(status < 1) {
731 
732  if(timeout == TIMEOUT_INF)
733  status = poll(&pfd, 1, -1);
734  else
735  status = poll(&pfd, 1, timeout);
736 
737  if(status < 1) {
738  // don't stop polling because of a simple
739  // signal :)
740  if(status == -1 && errno == EINTR)
741  continue;
742 
743  return false;
744  }
745  }
746 
747  if(pfd.revents & pfd.events)
748  return true;
749  return false;
750 #else
751  struct timeval tv;
752  struct timeval *tvp = &tv;
753  fd_set grp;
754 
755  if(timeout == TIMEOUT_INF)
756  tvp = NULL;
757  else {
758  tv.tv_usec = (timeout % 1000) * 1000;
759  tv.tv_sec = timeout / 1000;
760  }
761 
762  FD_ZERO(&grp);
763  SOCKET sosave = so;
764  if(so == INVALID_SOCKET)
765  return true;
766  FD_SET(sosave, &grp);
767  switch(pending) {
768  case pendingInput:
769  status = ::select((int)so + 1, &grp, NULL, NULL, tvp);
770  break;
771  case pendingOutput:
772  status = ::select((int)so + 1, NULL, &grp, NULL, tvp);
773  break;
774  case pendingError:
775  status = ::select((int)so + 1, NULL, NULL, &grp, tvp);
776  break;
777  }
778  if(status < 1)
779  return false;
780  if(FD_ISSET(so, &grp))
781  return true;
782  return false;
783 #endif
784 }
785 
786 bool Socket::operator!() const
787 {
788  return (Socket::state == INITIAL) ? true : false;
789 }
790 
791 Socket::operator bool() const
792 {
793  return (Socket::state == INITIAL) ? false : true;
794 }
795 
797 {
798  if(so == from.so)
799  return *this;
800 
801  if(state != INITIAL)
802  endSocket();
803 
804  so = dupSocket(from.so,from.state);
805  if(so == INVALID_SOCKET) {
806  error(errCopyFailed,(char *)"Could not duplicate socket handle",socket_errno);
807  state = INITIAL;
808  }
809  else
810  state = from.state;
811 
812  return *this;
813 }
814 
816 {
818 
819  switch(fam) {
820  case IPV4:
821  so = socket(fam, SOCK_DGRAM, IPPROTO_UDP);
822  break;
823 #ifdef CCXX_IPV6
824  case IPV6:
825  so = socket(fam, SOCK_DGRAM, IPPROTO_UDP);
826  break;
827 #endif
828  default:
829  return false;
830  }
831 
832  if(so == INVALID_SOCKET)
833  return false;
834 
835  release(so);
836  return true;
837 }
838 
840 {
842  sockaddr_in6 from;
843  char buf;
844  socklen_t len = sizeof(from);
845  int rc = ::recvfrom(so, &buf, 1, MSG_PEEK, (sockaddr *)&from, &len);
846 
847 #ifdef _MSWINDOWS_
848  if(rc < 1 && WSAGetLastError() != WSAEMSGSIZE) {
849  error(errInput,(char *)"Could not read from socket",socket_errno);
850  return addr;
851  }
852 #else
853  if(rc < 0) {
854  error(errInput,(char *)"Could not read from socket",socket_errno);
855  return addr;
856  }
857 #endif
858  else {
859  if(rc < 1)
860  return addr;
861  }
862 
863  addr.insert((sockaddr *)&from);
864  return addr;
865 }
866 
868 {
870  sockaddr_in* from = addr;
871  struct in_addr any;
872  any.s_addr = INADDR_ANY;
873 
874  if (from == NULL) {
875  if (port)
876  *port = 0;
877  return IPV4Host(any);
878  }
879 
880  if (port)
881  *port = ntohs(from->sin_port);
882  return IPV4Host(from->sin_addr);
883 }
884 
885 #ifdef CCXX_IPV6
886 IPV6Host Socket::getIPV6Sender(in_port_t *port) const
887 {
889  sockaddr_in6* from = addr;
890  if (from == NULL) {
891  if (port)
892  *port = 0;
893  return IPV6Host(in6addr_any);
894  }
895 
896  if (port)
897  *port = ntohs(from->sin6_port);
898  return IPV6Host(from->sin6_addr);
899 }
900 #endif
901 
903 {
905  struct sockaddr_in6 addr;
906  socklen_t len = sizeof(addr);
907 
908  if(getsockname(so, (struct sockaddr *)&addr, &len)) {
909  error(errResourceFailure,(char *)"Could not get socket address",socket_errno);
910  return saddr;
911  }
912  saddr.insert((sockaddr *)&addr);
913  return saddr;
914 }
915 
917 {
918  const sockaddr_in* from = getLocal();
919  struct in_addr any;
920  any.s_addr = INADDR_ANY;
921 
922  if (from == NULL) {
923  if (port)
924  *port = 0;
925  return IPV4Host(any);
926  }
927 
928  if (port)
929  *port = ntohs(from->sin_port);
930  return IPV4Host(from->sin_addr);
931 }
932 
933 #ifdef CCXX_IPV6
934 IPV6Host Socket::getIPV6Local(in_port_t *port) const
935 {
936  const sockaddr_in6* from = getLocal();
937  if (from == NULL) {
938  if (port)
939  *port = 0;
940  return IPV6Host(in6addr_any);
941  }
942 
943  if (port)
944  *port = ntohs(from->sin6_port);
945  return IPV6Host(from->sin6_addr);
946 }
947 #endif
948 
949 
951 {
953  struct sockaddr_in6 addr;
954  socklen_t len = sizeof(addr);
955 
956  if(getpeername(so, (struct sockaddr *)&addr, &len)) {
957 #ifndef _MSWINDOWS_
958  if(errno == ENOTCONN)
959  error(errNotConnected,(char *)"Could not get peer address",socket_errno);
960  else
961 #endif
962  error(errResourceFailure,(char *)"Could not get peer address",socket_errno);
963  return saddr;
964  }
965  saddr.insert((sockaddr *)&addr);
966  return saddr;
967 }
968 
970 {
971  sockaddr_in* from = getPeer();
972  struct in_addr any;
973  any.s_addr = INADDR_ANY;
974 
975  if (from == NULL) {
976  if (port)
977  *port = 0;
978  return IPV4Host(any);
979  }
980 
981  if (port)
982  *port = ntohs(from->sin_port);
983  return IPV4Host(from->sin_addr);
984 }
985 
986 #ifdef CCXX_IPV6
987 IPV6Host Socket::getIPV6Peer(in_port_t *port) const
988 {
989  sockaddr_in6* from = getPeer();
990  if (from == NULL) {
991  if (port)
992  *port = 0;
993  return IPV6Host(in6addr_any);
994  }
995 
996  if (port)
997  *port = ntohs(from->sin6_port);
998  return IPV6Host(from->sin6_addr);
999 }
1000 #endif
1001 
1002 void Socket::setCompletion(bool immediate)
1003 {
1004  flags.completion = immediate;
1005 #ifdef _MSWINDOWS_
1006  unsigned long flag = 0;
1007  // note that this will not work on some versions of Windows for Workgroups. Tough. -- jfc
1008  switch( immediate ) {
1009  case false:
1010  // this will not work if you are using WSAAsyncSelect or WSAEventSelect.
1011  // -- perhaps I should throw an exception
1012  flag = 1;
1013 // ioctlsocket( so, FIONBIO, (unsigned long *) 1);
1014  break;
1015  case true:
1016  flag = 0;
1017 // ioctlsocket( so, FIONBIO, (unsigned long *) 0);
1018  break;
1019  }
1020  ioctlsocket(so, FIONBIO, &flag);
1021 #else
1022  int fflags = fcntl(so, F_GETFL);
1023 
1024  if(immediate) {
1025  fflags &=~ O_NONBLOCK;
1026  fcntl(so, F_SETFL, fflags);
1027  }
1028  else {
1029  fflags |= O_NONBLOCK;
1030  fcntl(so, F_SETFL, fflags);
1031  }
1032 #endif
1033 }
1034 
1036 {
1037  int opt = (enable ? ~0: 0);
1038 #if (defined(SO_KEEPALIVE) || defined(_MSWINDOWS_))
1039  if(setsockopt(so, SOL_SOCKET, SO_KEEPALIVE,
1040  (char *)&opt, (socklen_t)sizeof(opt)))
1041  return error(errKeepaliveDenied,(char *)"Could not set socket keep-alive option",socket_errno);
1042 #endif
1043  flags.keepalive = enable;
1044  return errSuccess;
1045 }
1046 
1048 {
1049 #ifdef SO_LINGER
1050  flags.linger = linger;
1051  return errSuccess;
1052 #else
1053  return error(errServiceUnavailable,(char *)"Socket lingering not supported");
1054 #endif
1055 }
1056 
1058 {
1059 #ifdef SOL_IP
1060  uint8_t tos;
1061  switch(service) {
1062 #ifdef IPTOS_LOWDELAY
1063  case tosLowDelay:
1064  tos = IPTOS_LOWDELAY;
1065  break;
1066 #endif
1067 #ifdef IPTOS_THROUGHPUT
1068  case tosThroughput:
1070  break;
1071 #endif
1072 #ifdef IPTOS_RELIABILITY
1073  case tosReliability:
1075  break;
1076 #endif
1077 #ifdef IPTOS_MINCOST
1078  case tosMinCost:
1079  tos = IPTOS_MINCOST;
1080  break;
1081 #endif
1082  default:
1083  return error(errServiceUnavailable,(char *)"Unknown type-of-service");
1084  }
1085  if(setsockopt(so, SOL_IP, IP_TOS,(char *)&tos, (socklen_t)sizeof(tos)))
1086  return error(errServiceDenied,(char *)"Could not set type-of-service",socket_errno);
1087  return errSuccess;
1088 #else
1089  return error(errServiceUnavailable,(char *)"Socket type-of-service not supported",socket_errno);
1090 #endif
1091 }
1092 
1093 bool Socket::isConnected(void) const
1094 {
1095  return (Socket::state == CONNECTED) ? true : false;
1096 }
1097 
1098 bool Socket::isActive(void) const
1099 {
1100  return (state != INITIAL) ? true : false;
1101 }
1102 
1103 } // namespace ost
ost::Socket::errCopyFailed
Definition: socket.h:117
ost::Socket::readLine
ssize_t readLine(char *buf, size_t len, timeout_t timeout=0)
Definition: socket.cpp:543
ost::Socket::State
State
Definition: socket.h:95
ost::Socket::getIPV4Peer
IPV4Host getIPV4Peer(in_port_t *port=NULL) const
Definition: socket.cpp:969
ost::Socket::linger
bool linger
Definition: socket.h:183
O_NONBLOCK
#define O_NONBLOCK
Definition: socket.cpp:64
ost::Socket::IPV4
Definition: socket.h:109
ucommon::Socket::type
int type(void) const
Definition: socket.h:1093
ost::SOCKET
socket_t SOCKET
Definition: socket.h:90
IPTOS_RELIABILITY
#define IPTOS_RELIABILITY
Definition: socket.h:74
ucommon::Socket::join
int join(const struct addrinfo *list, const int ifindex=0)
Definition: socket.cpp:2276
ost::Socket::dupSocket
static socket_t dupSocket(socket_t s, Socket::State state)
Definition: socket.cpp:113
ost::Thread::throwException
Definition: thread.h:415
ucommon::limit
T &() limit(T &value, T &low, T &high)
Definition: generics.h:468
ucommon::Socket::error
static int error(void)
Definition: socket.cpp:1849
ost::Socket::getLocal
ucommon::Socket::address getLocal() const
Definition: socket.cpp:902
ucommon::Socket::tos
int tos(int type)
Definition: socket.h:1123
ost::Socket::setMulticastByFamily
Error setMulticastByFamily(bool enable, Family family=IPV4)
Definition: socket.cpp:392
ost::Socket::CONNECTED
Definition: socket.h:99
ucommon::Socket::err
int err(void) const
Definition: socket.h:919
ucommon
Definition: access.cpp:23
export.h
ost::Socket::setNoDelay
Error setNoDelay(bool enable)
Definition: socket.cpp:531
ost::IPV4Host
Address of a specific Internet host machine.
Definition: address.h:578
ost::Socket::errConnectBusy
Definition: socket.h:129
ost::String
ucommon::String String
Definition: string.h:54
ost::Socket::errServiceDenied
Definition: socket.h:135
TIMEOUT_INF
#define TIMEOUT_INF
Definition: config.h:58
ost::Socket::errConnectNoRoute
Definition: socket.h:130
ost::Socket::errConnectTimeout
Definition: socket.h:126
ost::Socket::pendingError
Definition: socket.h:160
timeout_t
unsigned long timeout_t
Definition: platform.h:453
ost::Socket::errConnectFailed
Definition: socket.h:127
ost::Socket::Socket
Socket()
Definition: socket.cpp:168
ost::Socket::pendingOutput
Definition: socket.h:159
MSG_NOSIGNAL
#define MSG_NOSIGNAL
Definition: socket.cpp:62
ost::Socket::tosLowDelay
Definition: socket.h:149
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
ost::Socket::operator!
bool operator!() const
Definition: socket.cpp:786
ost::Socket::errResourceFailure
Definition: socket.h:120
ost::Socket::pendingInput
Definition: socket.h:158
ost::Socket::check
static bool check(Family fam)
Definition: socket.cpp:815
ost::Thread::throwNothing
Definition: thread.h:413
ost::Socket::errKeepaliveDenied
Definition: socket.h:134
socket_t
int socket_t
Definition: platform.h:414
ost::Socket::errInvalidValue
Definition: socket.h:143
ost::Socket::errMulticastDisabled
Definition: socket.h:137
ost::Socket::isPending
virtual bool isPending(Pending pend, timeout_t timeout=TIMEOUT_INF)
Definition: socket.cpp:705
ost::Socket::join
Error join(const ucommon::Socket::address &ia, int iface=0)
Definition: socket.cpp:488
ucommon::Socket::so
socket_t so
Definition: socket.h:330
ost::Socket::tosMinCost
Definition: socket.h:152
ost::Socket::errstr
const char * errstr
Definition: socket.h:167
socket_errno
#define socket_errno
Definition: socket.cpp:62
port
static shell::numericopt port('p', "--port", _TEXT("port to use"), "port", 0)
address.h
Network addresses and sockets related classes.
ucommon::Socket::pending
unsigned pending(void) const
Definition: socket.h:973
ost::Socket::errInput
Definition: socket.h:118
ost::Thread::getException
static Throw getException(void)
Definition: thread.cpp:287
ost::Socket::endSocket
void endSocket(void)
Definition: socket.cpp:136
ost::Socket::setLinger
Error setLinger(bool linger)
Definition: socket.cpp:1047
ost::Socket::receiveTimeout
Error receiveTimeout(timeout_t timer)
Definition: socket.cpp:334
ost::Socket::bufferSize
Error bufferSize(unsigned size)
Definition: socket.cpp:362
ost::Socket::state
State volatile state
Definition: socket.h:187
ost::Socket::setTimeToLiveByFamily
Error setTimeToLiveByFamily(uint8_t ttl, Family fam=IPV4)
Definition: socket.cpp:436
ost::Socket::sendLimit
Error sendLimit(int limit=2048)
Definition: socket.cpp:290
ost::Socket
Definition: socket.h:92
ost::Socket::STREAM
Definition: socket.h:101
ucommon::dup
T * dup(const T &object)
Definition: generics.h:324
ost::Socket::getPeer
ucommon::Socket::address getPeer() const
Definition: socket.cpp:950
ost::Socket::AVAILABLE
Definition: socket.h:97
ost::Socket::errSuccess
Definition: socket.h:115
ost::Socket::writeData
virtual ssize_t writeData(const void *buf, size_t len, timeout_t t=0)
Definition: socket.cpp:664
ost::Socket::INITIAL
Definition: socket.h:96
ost::Socket::setRouting
Error setRouting(bool enable)
Definition: socket.cpp:518
INVALID_SOCKET
#define INVALID_SOCKET
Definition: platform.h:416
ost::Socket::isConnected
bool isConnected(void) const
Definition: socket.cpp:1093
_IOLEN64
#define _IOLEN64
Definition: socket.cpp:90
ost::Socket::errConnectInvalid
Definition: socket.h:128
ost::Socket::connectError
Error connectError(void) const
Definition: socket.cpp:262
ucommon::Socket::release
void release(void)
Definition: socket.cpp:1764
ost::Socket::operator=
Socket & operator=(const Socket &from)
Definition: socket.cpp:796
ost::Socket::getIPV4Local
IPV4Host getIPV4Local(in_port_t *port=NULL) const
Definition: socket.cpp:916
ost::Socket::getSystemErrorString
const char * getSystemErrorString(void) const
Definition: socket.cpp:695
ost::Socket::errCreateFailed
Definition: socket.h:116
ost::Socket::drop
Error drop(const ucommon::Socket::address &ia, int iface=0)
Definition: socket.cpp:503
ost::Socket::receiveLimit
Error receiveLimit(int limit=1)
Definition: socket.cpp:303
ost::Socket::sendBuffer
Error sendBuffer(unsigned size)
Definition: socket.cpp:351
ucommon::str
String str(Socket &so, size_t size)
Definition: socket.cpp:3507
ost::Socket::Error
Error
Definition: socket.h:114
ost::Socket::setBroadcast
Error setBroadcast(bool enable)
Definition: socket.cpp:382
THROW
#define THROW(x)
Definition: generics.h:37
ost
Definition: address.cpp:63
ost::Socket::setCompletion
void setCompletion(bool immediate)
Definition: socket.cpp:1002
ost::Socket::syserr
long syserr
Definition: socket.h:168
socket.h
socket operations.
ost::Socket::Tos
Tos
Definition: socket.h:148
ost::Socket::setTypeOfService
Error setTypeOfService(Tos service)
Definition: socket.cpp:1057
ucommon::Socket::family
static int family(socket_t socket)
Definition: socket.cpp:3428
IPTOS_THROUGHPUT
#define IPTOS_THROUGHPUT
Definition: socket.h:73
ucommon::Socket::drop
int drop(const struct addrinfo *list, const int ifindex=0)
Definition: socket.cpp:2284
ucommon::Socket::address
Definition: socket.h:364
ost::Socket::errNotConnected
Definition: socket.h:123
timeout
static shell::numericopt timeout('t', "--timeout", _TEXT("optional keyboard input timeout"), "seconds", 0)
ost::Socket::Family
Family
Definition: socket.h:105
ost::Socket::errRoutingDenied
Definition: socket.h:133
ost::Socket::ttl
unsigned ttl
Definition: socket.h:184
ost::Socket::errNoDelay
Definition: socket.h:139
IPTOS_MINCOST
#define IPTOS_MINCOST
Definition: socket.h:75
ost::Socket::errServiceUnavailable
Definition: socket.h:136
ost::Socket::readData
virtual ssize_t readData(void *buf, size_t len, char separator=0, timeout_t t=0)
Definition: socket.cpp:600
config.h
ucommon::Socket::len
static socklen_t len(const struct sockaddr *address)
Definition: socket.cpp:3410
ost::Socket::errTimeout
Definition: socket.h:138
ost::Socket::isActive
bool isActive(void) const
Definition: socket.cpp:1098
ost::Socket::setSocket
void setSocket(void)
Definition: socket.cpp:119
ost::Socket::getIPV4Sender
virtual IPV4Host getIPV4Sender(in_port_t *port=NULL) const
Definition: socket.cpp:867
ost::Socket::receiveBuffer
Error receiveBuffer(unsigned size)
Definition: socket.cpp:371
ost::Socket::Pending
Pending
Definition: socket.h:157
ost::Socket::errid
Error errid
Definition: socket.h:166
ost::Socket::setLoopbackByFamily
Error setLoopbackByFamily(bool enable, Family family=IPV4)
Definition: socket.cpp:459
ucommon::Socket::address::insert
unsigned insert(const struct addrinfo *address)
Definition: socket.cpp:1233
ost::Socket::setKeepAlive
Error setKeepAlive(bool enable)
Definition: socket.cpp:1035
ost::Thread::throwObject
Definition: thread.h:414
ost::Socket::sendTimeout
Error sendTimeout(timeout_t timer)
Definition: socket.cpp:316
ost::Socket::errConnectRefused
Definition: socket.h:124
ost::Socket::flags
struct ost::Socket::@7 flags
ucommon::addr
const struct sockaddr * addr(Socket::address &address)
Definition: socket.h:2089
ost::Socket::~Socket
~Socket()
Definition: socket.cpp:208
ost::Socket::tosThroughput
Definition: socket.h:150
ost::Socket::errBroadcastDenied
Definition: socket.h:132
ucommon::Socket::port
static in_port_t port(const struct sockaddr *address)
Definition: socket.cpp:3117
ost::Socket::tosReliability
Definition: socket.h:151
IPTOS_LOWDELAY
#define IPTOS_LOWDELAY
Definition: socket.h:72
ost::Socket::errOutput
Definition: socket.h:121
ost::Socket::getSender
ucommon::Socket::address getSender() const
Definition: socket.cpp:839