CPPMyth
Library to interoperate with MythTV server
Loading...
Searching...
No Matches
socket.cpp
1/*
2 * Copyright (C) 2014-2026 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
35typedef int socklen_t;
36typedef IN_ADDR in_addr_t;
37
38#else
39#include <unistd.h>
40#include <fcntl.h>
41#include <sys/types.h>
42#include <sys/socket.h>
43#include <sys/select.h>
44#include <netinet/in.h>
45#include <netdb.h>
46#include <arpa/inet.h>
47#define closesocket(a) close(a)
48#define LASTERROR errno
49#define ERRNO_INTR EINTR
50#endif /* __WINDOWS__ */
51
52#include <signal.h>
53
54using namespace NSROOT;
55
56static int __addressFamily(SOCKET_AF_t saf)
57{
58 switch(saf)
59 {
60 case SOCKET_AF_INET4:
61 return AF_INET;
62 case SOCKET_AF_INET6:
63 return AF_INET6;
64 default:
65 return AF_UNSPEC;
66 }
67}
68
69namespace NSROOT
70{
71
72 struct SocketAddress
73 {
74 sockaddr_storage data;
75 socklen_t sa_len;
76
77 SocketAddress() { Clear(AF_UNSPEC); }
78 SocketAddress(int family) { Clear(family); }
79 inline sockaddr* sa() { return (sockaddr*)&data; }
80 inline int sa_family() { return data.ss_family; }
81 void Clear(int family)
82 {
83 memset(&data, 0, sizeof(data));
84 data.ss_family = family;
85 sa_len = (family == AF_INET ? sizeof(sockaddr_in) : sizeof(sockaddr_in6));
86 }
87 };
88
89}
90
95
96static char my_hostname[SOCKET_HOSTNAME_MAXSIZE];
97
98TcpSocket::TcpSocket()
99: NetSocket()
100, m_socket(INVALID_SOCKET_VALUE)
101, m_rcvbuf(SOCKET_RCVBUF_MINSIZE)
102, m_errno(0)
103, m_attempt(SOCKET_READ_ATTEMPT)
104, m_buffer(nullptr)
105, m_bufptr(nullptr)
106, m_buflen(SOCKET_BUFFER_SIZE)
107, m_rcvlen(0)
108{
109}
110
111TcpSocket::~TcpSocket()
112{
113 if (TcpSocket::IsValid())
115 if (m_buffer)
116 delete[] m_buffer;
117}
118
119static int __connectAddr(struct addrinfo *addr, net_socket_t *s, int rcvbuf)
120{
121 int err = 0;
122
123 // set my hostname if it hasn't already been done
124 if ((my_hostname[0] == '\0') && (gethostname(my_hostname, sizeof(my_hostname)) < 0))
125 {
126 err = LASTERROR;
127 DBG(DBG_ERROR, "%s: gethostname failed (%d)\n", __FUNCTION__, err);
128 return err;
129 }
130
131 *s = socket(addr->ai_family, addr->ai_socktype, addr->ai_protocol);
132 if (*s == INVALID_SOCKET_VALUE)
133 {
134 err = LASTERROR;
135 DBG(DBG_ERROR, "%s: invalid socket (%d)\n", __FUNCTION__, err);
136 return err;
137 }
138
139 {
140 int opt_rcvbuf = (rcvbuf < SOCKET_RCVBUF_MINSIZE ? SOCKET_RCVBUF_MINSIZE : rcvbuf);
141 if (setsockopt(*s, SOL_SOCKET, SO_RCVBUF, (char*)&opt_rcvbuf, sizeof(opt_rcvbuf)))
142 DBG(DBG_WARN, "%s: could not set SO_RCVBUF from socket (%d)\n", __FUNCTION__, LASTERROR);
143 }
144
145 {
146#ifdef __WINDOWS__
147 int opt_timeo = SOCKET_TIMEOUT_SEC * 1000;
148#else
149 struct timeval opt_timeo;
150 opt_timeo.tv_sec = SOCKET_TIMEOUT_SEC;
151 opt_timeo.tv_usec = 0;
152#endif
153 if (setsockopt(*s, SOL_SOCKET, SO_SNDTIMEO, (char*)&opt_timeo, sizeof(opt_timeo)))
154 DBG(DBG_WARN, "%s: could not set SO_SNDTIMEO from socket (%d)\n", __FUNCTION__, LASTERROR);
155 }
156
157#ifdef SO_NOSIGPIPE
158 {
159 int opt_set = 1;
160 if (setsockopt(*s, SOL_SOCKET, SO_NOSIGPIPE, (char*)&opt_set, sizeof(int)))
161 DBG(DBG_WARN, "%s: could not set SO_NOSIGPIPE from socket (%d)\n", __FUNCTION__, LASTERROR);
162 }
163#endif
164
165 // configure the socket in non-blocking mode temporarily and so the connection
166 // attempt timeout will be handled by the internal select() call
167#ifdef __WINDOWS__
168 {
169 u_long nonblock = 1;
170 ioctlsocket(*s, FIONBIO, &nonblock);
171 }
172#else
173 int flags = fcntl(*s, F_GETFL, 0);
174 if (flags == -1) flags = 0;
175 fcntl(*s, F_SETFL, flags | O_NONBLOCK);
176#endif
177
178 if (connect(*s, addr->ai_addr, addr->ai_addrlen) == 0)
179 {
180 // restore blocking mode
181#ifdef __WINDOWS__
182 u_long nonblock = 0;
183 ioctlsocket(*s, FIONBIO, &nonblock);
184#else
185 fcntl(*s, F_SETFL, flags);
186#endif
187 DBG(DBG_PROTO, "%s: connected to socket(%p)\n", __FUNCTION__, s);
188 return 0;
189 }
190
191 err = LASTERROR;
192#ifdef __WINDOWS__
193 if (err != WSAEWOULDBLOCK && err != WSAEINPROGRESS)
194 {
195 DBG(DBG_ERROR, "%s: failed to connect (%d)\n", __FUNCTION__, err);
196 closesocket(*s);
197 *s = INVALID_SOCKET_VALUE;
198 return err;
199 }
200#else
201 if (err != EINPROGRESS)
202 {
203 DBG(DBG_ERROR, "%s: failed to connect (%d)\n", __FUNCTION__, err);
204 closesocket(*s);
205 *s = INVALID_SOCKET_VALUE;
206 return err;
207 }
208#endif
209
210 // wait for socket writable within the timeout
211 fd_set fds;
212 FD_ZERO(&fds);
213 FD_SET(*s, &fds);
214 struct timeval tv;
215 tv.tv_sec = SOCKET_TIMEOUT_SEC;
216 tv.tv_usec = 0;
217
218 int r = select((*s) + 1, nullptr, &fds, nullptr, &tv);
219 if (r > 0)
220 {
221 // check socket error
222 int so_error = 0;
223 socklen_t so_len = sizeof(so_error);
224 if (getsockopt(*s, SOL_SOCKET, SO_ERROR, (char*)&so_error, &so_len) == 0)
225 {
226 if (so_error != 0)
227 {
228 DBG(DBG_ERROR, "%s: failed to connect (SO_ERROR=%d)\n", __FUNCTION__, so_error);
229 closesocket(*s);
230 *s = INVALID_SOCKET_VALUE;
231 return so_error;
232 }
233 }
234 // restore blocking mode
235#ifdef __WINDOWS__
236 u_long nonblock = 0;
237 ioctlsocket(*s, FIONBIO, &nonblock);
238#else
239 fcntl(*s, F_SETFL, flags);
240#endif
241 DBG(DBG_PROTO, "%s: connected to socket(%p)\n", __FUNCTION__, s);
242 return 0;
243 }
244
245 if (r == 0)
246 err = ETIMEDOUT;
247 else
248 err = LASTERROR;
249
250 DBG(DBG_ERROR, "%s: failed to connect (%d)\n", __FUNCTION__, err);
251 closesocket(*s);
252 *s = INVALID_SOCKET_VALUE;
253 return err;
254}
255
256bool TcpSocket::Connect(const char *server, unsigned port, int rcvbuf)
257{
258 struct addrinfo hints;
259 struct addrinfo *result, *addr;
260 char service[33];
261 int err;
262
263 if (IsValid())
264 Disconnect();
265
266 if (rcvbuf > SOCKET_RCVBUF_MINSIZE)
267 m_rcvbuf = rcvbuf;
268
269 memset(&hints, 0, sizeof (hints));
270 hints.ai_family = AF_UNSPEC;
271 hints.ai_socktype = SOCK_STREAM;
272 hints.ai_protocol = IPPROTO_TCP;
273 snprintf(service, sizeof(service), "%u", port);
274
275 err = getaddrinfo(server, service, &hints, &result);
276 if (err)
277 {
278 switch (err)
279 {
280 case EAI_NONAME:
281 DBG(DBG_ERROR, "%s: the specified host is unknown\n", __FUNCTION__);
282 break;
283 case EAI_FAIL:
284 DBG(DBG_ERROR, "%s: a non-recoverable failure in name resolution occurred\n", __FUNCTION__);
285 break;
286 case EAI_MEMORY:
287 DBG(DBG_ERROR, "%s: a memory allocation failure occurred\n", __FUNCTION__);
288 break;
289 case EAI_AGAIN:
290 DBG(DBG_ERROR, "%s: a temporary error occurred on an authoritative name server\n", __FUNCTION__);
291 break;
292 default:
293 DBG(DBG_ERROR, "%s: unknown error %d\n", __FUNCTION__, err);
294 break;
295 }
296 m_errno = err;
297 return false;
298 }
299
300 for (addr = result; addr; addr = addr->ai_next)
301 {
302 err = __connectAddr(addr, &m_socket, m_rcvbuf);
303 if (!err)
304 break;
305 }
306 freeaddrinfo(result);
307 m_errno = err;
308 return (err ? false : true);
309}
310
311bool TcpSocket::SendData(const char* msg, size_t size)
312{
313 if (IsValid())
314 {
315
316#if defined(__WINDOWS__) || defined(SO_NOSIGPIPE)
317 size_t s = send(m_socket, msg, size, 0);
318 if (s != size)
319 {
320 m_errno = LASTERROR;
321 return false;
322 }
323#elif defined(MSG_NOSIGNAL)
324 size_t s = send(m_socket, msg, size, MSG_NOSIGNAL);
325 if (s != size)
326 {
327 m_errno = LASTERROR;
328 return false;
329 }
330#else
331 sigset_t sig_block, sig_restore, sig_pending;
332 sigemptyset(&sig_block);
333 sigaddset(&sig_block, SIGPIPE);
334 /*
335 * Block SIGPIPE for this thread.
336 * This works since kernel sends SIGPIPE to the thread that called write(),
337 * not to the whole process.
338 */
339 if (pthread_sigmask(SIG_BLOCK, &sig_block, &sig_restore) != 0)
340 return false;
341 /*
342 * Check if SIGPIPE is already pending.
343 */
344 int sigpipe_pending = -1;
345 if (sigpending(&sig_pending) != -1)
346 sigpipe_pending = sigismember(&sig_pending, SIGPIPE);
347 if (sigpipe_pending == -1)
348 {
349 pthread_sigmask(SIG_SETMASK, &sig_restore, nullptr);
350 return false;
351 }
352
353 size_t s = send(m_socket, msg, size, 0);
354 if (s != size)
355 {
356 m_errno = LASTERROR;
357 /*
358 * Fetch generated SIGPIPE if write() failed with EPIPE.
359 * However, if SIGPIPE was already pending before calling write(), it was
360 * also generated and blocked by caller, and caller may expect that it can
361 * fetch it later. Since signals are not queued, we don't fetch it in this
362 * case.
363 */
364 if (m_errno == EPIPE && sigpipe_pending == 0)
365 {
366 struct timespec ts;
367 ts.tv_sec = 0;
368 ts.tv_nsec = 0;
369 int sig;
370 while ((sig = sigtimedwait(&sig_block, 0, &ts)) == -1 && LASTERROR == EINTR);
371 }
372 pthread_sigmask(SIG_SETMASK, &sig_restore, nullptr);
373 return false;
374 }
375 pthread_sigmask(SIG_SETMASK, &sig_restore, nullptr);
376#endif
377
378 m_errno = 0;
379 return true;
380 }
381 m_errno = ENOTCONN;
382 return false;
383}
384
385size_t TcpSocket::ReceiveData(void *buf, size_t n)
386{
387 if (IsValid())
388 {
389 m_errno = 0;
390 size_t rcvlen = 0;
391 char *p = (char*)buf;
392
393 // Check for data remaining in buffer
394 if (m_buffer)
395 {
396 if (m_bufptr < m_buffer + m_rcvlen)
397 {
398 rcvlen = m_rcvlen - (m_bufptr - m_buffer);
399 if (rcvlen > n)
400 rcvlen = n;
401 memcpy(p, m_bufptr, rcvlen);
402 m_bufptr += rcvlen;
403 p += rcvlen;
404 n -= rcvlen;
405 if (n == 0)
406 return rcvlen;
407 }
408 }
409 else if ((m_buffer = new char[m_buflen]) == nullptr)
410 {
411 m_errno = ENOMEM;
412 DBG(DBG_ERROR, "%s: cannot allocate %u bytes for buffer\n", __FUNCTION__, (unsigned)m_buflen);
413 return 0;
414 }
415 // Reset buffer
416 m_bufptr = m_buffer;
417 m_rcvlen = 0;
418
419 struct timeval tv;
420 fd_set fds;
421 int r = 0, hangcount = 0;
422
423 while (n > 0)
424 {
425 tv = m_timeout;
426 FD_ZERO(&fds);
427 FD_SET(m_socket, &fds);
428 r = select(m_socket + 1, &fds, nullptr, nullptr, &tv);
429 if (r > 0)
430 {
431 // Under threshold use buffering
432 if (n < m_buflen)
433 {
434 if ((r = recv(m_socket, m_buffer, m_buflen, 0)) > 0)
435 {
436 m_rcvlen = r;
437 size_t s = r;
438 if (s > n)
439 s = n;
440 memcpy(p, m_buffer, s);
441 m_bufptr = m_buffer + s;
442 p += s;
443 n -= s;
444 rcvlen += s;
445 }
446 }
447 // No buffering
448 else
449 {
450 if ((r = recv(m_socket, p, n, 0)) > 0)
451 {
452 p += r;
453 n -= r;
454 rcvlen += r;
455 }
456 }
457 }
458 if (r == 0)
459 {
460 DBG(DBG_INFO, "%s: socket(%p) timed out (%d)\n", __FUNCTION__, &m_socket, hangcount);
461 m_errno = ETIMEDOUT;
462 if (++hangcount >= m_attempt)
463 break;
464 }
465 if (r < 0)
466 {
467 m_errno = LASTERROR;
468 if (m_errno != ERRNO_INTR)
469 break;
470 }
471 }
472 return rcvlen;
473 }
474 m_errno = ENOTCONN;
475 return 0;
476}
477
478size_t TcpSocket::BlockingRead(void *buf, size_t n)
479{
480 if (IsValid() && n > 0)
481 {
482 // Check for data remaining in buffer
483 if (m_buffer)
484 {
485 if (m_bufptr < m_buffer + m_rcvlen)
486 {
487 size_t rcvlen = m_rcvlen - (m_bufptr - m_buffer);
488 if (rcvlen > n)
489 rcvlen = n;
490 memcpy(buf, m_bufptr, rcvlen);
491 m_bufptr += rcvlen;
492 return rcvlen;
493 }
494 }
495
496 int r = 0;
497 if ((r = recv(m_socket, (char*)buf, n, 0)) > 0)
498 return r;
499 }
500 return 0;
501}
502
504{
505 if (IsValid())
506 {
507 if (shutdown(m_socket, SHUT_RDWR) == 0)
508 {
509 struct timeval tv;
510 fd_set fds;
511 tv.tv_sec = 1;
512 tv.tv_usec = 0;
513 char buf[256];
514 for (;;)
515 {
516 FD_ZERO(&fds);
517 FD_SET(m_socket, &fds);
518 if (select(m_socket + 1, &fds, nullptr, nullptr, &tv) > 0 &&
519 recv(m_socket, buf, sizeof(buf), 0) > 0)
520 {
521 // polling
522 tv.tv_sec = 0;
523 tv.tv_usec = 0;
524 continue;
525 }
526 break;
527 }
528 }
529
530 closesocket(m_socket);
531 m_socket = INVALID_SOCKET_VALUE;
532 m_rcvlen = 0;
533 }
534}
535
537{
538 return (m_socket == INVALID_SOCKET_VALUE ? false : true);
539}
540
541int TcpSocket::Listen(timeval *timeout)
542{
543 if (IsValid())
544 {
545 fd_set fds;
546 int r;
547
548 FD_ZERO(&fds);
549 FD_SET(m_socket, &fds);
550 r = select(m_socket + 1, &fds, nullptr, nullptr, timeout);
551 if (r < 0)
552 m_errno = LASTERROR;
553 return r;
554 }
555 m_errno = ENOTCONN;
556 return -1;
557}
558
560{
561 char rhost[INET6_ADDRSTRLEN];
562 memset(rhost, 0, INET6_ADDRSTRLEN);
563
564 if (!IsValid())
565 return rhost;
566
567 char addr[sizeof(sockaddr_in6)];
568 socklen_t addr_len = sizeof(addr);
569
570 if (getpeername(m_socket, (sockaddr*)&addr, &addr_len) == 0)
571 getnameinfo((sockaddr*)&addr, addr_len, rhost, sizeof(rhost), nullptr, 0, NI_NUMERICHOST);
572 else
573 m_errno = LASTERROR;
574
575 return rhost;
576}
577
579{
580 char host[INET6_ADDRSTRLEN];
581 memset(host, 0, INET6_ADDRSTRLEN);
582
583 if (!IsValid())
584 return host;
585
586 char addr[sizeof(sockaddr_in6)];
587 socklen_t addr_len = sizeof(addr);
588
589 if (getsockname(m_socket, (sockaddr*)&addr, &addr_len) == 0)
590 getnameinfo((sockaddr*)&addr, addr_len, host, sizeof(host), nullptr, 0, NI_NUMERICHOST);
591 else
592 m_errno = LASTERROR;
593
594 return host;
595}
596
598{
599 return my_hostname;
600}
601
606
607TcpServerSocket::TcpServerSocket()
608: m_socket(INVALID_SOCKET_VALUE)
609, m_errno(0)
610, m_requestQueueSize(0)
611{
612 m_addr = new(SocketAddress);
613}
614
615TcpServerSocket::~TcpServerSocket()
616{
617 Close();
618 if (m_addr)
619 {
620 delete m_addr;
621 m_addr = nullptr;
622 }
623}
624
625bool TcpServerSocket::Create(SOCKET_AF_t af)
626{
627 if (IsValid())
628 return false;
629
630 m_addr->Clear(__addressFamily(af));
631 m_socket = socket(m_addr->sa_family(), SOCK_STREAM, 0);
632 if (!IsValid())
633 {
634 m_errno = LASTERROR;
635 DBG(DBG_ERROR, "%s: invalid socket (%d)\n", __FUNCTION__, m_errno);
636 return false;
637 }
638
639 int opt_set;
640#ifdef __WINDOWS__
641 // The bind will succeed even an other socket is currently listening on the
642 // same address. So enable the option SO_EXCLUSIVEADDRUSE will fix the issue.
643 opt_set = 1;
644 if (setsockopt(m_socket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*)&opt_set, sizeof(int)))
645 {
646 m_errno = LASTERROR;
647 DBG(DBG_ERROR, "%s: could not set SO_EXCLUSIVEADDRUSE from socket (%d)\n", __FUNCTION__, m_errno);
648 return false;
649 }
650#else
651 // Reuse address. The bind will fail only if an other socket is currently
652 // listening on the same address.
653 opt_set = 1;
654 if (setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt_set, sizeof(int)))
655 {
656 m_errno = LASTERROR;
657 DBG(DBG_ERROR, "%s: could not set SO_REUSEADDR from socket (%d)\n", __FUNCTION__, m_errno);
658 return false;
659 }
660#endif
661
662 return true;
663}
664
666{
667 return (m_socket == INVALID_SOCKET_VALUE ? false : true);
668}
669
670bool TcpServerSocket::Bind(unsigned port)
671{
672 if (!IsValid())
673 return false;
674 int r = 0;
675
676 m_addr->Clear(m_addr->sa_family());
677 switch (m_addr->sa_family())
678 {
679 case AF_INET:
680 {
681 sockaddr_in* sa = (sockaddr_in*)m_addr->sa();
682 sa->sin_addr.s_addr = htonl(INADDR_ANY);
683 sa->sin_port = htons(port);
684 r = bind(m_socket, m_addr->sa(), m_addr->sa_len);
685 break;
686 }
687 case AF_INET6:
688 {
689 sockaddr_in6* sa = (sockaddr_in6*)m_addr->sa();
690 sa->sin6_addr = in6addr_any;
691 sa->sin6_port = htons(port);
692 r = bind(m_socket, m_addr->sa(), m_addr->sa_len);
693 break;
694 }
695 }
696
697 if (r)
698 {
699 m_errno = LASTERROR;
700 DBG(DBG_ERROR, "%s: could not bind to address (%d)\n", __FUNCTION__, m_errno);
701 return false;
702 }
703 return true;
704}
705
706bool TcpServerSocket::ListenConnection(int queueSize /*= SOCKET_LISTEN_QUEUE_SIZE*/)
707{
708 if (!IsValid())
709 return false;
710
711 if (listen(m_socket, queueSize))
712 {
713 m_errno = LASTERROR;
714 DBG(DBG_ERROR, "%s: listen failed (%d)\n", __FUNCTION__, m_errno);
715 return false;
716 }
717 m_requestQueueSize = queueSize;
718 return true;
719}
720
721TcpServerSocket::AcceptStatus TcpServerSocket::AcceptConnection(
722 TcpSocket& socket,
723 int timeout)
724{
725 struct timeval tv = { timeout, 0 };
726 fd_set fds;
727 int r = 0;
728 FD_ZERO(&fds);
729 FD_SET(m_socket, &fds);
730 r = select(m_socket + 1, &fds, nullptr, nullptr, &tv);
731 // on timed out, it should try again
732 if (r == 0)
733 return ACCEPT_TIMEOUT;
734 if (r < 0)
735 {
736 m_errno = LASTERROR;
737 // on interruption, it should try again
738 if (m_errno == ERRNO_INTR)
739 return ACCEPT_TIMEOUT;
740 // on unrecoverable error, it should break
741 return ACCEPT_ERROR;
742 }
743
744 m_addr->sa_len = sizeof(m_addr->data);
745 socket.m_socket = accept(m_socket, m_addr->sa(), &m_addr->sa_len);
746
747 if (!socket.IsValid())
748 {
749 // report failure
750 m_errno = LASTERROR;
751 // it should try again
752 return ACCEPT_FAILURE;
753 }
754
755 int opt_set;
756#ifdef SO_NOSIGPIPE
757 opt_set = 1;
758 if (setsockopt(socket.m_socket, SOL_SOCKET, SO_NOSIGPIPE, (char*)&opt_set, sizeof(int)))
759 DBG(DBG_WARN, "%s: could not set SO_NOSIGPIPE from socket (%d)\n", __FUNCTION__, LASTERROR);
760#endif
761#ifdef SO_KEEPALIVE
762 opt_set = 1;
763 if (setsockopt(socket.m_socket, SOL_SOCKET, SO_KEEPALIVE, (char*)&opt_set, sizeof(int)))
764 {
765 DBG(DBG_ERROR, "%s: could not set SO_KEEPALIVE from socket (%d)\n", __FUNCTION__, LASTERROR);
766 return ACCEPT_FAILURE;
767 }
768#endif
769
770#ifdef __WINDOWS__
771 int opt_timeo = SOCKET_TIMEOUT_SEC * 1000;
772#else
773 struct timeval opt_timeo;
774 opt_timeo.tv_sec = SOCKET_TIMEOUT_SEC;
775 opt_timeo.tv_usec = 0;
776#endif
777 if (setsockopt(socket.m_socket, SOL_SOCKET, SO_SNDTIMEO, (char*)&opt_timeo, sizeof(opt_timeo)))
778 DBG(DBG_WARN, "%s: could not set SO_SNDTIMEO from socket (%d)\n", __FUNCTION__, LASTERROR);
779
780 socket.SetReadAttempt(0);
781 return ACCEPT_SUCCESS;
782}
783
785{
786 char rhost[INET6_ADDRSTRLEN];
787 memset(rhost, 0, INET6_ADDRSTRLEN);
788 getnameinfo(m_addr->sa(), m_addr->sa_len, rhost, sizeof(rhost), nullptr, 0, NI_NUMERICHOST);
789 return rhost;
790}
791
793{
794 if (IsValid())
795 {
796 closesocket(m_socket);
797 m_socket = INVALID_SOCKET_VALUE;
798 }
799}
800
805
806UdpSocket::UdpSocket()
807: m_socket(INVALID_SOCKET_VALUE)
808, m_errno(0)
809, m_buffer(nullptr)
810, m_bufptr(nullptr)
811, m_buflen(SOCKET_BUFFER_SIZE)
812, m_rcvlen(0)
813{
814 m_addr = new SocketAddress;
815 m_from = new SocketAddress;
816}
817
818UdpSocket::UdpSocket(size_t bufferSize)
819: m_socket(INVALID_SOCKET_VALUE)
820, m_errno(0)
821, m_buffer(nullptr)
822, m_bufptr(nullptr)
823, m_buflen(bufferSize)
824, m_rcvlen(0)
825{
826 m_addr = new SocketAddress;
827 m_from = new SocketAddress;
828}
829
830UdpSocket::~UdpSocket()
831{
832 if (IsValid())
833 {
834 closesocket(m_socket);
835 m_socket = INVALID_SOCKET_VALUE;
836 }
837 if (m_addr)
838 {
839 delete m_addr;
840 m_addr = nullptr;
841 }
842 if (m_from)
843 {
844 delete m_from;
845 m_from = nullptr;
846 }
847 if (m_buffer)
848 {
849 delete[] m_buffer;
850 m_buffer = m_bufptr = nullptr;
851 }
852}
853
854bool UdpSocket::Open(SOCKET_AF_t af, const char* target, unsigned port)
855{
856 return Open(af) && SetAddress(target, port);
857}
858
859bool UdpSocket::Open(SOCKET_AF_t af, bool broadcast /*= false*/)
860{
861 if (IsValid() && m_addr->sa_family() != __addressFamily(af))
862 {
863 closesocket(m_socket);
864 m_socket = INVALID_SOCKET_VALUE;
865 }
866 if (m_socket == INVALID_SOCKET_VALUE)
867 {
868 m_addr->Clear(__addressFamily(af));
869 m_from->Clear(AF_UNSPEC);
870 if ((m_socket = socket(m_addr->sa_family(), SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET_VALUE)
871 {
872 m_errno = LASTERROR;
873 DBG(DBG_ERROR, "%s: create socket failed (%d)\n", __FUNCTION__, m_errno);
874 return false;
875 }
876 if (broadcast && af == SOCKET_AF_INET4)
877 {
878 // set broadcast permission
879 int _broadcast = 1;
880 if (setsockopt(m_socket, SOL_SOCKET, SO_BROADCAST, (char*)&_broadcast, sizeof(_broadcast)))
881 {
882 m_errno = LASTERROR;
883 DBG(DBG_ERROR, "%s: could not set SO_BROADCAST from socket (%d)\n", __FUNCTION__, m_errno);
884 return false;
885 }
886 }
887 }
888 m_errno = 0;
889 return true;
890}
891
892bool UdpSocket::SetAddress(const char* target, unsigned port)
893{
894 if (!IsValid())
895 {
896 DBG(DBG_ERROR, "%s: invalid socket\n", __FUNCTION__);
897 return false;
898 }
899
900 unsigned char _addr[sizeof(struct in6_addr)];
901 if (inet_pton(m_addr->sa_family(), target, &_addr) == 0)
902 {
903 m_errno = LASTERROR;
904 DBG(DBG_ERROR, "%s: invalid address (%s)\n", __FUNCTION__, target);
905 return false;
906 }
907
908 m_addr->Clear(m_addr->sa_family());
909 switch(m_addr->sa_family())
910 {
911 case AF_INET:
912 {
913 sockaddr_in* sa = (sockaddr_in*)m_addr->sa();
914 memcpy(&(sa->sin_addr.s_addr), _addr, sizeof(in_addr_t));
915 sa->sin_port = htons(port);
916 break;
917 }
918 case AF_INET6:
919 {
920 sockaddr_in6* sa = (sockaddr_in6*)m_addr->sa();
921 memcpy(&(sa->sin6_addr), _addr, sizeof(struct in6_addr));
922 sa->sin6_port = htons(port);
923 break;
924 }
925 default:
926 m_errno = EINVAL;
927 DBG(DBG_ERROR, "%s: address familly unknown (%d)\n", __FUNCTION__, m_addr->sa_family());
928 return false;
929 }
930 m_errno = 0;
931 return true;
932}
933
934bool UdpSocket::SetMulticastTTL(int multicastTTL)
935{
936 if (!IsValid())
937 return false;
938
939 switch(m_addr->sa_family())
940 {
941 case AF_INET:
942 {
943 // The v4 multicast TTL socket option requires that the value be passed in an unsigned char
944 unsigned char _ttl = (unsigned char) multicastTTL;
945 if (setsockopt(m_socket, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&_ttl, sizeof(_ttl)))
946 {
947 m_errno = LASTERROR;
948 DBG(DBG_ERROR, "%s: could not set IP_MULTICAST_TTL from socket (%d)\n", __FUNCTION__, m_errno);
949 return false;
950 }
951 break;
952 }
953 case AF_INET6:
954 {
955 // The v6 multicast TTL socket option requires that the value be passed in as an integer
956 if (setsockopt(m_socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char*)&multicastTTL, sizeof(multicastTTL)))
957 {
958 m_errno = LASTERROR;
959 DBG(DBG_ERROR, "%s: could not set IPV6_MULTICAST_HOPS from socket (%d)\n", __FUNCTION__, m_errno);
960 return false;
961 }
962 break;
963 }
964 default:
965 m_errno = EINVAL;
966 DBG(DBG_ERROR, "%s: address familly unknown (%d)\n", __FUNCTION__, m_addr->sa_family());
967 return false;
968 }
969 m_errno = 0;
970 return true;
971}
972
973bool UdpSocket::SendData(const char* buf, size_t size)
974{
975 if (IsValid())
976 {
977 size_t s = sendto(m_socket, buf, size, 0, m_addr->sa(), m_addr->sa_len);
978 if (s != size)
979 {
980 m_errno = LASTERROR;
981 return false;
982 }
983 m_errno = 0;
984 return true;
985 }
986 m_errno = ENOTSOCK;
987 return false;
988}
989
990size_t UdpSocket::ReceiveData(void* buf, size_t n)
991{
992 if (IsValid())
993 {
994 m_errno = 0;
995 size_t len = 0;
996
997 // fill rest of data from buffer
998 if (m_buffer)
999 {
1000 if (m_bufptr < m_buffer + m_rcvlen)
1001 {
1002 len = m_rcvlen - (m_bufptr - m_buffer);
1003 if (len > n)
1004 len = n;
1005 memcpy(buf, m_bufptr, len);
1006 m_bufptr += len;
1007 return len;
1008 }
1009 }
1010 else if ((m_buffer = new char[m_buflen]) == nullptr)
1011 {
1012 m_errno = ENOMEM;
1013 DBG(DBG_ERROR, "%s: cannot allocate %u bytes for buffer\n", __FUNCTION__, (unsigned)m_buflen);
1014 return 0;
1015 }
1016 // fill buffer with the next incoming datagram
1017 m_bufptr = m_buffer;
1018 m_rcvlen = 0;
1019
1020 struct timeval tv;
1021 fd_set fds;
1022 int r = 0;
1023
1024 tv = m_timeout;
1025 FD_ZERO(&fds);
1026 FD_SET(m_socket, &fds);
1027 r = select(m_socket + 1, &fds, nullptr, nullptr, &tv);
1028 if (r > 0)
1029 {
1030 if ((r = recvfrom(m_socket, m_buffer, m_buflen, 0, m_from->sa(), &m_from->sa_len)) > 0)
1031 {
1032 m_rcvlen = len = r;
1033 if (m_rcvlen == m_buflen)
1034 DBG(DBG_WARN, "%s: datagram have been truncated (%d)\n", __FUNCTION__, r);
1035 if (len > n)
1036 len = n;
1037 memcpy(buf, m_buffer, len);
1038 m_bufptr += len;
1039 }
1040 }
1041 if (r == 0)
1042 {
1043 m_errno = ETIMEDOUT;
1044 DBG(DBG_DEBUG, "%s: socket(%p) timed out\n", __FUNCTION__, &m_socket);
1045 }
1046 if (r < 0)
1047 {
1048 m_errno = LASTERROR;
1049 DBG(DBG_ERROR, "%s: socket(%p) read error (%d)\n", __FUNCTION__, &m_socket, m_errno);
1050 }
1051 return len;
1052 }
1053 m_errno = ENOTSOCK;
1054 return 0;
1055}
1056
1058{
1059 return (m_socket == INVALID_SOCKET_VALUE ? false : true);
1060}
1061
1063{
1064 char host[INET6_ADDRSTRLEN];
1065 memset(host, 0, INET6_ADDRSTRLEN);
1066 getnameinfo(m_from->sa(), m_from->sa_len, host, sizeof(host), nullptr, 0, NI_NUMERICHOST);
1067 return host;
1068}
1069
1074
1075UdpServerSocket::UdpServerSocket()
1076: m_socket(INVALID_SOCKET_VALUE)
1077, m_errno(0)
1078, m_buffer(nullptr)
1079, m_bufptr(nullptr)
1080, m_buflen(SOCKET_BUFFER_SIZE)
1081, m_rcvlen(0)
1082{
1083 m_addr = new SocketAddress;
1084 m_from = new SocketAddress;
1085 m_timeout.tv_sec = SOCKET_TIMEOUT_SEC;
1086 m_timeout.tv_usec = SOCKET_TIMEOUT_USEC;
1087
1088}
1089
1090UdpServerSocket::UdpServerSocket(size_t bufferSize)
1091: m_socket(INVALID_SOCKET_VALUE)
1092, m_errno(0)
1093, m_buffer(nullptr)
1094, m_bufptr(nullptr)
1095, m_buflen(bufferSize)
1096, m_rcvlen(0)
1097{
1098 m_addr = new SocketAddress;
1099 m_from = new SocketAddress;
1100 m_timeout.tv_sec = SOCKET_TIMEOUT_SEC;
1101 m_timeout.tv_usec = SOCKET_TIMEOUT_USEC;
1102}
1103
1104UdpServerSocket::~UdpServerSocket()
1105{
1106 if (IsValid())
1107 {
1108 closesocket(m_socket);
1109 m_socket = INVALID_SOCKET_VALUE;
1110 }
1111 if (m_addr)
1112 {
1113 delete m_addr;
1114 m_addr = nullptr;
1115 }
1116 if (m_from)
1117 {
1118 delete m_from;
1119 m_from = nullptr;
1120 }
1121 if (m_buffer)
1122 {
1123 delete[] m_buffer;
1124 m_buffer = m_bufptr = nullptr;
1125 }
1126}
1127
1128bool UdpServerSocket::Create(SOCKET_AF_t af)
1129{
1130 if (IsValid())
1131 return false;
1132
1133 m_addr->Clear(__addressFamily(af));
1134 m_socket = socket(m_addr->sa_family(), SOCK_DGRAM, 0);
1135 if (!IsValid())
1136 {
1137 m_errno = LASTERROR;
1138 DBG(DBG_ERROR, "%s: invalid socket (%d)\n", __FUNCTION__, m_errno);
1139 return false;
1140 }
1141
1142 int opt = 1;
1143 if (setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt)))
1144 {
1145 m_errno = LASTERROR;
1146 DBG(DBG_ERROR, "%s: could not set reuseaddr from socket (%d)\n", __FUNCTION__, m_errno);
1147 return false;
1148 }
1149 return true;
1150}
1151
1153{
1154 return (m_socket == INVALID_SOCKET_VALUE ? false : true);
1155}
1156
1157bool UdpServerSocket::Bind(unsigned port, bool reuse /*= false*/)
1158{
1159 if (!IsValid())
1160 return false;
1161
1162 m_addr->Clear(m_addr->sa_family());
1163 switch (m_addr->sa_family())
1164 {
1165 case AF_INET:
1166 {
1167 sockaddr_in* sa = (sockaddr_in*)m_addr->sa();
1168 sa->sin_addr.s_addr = htonl(INADDR_ANY);
1169 sa->sin_port = htons(port);
1170 break;
1171 }
1172 case AF_INET6:
1173 {
1174 sockaddr_in6* sa = (sockaddr_in6*)m_addr->sa();
1175 sa->sin6_addr = in6addr_any;
1176 sa->sin6_port = htons(port);
1177 break;
1178 }
1179 default:
1180 m_errno = EINVAL;
1181 DBG(DBG_ERROR, "%s: address familly unknown (%d)\n", __FUNCTION__, m_addr->sa_family());
1182 return false;
1183 }
1184
1185#ifdef __WINDOWS__
1186 // disable the option SO_EXCLUSIVEADDRUSE to allow reuse.
1187 int opt = (reuse ? 0 : 1);
1188 if (setsockopt(m_socket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*)&opt, sizeof(opt)))
1189 {
1190 m_errno = LASTERROR;
1191 DBG(DBG_ERROR, "%s: could not set exclusiveaddruse from socket (%d)\n", __FUNCTION__, m_errno);
1192 return false;
1193 }
1194#elif defined(SO_REUSEPORT)
1195 int opt = (reuse ? 1 : 0);
1196 if (setsockopt(m_socket, SOL_SOCKET, SO_REUSEPORT, (char*)&opt, sizeof(opt)))
1197 {
1198 m_errno = LASTERROR;
1199 DBG(DBG_ERROR, "%s: could not set reuseport from socket (%d)\n", __FUNCTION__, m_errno);
1200 return false;
1201 }
1202#else
1203 int opt = (reuse ? 1 : 0);
1204 if (setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt)))
1205 {
1206 m_errno = LASTERROR;
1207 DBG(DBG_ERROR, "%s: could not set reuseaddr from socket (%d)\n", __FUNCTION__, m_errno);
1208 return false;
1209 }
1210#endif
1211
1212 if (bind(m_socket, m_addr->sa(), m_addr->sa_len) != 0)
1213 {
1214 m_errno = LASTERROR;
1215 DBG(DBG_ERROR, "%s: could not bind to address (%d)\n", __FUNCTION__, m_errno);
1216 return false;
1217 }
1218 m_errno = 0;
1219 return true;
1220}
1221
1222bool UdpServerSocket::Bind(const char* addr, unsigned port, bool reuse /*= false*/)
1223{
1224 if (!IsValid())
1225 return false;
1226
1227 unsigned char _addr[sizeof(struct in6_addr)];
1228 if (inet_pton(m_addr->sa_family(), addr, &_addr) == 0)
1229 {
1230 m_errno = LASTERROR;
1231 DBG(DBG_ERROR, "%s: invalid address (%s)\n", __FUNCTION__, addr);
1232 return false;
1233 }
1234
1235 m_addr->Clear(m_addr->sa_family());
1236 switch(m_addr->sa_family())
1237 {
1238 case AF_INET:
1239 {
1240 sockaddr_in* sa = (sockaddr_in*)m_addr->sa();
1241 memcpy(&(sa->sin_addr.s_addr), _addr, sizeof(in_addr_t));
1242 sa->sin_port = htons(port);
1243 break;
1244 }
1245 case AF_INET6:
1246 {
1247 sockaddr_in6* sa = (sockaddr_in6*)m_addr->sa();
1248 memcpy(&(sa->sin6_addr), _addr, sizeof(struct in6_addr));
1249 sa->sin6_port = htons(port);
1250 break;
1251 }
1252 default:
1253 m_errno = EINVAL;
1254 DBG(DBG_ERROR, "%s: address familly unknown (%d)\n", __FUNCTION__, m_addr->sa_family());
1255 return false;
1256 }
1257
1258#ifdef __WINDOWS__
1259 // disable the option SO_EXCLUSIVEADDRUSE to allow reuse.
1260 int opt = (reuse ? 0 : 1);
1261 if (setsockopt(m_socket, SOL_SOCKET, SO_EXCLUSIVEADDRUSE, (char*)&opt, sizeof(opt)))
1262 {
1263 m_errno = LASTERROR;
1264 DBG(DBG_ERROR, "%s: could not set exclusiveaddruse from socket (%d)\n", __FUNCTION__, m_errno);
1265 return false;
1266 }
1267#elif defined(SO_REUSEPORT)
1268 int opt = (reuse ? 1 : 0);
1269 if (setsockopt(m_socket, SOL_SOCKET, SO_REUSEPORT, (char*)&opt, sizeof(opt)))
1270 {
1271 m_errno = LASTERROR;
1272 DBG(DBG_ERROR, "%s: could not set reuseport from socket (%d)\n", __FUNCTION__, m_errno);
1273 return false;
1274 }
1275#else
1276 int opt = (reuse ? 1 : 0);
1277 if (setsockopt(m_socket, SOL_SOCKET, SO_REUSEADDR, (char*)&opt, sizeof(opt)))
1278 {
1279 m_errno = LASTERROR;
1280 DBG(DBG_ERROR, "%s: could not set reuseaddr from socket (%d)\n", __FUNCTION__, m_errno);
1281 return false;
1282 }
1283#endif
1284
1285 if (bind(m_socket, m_addr->sa(), m_addr->sa_len) != 0)
1286 {
1287 m_errno = LASTERROR;
1288 DBG(DBG_ERROR, "%s: could not bind to address (%d)\n", __FUNCTION__, m_errno);
1289 return false;
1290 }
1291 m_errno = 0;
1292 return true;
1293}
1294
1296{
1297 if (!IsValid())
1298 return false;
1299
1300 switch(m_addr->sa_family())
1301 {
1302 case AF_INET:
1303 {
1304 // The v4 multicast TTL socket option requires that the value be passed in an unsigned char
1305 unsigned char _ttl = (unsigned char) multicastTTL;
1306 if (setsockopt(m_socket, IPPROTO_IP, IP_MULTICAST_TTL, (char*)&_ttl, sizeof(_ttl)))
1307 {
1308 m_errno = LASTERROR;
1309 DBG(DBG_ERROR, "%s: could not set IP_MULTICAST_TTL from socket (%d)\n", __FUNCTION__, m_errno);
1310 return false;
1311 }
1312 break;
1313 }
1314 case AF_INET6:
1315 {
1316 // The v6 multicast TTL socket option requires that the value be passed in as an integer
1317 if (setsockopt(m_socket, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char*)&multicastTTL, sizeof(multicastTTL)))
1318 {
1319 m_errno = LASTERROR;
1320 DBG(DBG_ERROR, "%s: could not set IPV6_MULTICAST_HOPS from socket (%d)\n", __FUNCTION__, m_errno);
1321 return false;
1322 }
1323 break;
1324 }
1325 default:
1326 m_errno = EINVAL;
1327 DBG(DBG_ERROR, "%s: address familly unknown (%d)\n", __FUNCTION__, m_addr->sa_family());
1328 return false;
1329 }
1330 m_errno = 0;
1331 return true;
1332}
1333
1334bool UdpServerSocket::SetMulticastMembership(const char* group, bool join)
1335{
1336 if (!IsValid())
1337 return false;
1338
1339 switch(m_addr->sa_family())
1340 {
1341 case AF_INET:
1342 {
1343 struct ip_mreq mreq;
1344 if (inet_pton(AF_INET, group, &mreq.imr_multiaddr) == 0)
1345 {
1346 m_errno = LASTERROR;
1347 DBG(DBG_ERROR, "%s: invalid address (%d)\n", __FUNCTION__, m_errno);
1348 return false;
1349 }
1350 mreq.imr_interface.s_addr = htonl(INADDR_ANY);
1351 if (setsockopt(m_socket, IPPROTO_IP, join ? IP_ADD_MEMBERSHIP : IP_DROP_MEMBERSHIP, reinterpret_cast<const char*>(&mreq), sizeof(mreq)))
1352 {
1353 m_errno = LASTERROR;
1354 DBG(DBG_ERROR, "%s: could not set multicast membership from socket (%d)\n", __FUNCTION__, m_errno);
1355 return false;
1356 }
1357 break;
1358 }
1359 case AF_INET6:
1360 {
1361 struct ipv6_mreq mreq;
1362 if (inet_pton(AF_INET6, group, &mreq.ipv6mr_multiaddr) == 0)
1363 {
1364 m_errno = LASTERROR;
1365 DBG(DBG_ERROR, "%s: invalid address (%d)\n", __FUNCTION__, m_errno);
1366 return false;
1367 }
1368 mreq.ipv6mr_interface = 0;
1369 if (setsockopt(m_socket, IPPROTO_IPV6, join ? IPV6_JOIN_GROUP : IPV6_LEAVE_GROUP, reinterpret_cast<const char*>(&mreq), sizeof(mreq)))
1370 {
1371 m_errno = LASTERROR;
1372 DBG(DBG_ERROR, "%s: could not set multicast membership from socket (%d)\n", __FUNCTION__, m_errno);
1373 return false;
1374 }
1375 break;
1376 }
1377 default:
1378 m_errno = EINVAL;
1379 DBG(DBG_ERROR, "%s: address familly unknown (%d)\n", __FUNCTION__, m_addr->sa_family());
1380 return false;
1381 }
1382 m_errno = 0;
1383 return true;
1384}
1385
1387{
1388 if (IsValid())
1389 {
1390 m_errno = 0;
1391
1392 if (!m_buffer && (m_buffer = new char[m_buflen]) == nullptr)
1393 {
1394 m_errno = ENOMEM;
1395 DBG(DBG_ERROR, "%s: cannot allocate %u bytes for buffer\n", __FUNCTION__, (unsigned)m_buflen);
1396 return 0;
1397 }
1398 // reset buffer
1399 m_bufptr = m_buffer;
1400 m_rcvlen = 0;
1401
1402 fd_set fds;
1403 int r = 0;
1404
1405 FD_ZERO(&fds);
1406 FD_SET(m_socket, &fds);
1407 r = select(m_socket + 1, &fds, nullptr, nullptr, &m_timeout);
1408 if (r > 0)
1409 {
1410 if ((r = recvfrom(m_socket, m_buffer, m_buflen, 0, m_from->sa(), &m_from->sa_len)) > 0)
1411 {
1412 m_rcvlen = r;
1413 if (m_rcvlen == m_buflen)
1414 DBG(DBG_WARN, "%s: datagram have been truncated (%d)\n", __FUNCTION__, r);
1415 }
1416 }
1417 if (r == 0)
1418 {
1419 m_errno = ETIMEDOUT;
1420 DBG(DBG_DEBUG, "%s: socket(%p) timed out\n", __FUNCTION__, &m_socket);
1421 }
1422 if (r < 0)
1423 {
1424 m_errno = LASTERROR;
1425 DBG(DBG_ERROR, "%s: socket(%p) read error (%d)\n", __FUNCTION__, &m_socket, m_errno);
1426 }
1427 return m_rcvlen;
1428 }
1429 m_errno = ENOTSOCK;
1430 return 0;
1431}
1432
1434{
1435 char host[INET6_ADDRSTRLEN];
1436 memset(host, 0, INET6_ADDRSTRLEN);
1437 getnameinfo(m_from->sa(), m_from->sa_len, host, sizeof(host), nullptr, 0, NI_NUMERICHOST);
1438 return host;
1439}
1440
1441size_t UdpServerSocket::ReadData(void* buf, size_t n)
1442{
1443 if (IsValid())
1444 {
1445 m_errno = 0;
1446 size_t len = 0;
1447
1448 if (m_buffer && m_bufptr < m_buffer + m_rcvlen)
1449 {
1450 len = m_rcvlen - (m_bufptr - m_buffer);
1451 if (len > n)
1452 len = n;
1453 memcpy(buf, m_bufptr, len);
1454 m_bufptr += len;
1455 }
1456 return len;
1457 }
1458 m_errno = ENOTSOCK;
1459 return 0;
1460}
bool IsValid() const
Definition socket.cpp:665
bool Bind(unsigned port)
Definition socket.cpp:670
bool Create(SOCKET_AF_t af)
Definition socket.cpp:625
std::string GetRemoteAddrInfo()
Definition socket.cpp:784
AcceptStatus AcceptConnection(TcpSocket &socket, int timeout)
Definition socket.cpp:721
bool ListenConnection(int queueSize=SOCKET_LISTEN_QUEUE_SIZE)
Definition socket.cpp:706
virtual void Disconnect()
Definition socket.cpp:503
static const char * GetMyHostName()
Definition socket.cpp:597
std::string GetRemoteAddrInfo()
Definition socket.cpp:559
std::string GetHostAddrInfo()
Definition socket.cpp:578
virtual size_t ReceiveData(void *buf, size_t n)
Definition socket.cpp:385
void SetReadAttempt(int n)
Definition socket.h:83
virtual bool SendData(const char *buf, size_t size)
Definition socket.cpp:311
virtual bool IsValid() const
Definition socket.cpp:536
virtual bool Connect(const char *server, unsigned port, int rcvbuf)
Definition socket.cpp:256
int Listen(timeval *timeout)
Definition socket.cpp:541
virtual size_t BlockingRead(void *buf, size_t n)
Definition socket.cpp:478
bool Bind(unsigned port, bool reuse=false)
Definition socket.cpp:1157
bool SetMulticastTTL(int multicastTTL)
Definition socket.cpp:1295
size_t ReadData(void *buf, size_t n)
Definition socket.cpp:1441
bool Create(SOCKET_AF_t af)
Definition socket.cpp:1128
bool SetMulticastMembership(const char *group, bool join)
Definition socket.cpp:1334
std::string GetRemoteAddrInfo() const
Definition socket.cpp:1433
std::string GetRemoteAddrInfo() const
Definition socket.cpp:1062
size_t ReceiveData(void *buf, size_t n)
Definition socket.cpp:990
bool SetMulticastTTL(int multicastTTL)
Definition socket.cpp:934
bool Open(SOCKET_AF_t af, const char *target, unsigned port)
Definition socket.cpp:854
bool IsValid() const
Definition socket.cpp:1057
bool SetAddress(const char *target, unsigned port)
Definition socket.cpp:892
bool SendData(const char *buf, size_t size)
Definition socket.cpp:973