CPPMyth
Library to interoperate with MythTV server
socket.cpp
1 /*
2  * Copyright (C) 2014-2019 Jean-Luc Barriere
3  *
4  * This library is free software; you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as published
6  * by the Free Software Foundation; either version 3, or (at your option)
7  * any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library; see the file COPYING. If not, write to
16  * the Free Software Foundation, 51 Franklin Street, Fifth Floor, Boston,
17  * MA 02110-1301 USA
18  * http://www.gnu.org/copyleft/gpl.html
19  *
20  */
21 
22 #include "socket.h"
23 #include "debug.h"
24 
25 #include <errno.h>
26 #include <cstdio>
27 #include <cstring>
28 
29 #ifdef __WINDOWS__
30 #include <WS2tcpip.h>
31 #define SHUT_RDWR SD_BOTH
32 #define SHUT_WR SD_SEND
33 #define LASTERROR WSAGetLastError()
34 #define ERRNO_INTR WSAEINTR
35 typedef int socklen_t;
36 typedef IN_ADDR in_addr_t;
37 
38 #else
39 #include <unistd.h>
40 #include <sys/types.h>
41 #include <sys/socket.h>
42 #include <sys/select.h>
43 #include <netinet/in.h>
44 #include <netdb.h>
45 #include <arpa/inet.h>
46 #define closesocket(a) close(a)
47 #define LASTERROR errno
48 #define ERRNO_INTR EINTR
49 #endif /* __WINDOWS__ */
50 
51 #include <signal.h>
52 
53 using namespace NSROOT;
54 
55 static int __addressFamily(SOCKET_AF_t saf)
56 {
57  switch(saf)
58  {
59  case SOCKET_AF_INET4:
60  return AF_INET;
61  case SOCKET_AF_INET6:
62  return AF_INET6;
63  default:
64  return AF_UNSPEC;
65  }
66 }
67 
68 namespace NSROOT
69 {
70 
72  {
73  sockaddr_storage data;
74  socklen_t sa_len;
75 
76  SocketAddress() { Clear(AF_UNSPEC); }
77  SocketAddress(int family) { Clear(family); }
78  inline sockaddr* sa() { return (sockaddr*)&data; }
79  inline int sa_family() { return data.ss_family; }
80  void Clear(int family)
81  {
82  memset(&data, 0, sizeof(data));
83  data.ss_family = family;
84  sa_len = (family == AF_INET ? sizeof(sockaddr_in) : sizeof(sockaddr_in6));
85  }
86  };
87 
88 }
89 
94 
95 static char my_hostname[SOCKET_HOSTNAME_MAXSIZE];
96 static volatile net_socket_t my_socket;
97 
98 static void __sigHandler(int sig)
99 {
100  closesocket(my_socket);
101  my_socket = INVALID_SOCKET_VALUE;
102  (void)sig;
103 }
104 
105 TcpSocket::TcpSocket()
106 : NetSocket()
107 , m_socket(INVALID_SOCKET_VALUE)
108 , m_rcvbuf(SOCKET_RCVBUF_MINSIZE)
109 , m_errno(0)
110 , m_attempt(SOCKET_READ_ATTEMPT)
111 , m_buffer(NULL)
112 , m_bufptr(NULL)
113 , m_buflen(SOCKET_BUFFER_SIZE)
114 , m_rcvlen(0)
115 {
116 }
117 
118 TcpSocket::~TcpSocket()
119 {
120  if (IsValid())
121  Disconnect();
122  if (m_buffer)
123  delete[] m_buffer;
124 }
125 
126 static int __connectAddr(struct addrinfo *addr, net_socket_t *s, int rcvbuf)
127 {
128 #ifndef __WINDOWS__
129  void (*old_sighandler)(int);
130  int old_alarm;
131 #endif
132  socklen_t size;
133  int err = 0, opt_rcvbuf;
134 
135  if ((my_hostname[0] == '\0') && (gethostname(my_hostname, sizeof (my_hostname)) < 0))
136  {
137  err = LASTERROR;
138  DBG(DBG_ERROR, "%s: gethostname failed (%d)\n", __FUNCTION__, err);
139  return err;
140  }
141 
142  *s = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
143  if (*s == INVALID_SOCKET_VALUE)
144  {
145  err = LASTERROR;
146  DBG(DBG_ERROR, "%s: invalid socket (%d)\n", __FUNCTION__, err);
147  return err;
148  }
149 
150  opt_rcvbuf = (rcvbuf < SOCKET_RCVBUF_MINSIZE ? SOCKET_RCVBUF_MINSIZE : rcvbuf);
151  size = sizeof (opt_rcvbuf);
152  if (setsockopt(*s, SOL_SOCKET, SO_RCVBUF, (char *)&opt_rcvbuf, size))
153  DBG(DBG_WARN, "%s: could not set rcvbuf from socket (%d)\n", __FUNCTION__, LASTERROR);
154  if (getsockopt(*s, SOL_SOCKET, SO_RCVBUF, (char *)&opt_rcvbuf, &size))
155  DBG(DBG_WARN, "%s: could not get rcvbuf from socket (%d)\n", __FUNCTION__, LASTERROR);
156 
157 #ifdef SO_NOSIGPIPE
158  int opt_set = 1;
159  if (setsockopt(*s, SOL_SOCKET, SO_NOSIGPIPE, (void *)&opt_set, sizeof(int)))
160  DBG(DBG_WARN, "%s: could not set nosigpipe from socket (%d)\n", __FUNCTION__, LASTERROR);
161 #endif
162 
163 #ifndef __WINDOWS__
164  old_sighandler = signal(SIGALRM, __sigHandler);
165  old_alarm = alarm(5);
166  my_socket = *s;
167 #endif
168  if (connect(*s, addr->ai_addr, addr->ai_addrlen) < 0)
169  {
170  err = LASTERROR;
171  DBG(DBG_ERROR, "%s: failed to connect (%d)\n", __FUNCTION__, err);
172  closesocket(*s);
173  *s = INVALID_SOCKET_VALUE;
174 #ifndef __WINDOWS__
175  signal(SIGALRM, old_sighandler);
176  alarm(old_alarm);
177 #endif
178  return err;
179  }
180 #ifndef __WINDOWS__
181  my_socket = INVALID_SOCKET_VALUE;
182  signal(SIGALRM, old_sighandler);
183  alarm(old_alarm);
184 #endif
185  DBG(DBG_PROTO, "%s: connected to socket(%p)\n", __FUNCTION__, s);
186  return err;
187 }
188 
189 bool TcpSocket::Connect(const char *server, unsigned port, int rcvbuf)
190 {
191  struct addrinfo hints;
192  struct addrinfo *result, *addr;
193  char service[33];
194  int err;
195 
196  if (IsValid())
197  Disconnect();
198 
199  if (rcvbuf > SOCKET_RCVBUF_MINSIZE)
200  m_rcvbuf = rcvbuf;
201 
202  memset(&hints, 0, sizeof (hints));
203  hints.ai_family = AF_UNSPEC;
204  hints.ai_socktype = SOCK_STREAM;
205  hints.ai_protocol = IPPROTO_TCP;
206  snprintf(service, sizeof(service), "%u", port);
207 
208  err = getaddrinfo(server, service, &hints, &result);
209  if (err)
210  {
211  switch (err)
212  {
213  case EAI_NONAME:
214  DBG(DBG_ERROR, "%s: the specified host is unknown\n", __FUNCTION__);
215  break;
216  case EAI_FAIL:
217  DBG(DBG_ERROR, "%s: a non-recoverable failure in name resolution occurred\n", __FUNCTION__);
218  break;
219  case EAI_MEMORY:
220  DBG(DBG_ERROR, "%s: a memory allocation failure occurred\n", __FUNCTION__);
221  break;
222  case EAI_AGAIN:
223  DBG(DBG_ERROR, "%s: a temporary error occurred on an authoritative name server\n", __FUNCTION__);
224  break;
225  default:
226  DBG(DBG_ERROR, "%s: unknown error %d\n", __FUNCTION__, err);
227  break;
228  }
229  m_errno = err;
230  return false;
231  }
232 
233  for (addr = result; addr; addr = addr->ai_next)
234  {
235  err = __connectAddr(addr, &m_socket, m_rcvbuf);
236  if (!err)
237  break;
238  }
239  freeaddrinfo(result);
240  m_errno = err;
241  return (err ? false : true);
242 }
243 
244 bool TcpSocket::SendData(const char *msg, size_t size)
245 {
246  if (IsValid())
247  {
248 
249 #if defined(__WINDOWS__) || defined(SO_NOSIGPIPE)
250  size_t s = send(m_socket, msg, size, 0);
251  if (s != size)
252  {
253  m_errno = LASTERROR;
254  return false;
255  }
256 #elif defined(MSG_NOSIGNAL)
257  size_t s = send(m_socket, msg, size, MSG_NOSIGNAL);
258  if (s != size)
259  {
260  m_errno = LASTERROR;
261  return false;
262  }
263 #else
264  sigset_t sig_block, sig_restore, sig_pending;
265  sigemptyset(&sig_block);
266  sigaddset(&sig_block, SIGPIPE);
267  /*
268  * Block SIGPIPE for this thread.
269  * This works since kernel sends SIGPIPE to the thread that called write(),
270  * not to the whole process.
271  */
272  if (pthread_sigmask(SIG_BLOCK, &sig_block, &sig_restore) != 0)
273  return false;
274  /*
275  * Check if SIGPIPE is already pending.
276  */
277  int sigpipe_pending = -1;
278  if (sigpending(&sig_pending) != -1)
279  sigpipe_pending = sigismember(&sig_pending, SIGPIPE);
280  if (sigpipe_pending == -1)
281  {
282  pthread_sigmask(SIG_SETMASK, &sig_restore, NULL);
283  return false;
284  }
285 
286  size_t s = send(m_socket, msg, size, 0);
287  if (s != size)
288  {
289  m_errno = LASTERROR;
290  /*
291  * Fetch generated SIGPIPE if write() failed with EPIPE.
292  * However, if SIGPIPE was already pending before calling write(), it was
293  * also generated and blocked by caller, and caller may expect that it can
294  * fetch it later. Since signals are not queued, we don't fetch it in this
295  * case.
296  */
297  if (m_errno == EPIPE && sigpipe_pending == 0)
298  {
299  struct timespec ts;
300  ts.tv_sec = 0;
301  ts.tv_nsec = 0;
302  int sig;
303  while ((sig = sigtimedwait(&sig_block, 0, &ts)) == -1 && LASTERROR == EINTR);
304  }
305  pthread_sigmask(SIG_SETMASK, &sig_restore, NULL);
306  return false;
307  }
308  pthread_sigmask(SIG_SETMASK, &sig_restore, NULL);
309 #endif
310 
311  m_errno = 0;
312  return true;
313  }
314  m_errno = ENOTCONN;
315  return false;
316 }
317 
318 size_t TcpSocket::ReceiveData(void *buf, size_t n)
319 {
320  if (IsValid())
321  {
322  m_errno = 0;
323  size_t rcvlen = 0;
324  char *p = (char*)buf;
325 
326  // Check for data remaining in buffer
327  if (m_buffer)
328  {
329  if (m_bufptr < m_buffer + m_rcvlen)
330  {
331  rcvlen = m_rcvlen - (m_bufptr - m_buffer);
332  if (rcvlen > n)
333  rcvlen = n;
334  memcpy(p, m_bufptr, rcvlen);
335  m_bufptr += rcvlen;
336  p += rcvlen;
337  n -= rcvlen;
338  if (n == 0)
339  return rcvlen;
340  }
341  }
342  else if ((m_buffer = new char[m_buflen]) == NULL)
343  {
344  m_errno = ENOMEM;
345  DBG(DBG_ERROR, "%s: cannot allocate %u bytes for buffer\n", __FUNCTION__, m_buflen);
346  return 0;
347  }
348  // Reset buffer
349  m_bufptr = m_buffer;
350  m_rcvlen = 0;
351 
352  struct timeval tv;
353  fd_set fds;
354  int r = 0, hangcount = 0;
355 
356  while (n > 0)
357  {
358  tv = m_timeout;
359  FD_ZERO(&fds);
360  FD_SET(m_socket, &fds);
361  r = select(m_socket + 1, &fds, NULL, NULL, &tv);
362  if (r > 0)
363  {
364  // Under threshold use buffering
365  if (n < m_buflen)
366  {
367  if ((r = recv(m_socket, m_buffer, m_buflen, 0)) > 0)
368  {
369  m_rcvlen = r;
370  size_t s = r;
371  if (s > n)
372  s = n;
373  memcpy(p, m_buffer, s);
374  m_bufptr = m_buffer + s;
375  p += s;
376  n -= s;
377  rcvlen += s;
378  }
379  }
380  // No buffering
381  else
382  {
383  if ((r = recv(m_socket, p, n, 0)) > 0)
384  {
385  p += r;
386  n -= r;
387  rcvlen += r;
388  }
389  }
390  }
391  if (r == 0)
392  {
393  DBG(DBG_WARN, "%s: socket(%p) timed out (%d)\n", __FUNCTION__, &m_socket, hangcount);
394  m_errno = ETIMEDOUT;
395  if (++hangcount >= m_attempt)
396  break;
397  }
398  if (r < 0)
399  {
400  m_errno = LASTERROR;
401  if (m_errno != ERRNO_INTR)
402  break;
403  }
404  }
405  return rcvlen;
406  }
407  m_errno = ENOTCONN;
408  return 0;
409 }
410 
412 {
413  if (IsValid())
414  {
415  char buf[256];
416  struct timeval tv;
417  fd_set fds;
418  int r = 0;
419 
420  shutdown(m_socket, SHUT_RDWR);
421 
422  tv.tv_sec = 5;
423  tv.tv_usec = 0;
424  do
425  {
426  FD_ZERO(&fds);
427  FD_SET(m_socket, &fds);
428  r = select(m_socket + 1, &fds, NULL, NULL, &tv);
429  if (r > 0)
430  r = recv(m_socket, buf, sizeof(buf), 0);
431  } while (r > 0);
432 
433  closesocket(m_socket);
434  m_socket = INVALID_SOCKET_VALUE;
435  m_rcvlen = 0;
436  }
437 }
438 
439 bool TcpSocket::IsValid() const
440 {
441  return (m_socket == INVALID_SOCKET_VALUE ? false : true);
442 }
443 
444 int TcpSocket::Listen(timeval *timeout)
445 {
446  if (IsValid())
447  {
448  fd_set fds;
449  int r;
450 
451  FD_ZERO(&fds);
452  FD_SET(m_socket, &fds);
453  r = select(m_socket + 1, &fds, NULL, NULL, timeout);
454  if (r < 0)
455  m_errno = LASTERROR;
456  return r;
457  }
458  m_errno = ENOTCONN;
459  return -1;
460 }
461 
463 {
464  char host[INET6_ADDRSTRLEN];
465  memset(host, 0, INET6_ADDRSTRLEN);
466 
467  if (!IsValid())
468  return host;
469 
470  char addr[sizeof(sockaddr_in6)];
471  socklen_t addr_len = sizeof(addr);
472 
473  if (getsockname(m_socket, (sockaddr*)&addr, &addr_len) == 0)
474  getnameinfo((sockaddr*)&addr, addr_len, host, sizeof(host), NULL, 0, NI_NUMERICHOST);
475  else
476  m_errno = LASTERROR;
477 
478  return host;
479 }
480 
482 {
483  return my_hostname;
484 }
485 
490 
491 TcpServerSocket::TcpServerSocket()
492 : m_socket(INVALID_SOCKET_VALUE)
493 , m_errno(0)
494 , m_requestQueueSize(0)
495 {
496  m_addr = new(SocketAddress);
497 }
498 
499 TcpServerSocket::~TcpServerSocket()
500 {
501  Close();
502  if (m_addr)
503  {
504  delete(m_addr);
505  m_addr = NULL;
506  }
507 }
508 
509 bool TcpServerSocket::Create(SOCKET_AF_t af)
510 {
511  if (IsValid())
512  return false;
513 
514  m_addr->Clear(__addressFamily(af));
515  m_socket = socket(m_addr->sa_family(), SOCK_STREAM, 0);
516  if (!IsValid())
517  {
518  m_errno = LASTERROR;
519  DBG(DBG_ERROR, "%s: invalid socket (%d)\n", __FUNCTION__, m_errno);
520  return false;
521  }
522 
523 #ifdef __WINDOWS__
524  // The bind will succeed even an other socket is currently listening on the
525  // same address. So enable the option SO_EXCLUSIVEADDRUSE will fix the issue.
526  int opt_exclusive = 1;
527  if (setsockopt(m_socket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*)&opt_exclusive, sizeof(opt_exclusive)))
528  {
529  m_errno = LASTERROR;
530  DBG(DBG_ERROR, "%s: could not set exclusiveaddruse from socket (%d)\n", __FUNCTION__, m_errno);
531  return false;
532  }
533 #else
534  // Reuse address. The bind will fail only if an other socket is currently
535  // listening on the same address.
536  int opt_reuseaddr = 1;
537  if (setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt_reuseaddr, sizeof(opt_reuseaddr)))
538  {
539  m_errno = LASTERROR;
540  DBG(DBG_ERROR, "%s: could not set reuseaddr from socket (%d)\n", __FUNCTION__, m_errno);
541  return false;
542  }
543 #endif
544 
545  return true;
546 }
547 
549 {
550  return (m_socket == INVALID_SOCKET_VALUE ? false : true);
551 }
552 
553 bool TcpServerSocket::Bind(unsigned port)
554 {
555  if (!IsValid())
556  return false;
557  int r = 0;
558 
559  m_addr->Clear(m_addr->sa_family());
560  switch (m_addr->sa_family())
561  {
562  case AF_INET:
563  {
564  sockaddr_in* sa = (sockaddr_in*)m_addr->sa();
565  sa->sin_addr.s_addr = htonl(INADDR_ANY);
566  sa->sin_port = htons(port);
567  r = bind(m_socket, m_addr->sa(), m_addr->sa_len);
568  break;
569  }
570  case AF_INET6:
571  {
572  sockaddr_in6* sa = (sockaddr_in6*)m_addr->sa();
573  sa->sin6_addr = in6addr_any;
574  sa->sin6_port = htons(port);
575  r = bind(m_socket, m_addr->sa(), m_addr->sa_len);
576  break;
577  }
578  }
579 
580  if (r)
581  {
582  m_errno = LASTERROR;
583  DBG(DBG_ERROR, "%s: could not bind to address (%d)\n", __FUNCTION__, m_errno);
584  return false;
585  }
586  return true;
587 }
588 
589 bool TcpServerSocket::ListenConnection(int queueSize /*= SOCKET_CONNECTION_REQUESTS*/)
590 {
591  if (!IsValid())
592  return false;
593 
594  if (listen(m_socket, queueSize))
595  {
596  m_errno = LASTERROR;
597  DBG(DBG_ERROR, "%s: listen failed (%d)\n", __FUNCTION__, m_errno);
598  return false;
599  }
600  m_requestQueueSize = queueSize;
601  return true;
602 }
603 
605 {
606  socket.m_socket = accept(m_socket, m_addr->sa(), &m_addr->sa_len);
607  if (!socket.IsValid())
608  {
609  m_errno = LASTERROR;
610  DBG(DBG_ERROR, "%s: accept failed (%d)\n", __FUNCTION__, m_errno);
611  return false;
612  }
613 
614 #ifdef SO_NOSIGPIPE
615  int opt_set = 1;
616  if (setsockopt(socket.m_socket, SOL_SOCKET, SO_NOSIGPIPE, (void *)&opt_set, sizeof(int)))
617  DBG(DBG_WARN, "%s: could not set nosigpipe from socket (%d)\n", __FUNCTION__, LASTERROR);
618 #endif
619 
620  socket.SetReadAttempt(0);
621  return true;
622 }
623 
625 {
626  if (IsValid())
627  {
628  closesocket(m_socket);
629  m_socket = INVALID_SOCKET_VALUE;
630  }
631 }
632 
637 
638 UdpSocket::UdpSocket()
639 : m_socket(INVALID_SOCKET_VALUE)
640 , m_errno(0)
641 , m_buffer(NULL)
642 , m_bufptr(NULL)
643 , m_buflen(SOCKET_BUFFER_SIZE)
644 , m_rcvlen(0)
645 {
646  m_addr = new SocketAddress;
647  m_from = new SocketAddress;
648 }
649 
650 UdpSocket::UdpSocket(size_t bufferSize)
651 : m_socket(INVALID_SOCKET_VALUE)
652 , m_errno(0)
653 , m_buffer(NULL)
654 , m_bufptr(NULL)
655 , m_buflen(bufferSize)
656 , m_rcvlen(0)
657 {
658  m_addr = new SocketAddress;
659  m_from = new SocketAddress;
660 }
661 
662 UdpSocket::~UdpSocket()
663 {
664  if (IsValid())
665  {
666  closesocket(m_socket);
667  m_socket = INVALID_SOCKET_VALUE;
668  }
669  if (m_addr)
670  {
671  delete m_addr;
672  m_addr = NULL;
673  }
674  if (m_from)
675  {
676  delete m_from;
677  m_from = NULL;
678  }
679  if (m_buffer)
680  {
681  delete[] m_buffer;
682  m_buffer = m_bufptr = NULL;
683  }
684 }
685 
686 bool UdpSocket::Open(SOCKET_AF_t af, const char* target, unsigned port)
687 {
688  return Open(af) && SetAddress(target, port);
689 }
690 
691 bool UdpSocket::Open(SOCKET_AF_t af, bool broadcast /*= false*/)
692 {
693  if (IsValid() && m_addr->sa_family() != __addressFamily(af))
694  {
695  closesocket(m_socket);
696  m_socket = INVALID_SOCKET_VALUE;
697  }
698  if (m_socket == INVALID_SOCKET_VALUE)
699  {
700  m_addr->Clear(__addressFamily(af));
701  m_from->Clear(AF_UNSPEC);
702  if ((m_socket = socket(m_addr->sa_family(), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET_VALUE)
703  {
704  m_errno = LASTERROR;
705  DBG(DBG_ERROR, "%s: create socket failed (%d)\n", __FUNCTION__, m_errno);
706  return false;
707  }
708  if (broadcast && af == SOCKET_AF_INET4)
709  {
710  // set broadcast permission
711  int _broadcast = 1;
712  if (setsockopt(m_socket, SOL_SOCKET, SO_BROADCAST, (char*)&_broadcast, sizeof(_broadcast)))
713  {
714  m_errno = LASTERROR;
715  DBG(DBG_ERROR, "%s: could not set SO_BROADCAST from socket (%d)\n", __FUNCTION__, m_errno);
716  return false;
717  }
718  }
719  }
720  m_errno = 0;
721  return true;
722 }
723 
724 bool UdpSocket::SetAddress(const char* target, unsigned port)
725 {
726  if (!IsValid())
727  {
728  DBG(DBG_ERROR, "%s: invalid socket\n", __FUNCTION__);
729  return false;
730  }
731 
732  unsigned char _addr[sizeof(struct in6_addr)];
733  if (inet_pton(m_addr->sa_family(), target, &_addr) == 0)
734  {
735  m_errno = LASTERROR;
736  DBG(DBG_ERROR, "%s: invalid address (%s)\n", __FUNCTION__, target);
737  return false;
738  }
739 
740  m_addr->Clear(m_addr->sa_family());
741  switch(m_addr->sa_family())
742  {
743  case AF_INET:
744  {
745  sockaddr_in* sa = (sockaddr_in*)m_addr->sa();
746  memcpy(&(sa->sin_addr.s_addr), _addr, sizeof(in_addr_t));
747  sa->sin_port = htons(port);
748  break;
749  }
750  case AF_INET6:
751  {
752  sockaddr_in6* sa = (sockaddr_in6*)m_addr->sa();
753  memcpy(&(sa->sin6_addr), _addr, sizeof(struct in6_addr));
754  sa->sin6_port = htons(port);
755  break;
756  }
757  default:
758  m_errno = EINVAL;
759  DBG(DBG_ERROR, "%s: address familly unknown (%d)\n", __FUNCTION__, m_addr->sa_family());
760  return false;
761  }
762  m_errno = 0;
763  return true;
764 }
765 
766 bool UdpSocket::SetMulticastTTL(int multicastTTL)
767 {
768  if (!IsValid())
769  return false;
770 
771  switch(m_addr->sa_family())
772  {
773  case AF_INET:
774  {
775  // The v4 multicast TTL socket option requires that the value be passed in an unsigned char
776  unsigned char _ttl = (unsigned char) multicastTTL;
777  if (setsockopt(m_socket, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&_ttl, sizeof(_ttl)))
778  {
779  m_errno = LASTERROR;
780  DBG(DBG_ERROR, "%s: could not set IP_MULTICAST_TTL from socket (%d)\n", __FUNCTION__, m_errno);
781  return false;
782  }
783  break;
784  }
785  case AF_INET6:
786  {
787  // The v6 multicast TTL socket option requires that the value be passed in as an integer
788  if (setsockopt(m_socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char*)&multicastTTL, sizeof(multicastTTL)))
789  {
790  m_errno = LASTERROR;
791  DBG(DBG_ERROR, "%s: could not set IPV6_MULTICAST_HOPS from socket (%d)\n", __FUNCTION__, m_errno);
792  return false;
793  }
794  break;
795  }
796  default:
797  m_errno = EINVAL;
798  DBG(DBG_ERROR, "%s: address familly unknown (%d)\n", __FUNCTION__, m_addr->sa_family());
799  return false;
800  }
801  m_errno = 0;
802  return true;
803 }
804 
805 bool UdpSocket::SendData(const char* buf, size_t size)
806 {
807  if (IsValid())
808  {
809  size_t s = sendto(m_socket, buf, size, 0, m_addr->sa(), m_addr->sa_len);
810  if (s != size)
811  {
812  m_errno = LASTERROR;
813  return false;
814  }
815  m_errno = 0;
816  return true;
817  }
818  m_errno = ENOTSOCK;
819  return false;
820 }
821 
822 size_t UdpSocket::ReceiveData(void* buf, size_t n)
823 {
824  if (IsValid())
825  {
826  m_errno = 0;
827  size_t len = 0;
828 
829  // fill rest of data from buffer
830  if (m_buffer)
831  {
832  if (m_bufptr < m_buffer + m_rcvlen)
833  {
834  len = m_rcvlen - (m_bufptr - m_buffer);
835  if (len > n)
836  len = n;
837  memcpy(buf, m_bufptr, len);
838  m_bufptr += len;
839  return len;
840  }
841  }
842  else if ((m_buffer = new char[m_buflen]) == NULL)
843  {
844  m_errno = ENOMEM;
845  DBG(DBG_ERROR, "%s: cannot allocate %u bytes for buffer\n", __FUNCTION__, m_buflen);
846  return 0;
847  }
848  // fill buffer with the next incoming datagram
849  m_bufptr = m_buffer;
850  m_rcvlen = 0;
851 
852  struct timeval tv;
853  fd_set fds;
854  int r = 0;
855 
856  tv = m_timeout;
857  FD_ZERO(&fds);
858  FD_SET(m_socket, &fds);
859  r = select(m_socket + 1, &fds, NULL, NULL, &tv);
860  if (r > 0)
861  {
862  if ((r = recvfrom(m_socket, m_buffer, m_buflen, 0, m_from->sa(), &m_from->sa_len)) > 0)
863  {
864  m_rcvlen = len = r;
865  if (m_rcvlen == m_buflen)
866  DBG(DBG_WARN, "%s: datagram have been truncated (%d)\n", __FUNCTION__, r);
867  if (len > n)
868  len = n;
869  memcpy(buf, m_buffer, len);
870  m_bufptr += len;
871  }
872  }
873  if (r == 0)
874  {
875  m_errno = ETIMEDOUT;
876  DBG(DBG_DEBUG, "%s: socket(%p) timed out\n", __FUNCTION__, &m_socket);
877  }
878  if (r < 0)
879  {
880  m_errno = LASTERROR;
881  DBG(DBG_ERROR, "%s: socket(%p) read error (%d)\n", __FUNCTION__, &m_socket, m_errno);
882  }
883  return len;
884  }
885  m_errno = ENOTSOCK;
886  return 0;
887 }
888 
889 bool UdpSocket::IsValid() const
890 {
891  return (m_socket == INVALID_SOCKET_VALUE ? false : true);
892 }
893 
894 std::string UdpSocket::GetRemoteAddrInfo() const
895 {
896  char host[INET6_ADDRSTRLEN];
897  memset(host, 0, INET6_ADDRSTRLEN);
898  getnameinfo(m_from->sa(), m_from->sa_len, host, sizeof(host), NULL, 0, NI_NUMERICHOST);
899  return host;
900 }
901 
906 
907 UdpServerSocket::UdpServerSocket()
908 : m_socket(INVALID_SOCKET_VALUE)
909 , m_errno(0)
910 , m_buffer(NULL)
911 , m_bufptr(NULL)
912 , m_buflen(SOCKET_BUFFER_SIZE)
913 , m_rcvlen(0)
914 {
915  m_addr = new SocketAddress;
916  m_from = new SocketAddress;
917  m_timeout.tv_sec = SOCKET_READ_TIMEOUT_SEC;
918  m_timeout.tv_usec = SOCKET_READ_TIMEOUT_USEC;
919 
920 }
921 
922 UdpServerSocket::UdpServerSocket(size_t bufferSize)
923 : m_socket(INVALID_SOCKET_VALUE)
924 , m_errno(0)
925 , m_buffer(NULL)
926 , m_bufptr(NULL)
927 , m_buflen(bufferSize)
928 , m_rcvlen(0)
929 {
930  m_addr = new SocketAddress;
931  m_from = new SocketAddress;
932  m_timeout.tv_sec = SOCKET_READ_TIMEOUT_SEC;
933  m_timeout.tv_usec = SOCKET_READ_TIMEOUT_USEC;
934 }
935 
936 UdpServerSocket::~UdpServerSocket()
937 {
938  if (IsValid())
939  {
940  closesocket(m_socket);
941  m_socket = INVALID_SOCKET_VALUE;
942  }
943  if (m_addr)
944  {
945  delete m_addr;
946  m_addr = NULL;
947  }
948  if (m_from)
949  {
950  delete m_from;
951  m_from = NULL;
952  }
953  if (m_buffer)
954  {
955  delete[] m_buffer;
956  m_buffer = m_bufptr = NULL;
957  }
958 }
959 
960 bool UdpServerSocket::Create(SOCKET_AF_t af)
961 {
962  if (IsValid())
963  return false;
964 
965  m_addr->Clear(__addressFamily(af));
966  m_socket = socket(m_addr->sa_family(), SOCK_DGRAM, 0);
967  if (!IsValid())
968  {
969  m_errno = LASTERROR;
970  DBG(DBG_ERROR, "%s: invalid socket (%d)\n", __FUNCTION__, m_errno);
971  return false;
972  }
973 
974  int opt_reuseaddr = 1;
975  if (setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt_reuseaddr, sizeof(opt_reuseaddr)))
976  {
977  m_errno = LASTERROR;
978  DBG(DBG_ERROR, "%s: could not set reuseaddr from socket (%d)\n", __FUNCTION__, m_errno);
979  return false;
980  }
981  return true;
982 }
983 
985 {
986  return (m_socket == INVALID_SOCKET_VALUE ? false : true);
987 }
988 
989 bool UdpServerSocket::Bind(unsigned port)
990 {
991  if (!IsValid())
992  return false;
993 
994  m_addr->Clear(m_addr->sa_family());
995  switch (m_addr->sa_family())
996  {
997  case AF_INET:
998  {
999  sockaddr_in* sa = (sockaddr_in*)m_addr->sa();
1000  sa->sin_addr.s_addr = htonl(INADDR_ANY);
1001  sa->sin_port = htons(port);
1002  break;
1003  }
1004  case AF_INET6:
1005  {
1006  sockaddr_in6* sa = (sockaddr_in6*)m_addr->sa();
1007  sa->sin6_addr = in6addr_any;
1008  sa->sin6_port = htons(port);
1009  break;
1010  }
1011  default:
1012  m_errno = EINVAL;
1013  DBG(DBG_ERROR, "%s: address familly unknown (%d)\n", __FUNCTION__, m_addr->sa_family());
1014  return false;
1015  }
1016 
1017  if (bind(m_socket, m_addr->sa(), m_addr->sa_len) != 0)
1018  {
1019  m_errno = LASTERROR;
1020  DBG(DBG_ERROR, "%s: could not bind to address (%d)\n", __FUNCTION__, m_errno);
1021  return false;
1022  }
1023  m_errno = 0;
1024  return true;
1025 }
1026 
1027 bool UdpServerSocket::SetMulticastTTL(int multicastTTL)
1028 {
1029  if (!IsValid())
1030  return false;
1031 
1032  switch(m_addr->sa_family())
1033  {
1034  case AF_INET:
1035  {
1036  // The v4 multicast TTL socket option requires that the value be passed in an unsigned char
1037  unsigned char _ttl = (unsigned char) multicastTTL;
1038  if (setsockopt(m_socket, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&_ttl, sizeof(_ttl)))
1039  {
1040  m_errno = LASTERROR;
1041  DBG(DBG_ERROR, "%s: could not set IP_MULTICAST_TTL from socket (%d)\n", __FUNCTION__, m_errno);
1042  return false;
1043  }
1044  break;
1045  }
1046  case AF_INET6:
1047  {
1048  // The v6 multicast TTL socket option requires that the value be passed in as an integer
1049  if (setsockopt(m_socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char*)&multicastTTL, sizeof(multicastTTL)))
1050  {
1051  m_errno = LASTERROR;
1052  DBG(DBG_ERROR, "%s: could not set IPV6_MULTICAST_HOPS from socket (%d)\n", __FUNCTION__, m_errno);
1053  return false;
1054  }
1055  break;
1056  }
1057  default:
1058  m_errno = EINVAL;
1059  DBG(DBG_ERROR, "%s: address familly unknown (%d)\n", __FUNCTION__, m_addr->sa_family());
1060  return false;
1061  }
1062  m_errno = 0;
1063  return true;
1064 }
1065 
1066 bool UdpServerSocket::SetMulticastMembership(const char* group, bool join)
1067 {
1068  if (!IsValid())
1069  return false;
1070 
1071  switch(m_addr->sa_family())
1072  {
1073  case AF_INET:
1074  {
1075  struct ip_mreq mreq;
1076  if (inet_pton(AF_INET, group, &mreq.imr_multiaddr) == 0)
1077  {
1078  m_errno = LASTERROR;
1079  DBG(DBG_ERROR, "%s: invalid address (%d)\n", __FUNCTION__, m_errno);
1080  return false;
1081  }
1082  mreq.imr_interface.s_addr = htonl(INADDR_ANY);
1083  if (setsockopt(m_socket, IPPROTO_IP, join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, reinterpret_cast<const char*>(&mreq), sizeof(mreq)))
1084  {
1085  m_errno = LASTERROR;
1086  DBG(DBG_ERROR, "%s: could not set multicast membership from socket (%d)\n", __FUNCTION__, m_errno);
1087  return false;
1088  }
1089  break;
1090  }
1091  case AF_INET6:
1092  {
1093  struct ipv6_mreq mreq;
1094  if (inet_pton(AF_INET6, group, &mreq.ipv6mr_multiaddr) == 0)
1095  {
1096  m_errno = LASTERROR;
1097  DBG(DBG_ERROR, "%s: invalid address (%d)\n", __FUNCTION__, m_errno);
1098  return false;
1099  }
1100  mreq.ipv6mr_interface = 0;
1101  if (setsockopt(m_socket, IPPROTO_IPV6, join ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP, reinterpret_cast<const char*>(&mreq), sizeof(mreq)))
1102  {
1103  m_errno = LASTERROR;
1104  DBG(DBG_ERROR, "%s: could not set multicast membership from socket (%d)\n", __FUNCTION__, m_errno);
1105  return false;
1106  }
1107  break;
1108  }
1109  default:
1110  m_errno = EINVAL;
1111  DBG(DBG_ERROR, "%s: address familly unknown (%d)\n", __FUNCTION__, m_addr->sa_family());
1112  return false;
1113  }
1114  m_errno = 0;
1115  return true;
1116 }
1117 
1118 size_t UdpServerSocket::AwaitIncoming(timeval timeout)
1119 {
1120  if (IsValid())
1121  {
1122  m_errno = 0;
1123 
1124  if (!m_buffer && (m_buffer = new char[m_buflen]) == NULL)
1125  {
1126  m_errno = ENOMEM;
1127  DBG(DBG_ERROR, "%s: cannot allocate %u bytes for buffer\n", __FUNCTION__, m_buflen);
1128  return 0;
1129  }
1130  // reset buffer
1131  m_bufptr = m_buffer;
1132  m_rcvlen = 0;
1133 
1134  struct timeval tv = timeout;
1135  fd_set fds;
1136  int r = 0;
1137 
1138  FD_ZERO(&fds);
1139  FD_SET(m_socket, &fds);
1140  r = select(m_socket + 1, &fds, NULL, NULL, &tv);
1141  if (r > 0)
1142  {
1143  if ((r = recvfrom(m_socket, m_buffer, m_buflen, 0, m_from->sa(), &m_from->sa_len)) > 0)
1144  {
1145  m_rcvlen = r;
1146  if (m_rcvlen == m_buflen)
1147  DBG(DBG_WARN, "%s: datagram have been truncated (%d)\n", __FUNCTION__, r);
1148  }
1149  }
1150  if (r == 0)
1151  {
1152  m_errno = ETIMEDOUT;
1153  DBG(DBG_DEBUG, "%s: socket(%p) timed out\n", __FUNCTION__, &m_socket);
1154  }
1155  if (r < 0)
1156  {
1157  m_errno = LASTERROR;
1158  DBG(DBG_ERROR, "%s: socket(%p) read error (%d)\n", __FUNCTION__, &m_socket, m_errno);
1159  }
1160  return m_rcvlen;
1161  }
1162  m_errno = ENOTSOCK;
1163  return 0;
1164 }
1165 
1166 size_t UdpServerSocket::AwaitIncoming()
1167 {
1168  return AwaitIncoming(m_timeout);
1169 }
1170 
1172 {
1173  char host[INET6_ADDRSTRLEN];
1174  memset(host, 0, INET6_ADDRSTRLEN);
1175  getnameinfo(m_from->sa(), m_from->sa_len, host, sizeof(host), NULL, 0, NI_NUMERICHOST);
1176  return host;
1177 }
1178 
1179 size_t UdpServerSocket::ReadData(void* buf, size_t n)
1180 {
1181  if (IsValid())
1182  {
1183  m_errno = 0;
1184  size_t len = 0;
1185 
1186  if (m_buffer && m_bufptr < m_buffer + m_rcvlen)
1187  {
1188  len = m_rcvlen - (m_bufptr - m_buffer);
1189  if (len > n)
1190  len = n;
1191  memcpy(buf, m_bufptr, len);
1192  m_bufptr += len;
1193  }
1194  return len;
1195  }
1196  m_errno = ENOTSOCK;
1197  return 0;
1198 }
size_t ReadData(void *buf, size_t n)
Definition: socket.cpp:1179
bool SetAddress(const char *target, unsigned port)
Definition: socket.cpp:724
int Listen(timeval *timeout)
Definition: socket.cpp:444
virtual void Disconnect()
Definition: socket.cpp:411
bool SetMulticastTTL(int multicastTTL)
Definition: socket.cpp:766
bool Create(SOCKET_AF_t af)
Definition: socket.cpp:509
bool IsValid() const
Definition: socket.cpp:889
bool SetMulticastMembership(const char *group, bool join)
Definition: socket.cpp:1066
virtual bool SendData(const char *buf, size_t size)
Definition: socket.cpp:244
void SetReadAttempt(int n)
Definition: socket.h:83
bool Bind(unsigned port)
Definition: socket.cpp:553
std::string GetRemoteAddrInfo() const
Definition: socket.cpp:1171
static const char * GetMyHostName()
Definition: socket.cpp:481
bool Bind(unsigned port)
Definition: socket.cpp:989
bool SetMulticastTTL(int multicastTTL)
Definition: socket.cpp:1027
bool AcceptConnection(TcpSocket &socket)
Definition: socket.cpp:604
bool SendData(const char *buf, size_t size)
Definition: socket.cpp:805
virtual bool Connect(const char *server, unsigned port, int rcvbuf)
Definition: socket.cpp:189
virtual size_t ReceiveData(void *buf, size_t n)
Definition: socket.cpp:318
bool ListenConnection(int queueSize=SOCKET_CONNECTION_REQUESTS)
Definition: socket.cpp:589
std::string GetRemoteAddrInfo() const
Definition: socket.cpp:894
bool IsValid() const
Definition: socket.cpp:548
std::string GetHostAddrInfo()
Definition: socket.cpp:462
bool Create(SOCKET_AF_t af)
Definition: socket.cpp:960
virtual bool IsValid() const
Definition: socket.cpp:439
bool IsValid() const
Definition: socket.cpp:984
size_t ReceiveData(void *buf, size_t n)
Definition: socket.cpp:822
bool Open(SOCKET_AF_t af, const char *target, unsigned port)
Definition: socket.cpp:686