blob: 32afe8e15e54794e8bdb7f10f08a93cc62241a73 [file] [log] [blame]
Emeric Vigier2f625822012-08-06 11:09:52 -04001// Copyright (C) 1999-2005 Open Source Telecom Corporation.
2// Copyright (C) 2009 Leandro Melo de Sales <leandroal@gmail.com>
3// Copyright (C) 2006-2010 David Sugar, Tycho Softworks,
4//
5// This program is free software; you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation; either version 2 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU General Public License
16// along with this program; if not, write to the Free Software
17// Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18//
19// As a special exception, you may use this file as part of a free software
20// library without restriction. Specifically, if other files instantiate
21// templates or use macros or inline functions from this file, or you compile
22// this file and link it with other files to produce an executable, this
23// file does not by itself cause the resulting executable to be covered by
24// the GNU General Public License. This exception does not however
25// invalidate any other reasons why the executable file might be covered by
26// the GNU General Public License.
27//
28// This exception applies only to the code released under the name GNU
29// Common C++. If you copy code from other releases into a copy of GNU
30// Common C++, as the General Public License permits, the exception does
31// not apply to the code that you add in this way. To avoid misleading
32// anyone as to the status of such modified files, you must delete
33// this exception notice from them.
34//
35// If you write modifications of your own for GNU Common C++, it is your choice
36// whether to permit this exception to apply to your modifications.
37// If you do not wish that, delete this exception notice.
38//
39
40#include <cc++/config.h>
41#include <cc++/export.h>
42#include <cc++/exception.h>
43#include <cc++/thread.h>
44#include <cc++/address.h>
45#include <cc++/socket.h>
46#include "private.h"
47#include "nat.h"
48#include <fcntl.h>
49#include <cerrno>
50#include <cstdlib>
51#include <cstdarg>
52#include <cstdio>
53
54#ifndef WIN32
55#include <netinet/tcp.h>
56#endif
57
58#ifdef WIN32
59#include <io.h>
60#define socket_errno WSAGetLastError()
61#endif
62
63#ifndef WIN32
64#include <sys/ioctl.h>
65#ifdef HAVE_NET_IP6_H
66#include <netinet/ip6.h>
67#endif
68
69#if defined(__hpux) && defined(_XOPEN_SOURCE_EXTENDED)
70#undef _XOPEN_SOURCE_EXTENDED
71#endif
72
73#ifdef HAVE_NETINET_IN_H
74#include <netinet/in.h>
75#endif
76
77#if defined(__hpux)
78#define _XOPEN_SOURCE_EXTENDED
79#endif
80
81#ifdef HAVE_NET_IF_H
82#include <net/if.h>
83#endif
84#endif
85
86#ifndef WIN32
87#define socket_errno errno
88# ifndef O_NONBLOCK
89# define O_NONBLOCK O_NDELAY
90# endif
91# ifdef IPPROTO_IP
92# ifndef SOL_IP
93# define SOL_IP IPPROTO_IP
94# endif // !SOL_IP
95# endif // IPPROTO_IP
96#endif // !WIN32
97
98#ifndef INADDR_LOOPBACK
99#define INADDR_LOOPBACK (unsigned long)0x7f000001
100#endif
101
102#ifdef CCXX_NAMESPACES
103namespace ost {
104using namespace std;
105#endif
106
107#if defined(WIN32) && !defined(__MINGW32__)
108static SOCKET dupSocket(SOCKET so,enum Socket::State state)
109{
110 if (state == Socket::STREAM)
111 return dup((int)so);
112
113 HANDLE pidHandle = GetCurrentProcess();
114 HANDLE dupHandle;
115 if(DuplicateHandle(pidHandle, reinterpret_cast<HANDLE>(so), pidHandle, &dupHandle, 0, FALSE, DUPLICATE_SAME_ACCESS))
116 return reinterpret_cast<SOCKET>(dupHandle);
117 return INVALID_SOCKET;
118}
119# define DUP_SOCK(s,state) dupSocket(s,state)
120#else
121# define DUP_SOCK(s,state) dup(s)
122#endif
123
124Mutex Socket::mutex;
125
126bool Socket::check(Family fam)
127{
128 SOCKET so = INVALID_SOCKET;
129
130 switch(fam) {
131 case IPV4:
132 so = socket(fam, SOCK_DGRAM, IPPROTO_UDP);
133 break;
134#ifdef CCXX_IPV6
135 case IPV6:
136 so = socket(fam, SOCK_DGRAM, IPPROTO_UDP);
137 break;
138#endif
139 default:
140 return false;
141 }
142
143 if(so == INVALID_SOCKET)
144 return false;
145
146#ifdef WIN32
147 closesocket(so);
148#else
149 close(so);
150#endif
151 return true;
152}
153
154Socket::Socket()
155{
156 setSocket();
157}
158
159Socket::Socket(int domain, int type, int protocol)
160{
161 setSocket();
162 so = socket(domain, type, protocol);
163 if(so == INVALID_SOCKET) {
164 error(errCreateFailed,(char *)"Could not create socket",socket_errno);
165 return;
166 }
167#ifdef SO_NOSIGPIPE
168 int opt = 1;
169 setsockopt(so, SOL_SOCKET, SO_NOSIGPIPE, (char *)&opt, sizeof(opt));
170#endif
171 state = AVAILABLE;
172}
173
174Socket::Socket(SOCKET fd)
175{
176 setSocket();
177 if (fd == INVALID_SOCKET) {
178 error(errCreateFailed,(char *)"Invalid socket handle passed",0);
179 return;
180 }
181 so = fd;
182 state = AVAILABLE;
183}
184
185Socket::Socket(const Socket &orig)
186{
187 setSocket();
188 so = DUP_SOCK(orig.so,orig.state);
189 if(so == INVALID_SOCKET)
190 error(errCopyFailed,(char *)"Could not duplicate socket handle",socket_errno);
191 state = orig.state;
192}
193
194Socket::~Socket()
195{
196 endSocket();
197}
198
199void Socket::setSocket(void)
200{
201 flags.thrown = false;
202 flags.broadcast = false;
203 flags.route = true;
204 flags.keepalive = false;
205 flags.loopback = true;
206 flags.multicast = false;
207 flags.linger = false;
208 flags.ttl = 1;
209 errid = errSuccess;
210 errstr = NULL;
211 syserr = 0;
212 state = INITIAL;
213 so = INVALID_SOCKET;
214}
215
216Socket::Error Socket::sendLimit(int limit)
217{
218#ifdef SO_SNDLOWAT
219 if(setsockopt(so, SOL_SOCKET, SO_SNDLOWAT, (char *)&limit, sizeof(limit)))
220 return errInvalidValue;
221
222 return errSuccess;
223
224#else
225 return errServiceUnavailable;
226#endif
227}
228
229Socket::Error Socket::receiveLimit(int limit)
230{
231#ifdef SO_RCVLOWAT
232 if(setsockopt(so, SOL_SOCKET, SO_RCVLOWAT, (char *)&limit, sizeof(limit)))
233 return errInvalidValue;
234
235 return errSuccess;
236
237#else
238 return errServiceUnavailable;
239#endif
240}
241
242Socket::Error Socket::sendTimeout(timeout_t to)
243{
244#ifdef SO_SNDTIMEO
245 struct timeval tv;
246
247 tv.tv_sec = to / 1000;
248 tv.tv_usec = (to % 1000) * 1000;
249
250 if(setsockopt(so, SOL_SOCKET, SO_SNDTIMEO, (char *)&tv, sizeof(tv)))
251 return errInvalidValue;
252
253 return errSuccess;
254
255#else
256 return errServiceUnavailable;
257#endif
258}
259
260Socket::Error Socket::receiveTimeout(timeout_t to)
261{
262#ifdef SO_RCVTIMEO
263 struct timeval tv;
264
265 tv.tv_sec = to / 1000;
266 tv.tv_usec = (to % 1000) * 1000;
267
268 if(setsockopt(so, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof(tv)))
269 return errInvalidValue;
270
271 return errSuccess;
272#else
273 return errServiceUnavailable;
274#endif
275}
276
277Socket::Error Socket::sendBuffer(unsigned bufsize)
278{
279#ifdef SO_SNDBUF
280 if(setsockopt(so, SOL_SOCKET, SO_SNDBUF, (char *)&bufsize, sizeof(bufsize)))
281 return errInvalidValue;
282 return errSuccess;
283#else
284 return errServiceUnavailable;
285#endif
286}
287
288Socket::Error Socket::bufferSize(unsigned bufsize)
289{
290 Error err = receiveBuffer(bufsize);
291 if(err == errSuccess)
292 err = sendBuffer(bufsize);
293
294 return err;
295}
296
297Socket::Error Socket::receiveBuffer(unsigned bufsize)
298{
299#ifdef SO_RCVBUF
300 if(setsockopt(so, SOL_SOCKET, SO_RCVBUF, (char *)&bufsize, sizeof(bufsize)))
301 return errInvalidValue;
302 return errSuccess;
303#else
304 return errServiceUnavailable;
305#endif
306}
307
308ssize_t Socket::readLine(char *str, size_t request, timeout_t timeout)
309{
310 bool crlf = false;
311 bool nl = false;
312 size_t nleft = request - 1; // leave also space for terminator
313 int nstat,c;
314
315 if(request < 1)
316 return 0;
317
318 str[0] = 0;
319
320 while(nleft && !nl) {
321 if(timeout) {
322 if(!isPending(pendingInput, timeout)) {
323 error(errTimeout,(char *)"Read timeout", 0);
324 return -1;
325 }
326 }
327 nstat = ::recv(so, str, _IOLEN64 nleft, MSG_PEEK);
328 if(nstat <= 0) {
329 error(errInput,(char *)"Could not read from socket", socket_errno);
330 return -1;
331 }
332
333 // FIXME: if unique char in buffer is '\r' return "\r"
334 // if buffer end in \r try to read another char?
335 // and if timeout ??
336 // remember last \r
337
338 for(c=0; c < nstat; ++c) {
339 if(str[c] == '\n') {
340 if (c > 0 && str[c-1] == '\r')
341 crlf = true;
342 ++c;
343 nl = true;
344 break;
345 }
346 }
347 nstat = ::recv(so, str, _IOLEN64 c, 0);
348 // TODO: correct ???
349 if(nstat < 0)
350 break;
351
352 // adjust ending \r\n in \n
353 if(crlf) {
354 --nstat;
355 str[nstat - 1] = '\n';
356 }
357
358 str += nstat;
359 nleft -= nstat;
360 }
361 *str = 0;
362 return (ssize_t)(request - nleft - 1);
363}
364
365ssize_t Socket::readData(void *Target, size_t Size, char Separator, timeout_t timeout)
366{
367 if ((Separator == 0x0D) || (Separator == 0x0A))
368 return (readLine ((char *) Target, Size, timeout));
369
370 if (Size < 1)
371 return (0);
372
373 ssize_t nstat;
374
375 if (Separator == 0) { // Flat-out read for a number of bytes.
376 if (timeout) {
377 if (!isPending (pendingInput, timeout)) {
378 error(errTimeout);
379 return (-1);
380 }
381 }
382 nstat =::recv (so, (char *)Target, _IOLEN64 Size, 0);
383
384 if (nstat < 0) {
385 error (errInput);
386 return (-1);
387 }
388 return (nstat);
389 }
390 /////////////////////////////////////////////////////////////
391 // Otherwise, we have a special char separator to use
392 /////////////////////////////////////////////////////////////
393 bool found = false;
394 size_t nleft = Size;
395 int c;
396 char *str = (char *) Target;
397
398 memset (str, 0, Size);
399
400 while (nleft && !found) {
401 if (timeout) {
402 if (!isPending (pendingInput, timeout)) {
403 error(errTimeout);
404 return (-1);
405 }
406 }
407 nstat =::recv (so, str, _IOLEN64 nleft, MSG_PEEK);
408 if (nstat <= 0) {
409 error (errInput);
410 return (-1);
411 }
412
413 for (c = 0; (c < nstat) && !found; ++c) {
414 if (str[c] == Separator)
415 found = true;
416 }
417
418 memset (str, 0, nleft);
419 nstat =::recv (so, str, c, 0);
420 if (nstat < 0)
421 break;
422
423 str += nstat;
424 nleft -= nstat;
425 }
426 return (ssize_t)(Size - (ssize_t) nleft);
427}
428
429ssize_t Socket::writeData(const void *Source, size_t Size, timeout_t timeout)
430{
431 if (Size < 1)
432 return (0);
433
434 ssize_t nstat;
435 const char *Slide = (const char *) Source;
436
437 while (true) {
438 if (timeout) {
439 if (!isPending (pendingOutput, timeout)) {
440 error(errOutput);
441 return (-1);
442 }
443 }
444 nstat =::send (so, Slide, _IOLEN64 Size, MSG_NOSIGNAL);
445
446 if (nstat <= 0) {
447 error(errOutput);
448 return (-1);
449 }
450 Size -= nstat;
451 Slide += nstat;
452
453
454 if (Size <= 0)
455 break;
456 }
457 return (nstat);
458}
459
460bool Socket::isConnected(void) const
461{
462 return (Socket::state == CONNECTED) ? true : false;
463}
464
465bool Socket::isActive(void) const
466{
467 return (state != INITIAL) ? true : false;
468}
469
470bool Socket::operator!() const
471{
472 return (Socket::state == INITIAL) ? true : false;
473}
474
475void Socket::endSocket(void)
476{
477 if(Socket::state == STREAM) {
478 state = INITIAL;
479#ifdef WIN32
480 if(so != (UINT)-1) {
481 SOCKET sosave = so;
482 so = INVALID_SOCKET;
483 closesocket((int)sosave);
484 }
485#else
486 if(so > -1) {
487 SOCKET sosave = so;
488 so = INVALID_SOCKET;
489 close(sosave);
490 }
491#endif
492 return;
493 }
494
495 state = INITIAL;
496 if(so == INVALID_SOCKET)
497 return;
498
499#ifdef SO_LINGER
500 struct linger linger;
501
502 if(flags.linger) {
503 linger.l_onoff = 1;
504 linger.l_linger = 60;
505 }
506 else
507 linger.l_onoff = linger.l_linger = 0;
508 setsockopt(so, SOL_SOCKET, SO_LINGER, (char *)&linger,
509 (socklen_t)sizeof(linger));
510#endif
511// shutdown(so, 2);
512#ifdef WIN32
513 closesocket(so);
514#else
515 close(so);
516#endif
517 so = INVALID_SOCKET;
518}
519
520#ifdef WIN32
521Socket::Error Socket::connectError(void)
522{
523 char* str = "Could not connect to remote host";
524 switch(WSAGetLastError()) {
525 case WSAENETDOWN:
526 return error(errResourceFailure,str,socket_errno);
527 case WSAEINPROGRESS:
528 return error(errConnectBusy,str,socket_errno);
529 case WSAEADDRNOTAVAIL:
530 return error(errConnectInvalid,str,socket_errno);
531 case WSAECONNREFUSED:
532 return error(errConnectRefused,str,socket_errno);
533 case WSAENETUNREACH:
534 return error(errConnectNoRoute,str,socket_errno);
535 default:
536 return error(errConnectFailed,str,socket_errno);
537 }
538}
539#else
540Socket::Error Socket::connectError(void)
541{
542 char* str = (char *)"Could not connect to remote host";
543 switch(errno) {
544#ifdef EHOSTUNREACH
545 case EHOSTUNREACH:
546 return error(errConnectNoRoute,str,socket_errno);
547#endif
548#ifdef ENETUNREACH
549 case ENETUNREACH:
550 return error(errConnectNoRoute,str,socket_errno);
551#endif
552 case EINPROGRESS:
553 return error(errConnectBusy,str,socket_errno);
554#ifdef EADDRNOTAVAIL
555 case EADDRNOTAVAIL:
556 return error(errConnectInvalid,str,socket_errno);
557#endif
558 case ECONNREFUSED:
559 return error(errConnectRefused,str,socket_errno);
560 case ETIMEDOUT:
561 return error(errConnectTimeout,str,socket_errno);
562 default:
563 return error(errConnectFailed,str,socket_errno);
564 }
565}
566#endif
567
568Socket::Error Socket::error(Error err, const char *errs, long systemError) const
569{
570 errid = err;
571 errstr = errs;
572 syserr = systemError;
573 if(!err)
574 return err;
575
576 if(flags.thrown)
577 return err;
578
579 // prevents recursive throws
580
581 flags.thrown = true;
582#ifdef CCXX_EXCEPTIONS
583 switch(Thread::getException()) {
584 case Thread::throwObject:
585 THROW((Socket *)this);
586#ifdef COMMON_STD_EXCEPTION
587 case Thread::throwException:
588 {
589 if(!errs)
590 errs = (char *)"";
591 THROW(SockException(String(errs), err, systemError));
592 }
593#endif
594 case Thread::throwNothing:
595 break;
596 }
597#endif
598 return err;
599}
600
601const char *Socket::getSystemErrorString(void) const
602{
603#ifdef CCXX_EXCEPTIONS
604 SockException e(errstr, errid, syserr);
605 return e.getSystemErrorString();
606#else
607 return NULL;
608#endif
609}
610
611Socket::Error Socket::setBroadcast(bool enable)
612{
613 int opt = (enable ? 1 : 0);
614 if(setsockopt(so, SOL_SOCKET, SO_BROADCAST,
615 (char *)&opt, (socklen_t)sizeof(opt)))
616 return error(errBroadcastDenied,(char *)"Could not set socket broadcast option",socket_errno);
617 flags.broadcast = enable;
618 return errSuccess;
619}
620
621Socket::Error Socket::setKeepAlive(bool enable)
622{
623 int opt = (enable ? ~0: 0);
624#if (defined(SO_KEEPALIVE) || defined(WIN32))
625 if(setsockopt(so, SOL_SOCKET, SO_KEEPALIVE,
626 (char *)&opt, (socklen_t)sizeof(opt)))
627 return error(errKeepaliveDenied,(char *)"Could not set socket keep-alive option",socket_errno);
628#endif
629 flags.keepalive = enable;
630 return errSuccess;
631}
632
633Socket::Error Socket::setLinger(bool linger)
634{
635#ifdef SO_LINGER
636 flags.linger = linger;
637 return errSuccess;
638#else
639 return error(errServiceUnavailable,(char *)"Socket lingering not supported");
640#endif
641}
642
643Socket::Error Socket::setRouting(bool enable)
644{
645 int opt = (enable ? 1 : 0);
646
647#ifdef SO_DONTROUTE
648 if(setsockopt(so, SOL_SOCKET, SO_DONTROUTE,
649 (char *)&opt, (socklen_t)sizeof(opt)))
650 return error(errRoutingDenied,(char *)"Could not set dont-route socket option",socket_errno);
651#endif
652 flags.route = enable;
653 return errSuccess;
654}
655
656Socket::Error Socket::setNoDelay(bool enable)
657{
658 int opt = (enable ? 1 : 0);
659
660 if(setsockopt(so, IPPROTO_TCP, TCP_NODELAY,
661 (char *)&opt, (socklen_t)sizeof(opt)))
662 return error(errNoDelay,(char *)"Could not set tcp-nodelay socket option",socket_errno);
663
664
665 return errSuccess;
666}
667
668Socket::Error Socket::setTypeOfService(Tos service)
669{
670#ifdef SOL_IP
671 unsigned char tos;
672 switch(service) {
673#ifdef IPTOS_LOWDELAY
674 case tosLowDelay:
675 tos = IPTOS_LOWDELAY;
676 break;
677#endif
678#ifdef IPTOS_THROUGHPUT
679 case tosThroughput:
680 tos = IPTOS_THROUGHPUT;
681 break;
682#endif
683#ifdef IPTOS_RELIABILITY
684 case tosReliability:
685 tos = IPTOS_RELIABILITY;
686 break;
687#endif
688#ifdef IPTOS_MINCOST
689 case tosMinCost:
690 tos = IPTOS_MINCOST;
691 break;
692#endif
693 default:
694 return error(errServiceUnavailable,(char *)"Unknown type-of-service");
695 }
696 if(setsockopt(so, SOL_IP, IP_TOS,(char *)&tos, (socklen_t)sizeof(tos)))
697 return error(errServiceDenied,(char *)"Could not set type-of-service",socket_errno);
698 return errSuccess;
699#else
700 return error(errServiceUnavailable,(char *)"Socket type-of-service not supported",socket_errno);
701#endif
702}
703
704Socket::Error Socket::setTimeToLiveByFamily(unsigned char ttl, Family fam)
705{
706 if(!flags.multicast)
707 return error(errMulticastDisabled,(char *)"Multicast not enabled on socket");
708
709 switch(fam) {
710#ifdef CCXX_IPV6
711 case IPV6:
712 flags.ttl = ttl;
713 setsockopt(so, IPPROTO_IPV6, IPV6_MULTICAST_HOPS, (char *)&ttl, sizeof(ttl));
714 return errSuccess;
715#endif
716 case IPV4:
717#ifdef IP_MULTICAST_TTL
718 flags.ttl = ttl;
719 setsockopt(so, IPPROTO_IP, IP_MULTICAST_TTL, (char *)&ttl, sizeof(ttl));
720 return errSuccess;
721#endif
722 default:
723 return error(errServiceUnavailable, (char *)"Multicast not supported");
724 }
725}
726
727Socket::Error Socket::setLoopbackByFamily(bool enable, Family family)
728{
729 unsigned char loop;
730
731 if(!flags.multicast)
732 return error(errMulticastDisabled,(char *)"Multicast not enabled on socket");
733
734 if(enable)
735 loop = 1;
736 else
737 loop = 0;
738 flags.loopback = enable;
739
740 switch(family) {
741#ifdef CCXX_IPV6
742 case IPV6:
743 setsockopt(so, IPPROTO_IPV6, IPV6_MULTICAST_LOOP, (char *)&loop, sizeof(loop));
744 return errSuccess;
745#endif
746 case IPV4:
747#ifdef IP_MULTICAST_LOOP
748 setsockopt(so, IPPROTO_IP, IP_MULTICAST_LOOP, (char *)&loop, sizeof(loop));
749 return errSuccess;
750#endif
751 default:
752 return error(errServiceUnavailable,(char *)"Multicast not supported");
753 }
754}
755
756bool Socket::isPending(Pending pending, timeout_t timeout)
757{
758 int status;
759#ifdef USE_POLL
760 struct pollfd pfd;
761
762 pfd.fd = so;
763 pfd.revents = 0;
764
765 if(so == INVALID_SOCKET)
766 return true;
767
768 switch(pending) {
769 case pendingInput:
770 pfd.events = POLLIN;
771 break;
772 case pendingOutput:
773 pfd.events = POLLOUT;
774 break;
775 case pendingError:
776 pfd.events = POLLERR | POLLHUP;
777 break;
778 }
779
780 status = 0;
781 while(status < 1) {
782
783 if(timeout == TIMEOUT_INF)
784 status = poll(&pfd, 1, -1);
785 else
786 status = poll(&pfd, 1, timeout);
787
788 if(status < 1) {
789 // don't stop polling because of a simple
790 // signal :)
791 if(status == -1 && errno == EINTR)
792 continue;
793
794 return false;
795 }
796 }
797
798 if(pfd.revents & pfd.events)
799 return true;
800 return false;
801#else
802 struct timeval tv;
803 struct timeval *tvp = &tv;
804 fd_set grp;
805
806 if(timeout == TIMEOUT_INF)
807 tvp = NULL;
808 else {
809 tv.tv_usec = (timeout % 1000) * 1000;
810 tv.tv_sec = timeout / 1000;
811 }
812
813 FD_ZERO(&grp);
814 SOCKET sosave = so;
815 if(so == INVALID_SOCKET)
816 return true;
817 FD_SET(sosave, &grp);
818#ifdef WIN32
819 Thread::Cancel cancel = Thread::enterCancel();
820#endif
821 switch(pending) {
822 case pendingInput:
823 status = select((int)so + 1, &grp, NULL, NULL, tvp);
824 break;
825 case pendingOutput:
826 status = select((int)so + 1, NULL, &grp, NULL, tvp);
827 break;
828 case pendingError:
829 status = select((int)so + 1, NULL, NULL, &grp, tvp);
830 break;
831 }
832#ifdef WIN32
833 Thread::exitCancel(cancel);
834#endif
835 if(status < 1)
836 return false;
837 if(FD_ISSET(so, &grp))
838 return true;
839 return false;
840#endif
841}
842
843Socket &Socket::operator=(const Socket &from)
844{
845 if(so == from.so)
846 return *this;
847
848 if(state != INITIAL)
849 endSocket();
850
851 so = DUP_SOCK(from.so,from.state);
852 if(so == INVALID_SOCKET) {
853 error(errCopyFailed,(char *)"Could not duplicate socket handle",socket_errno);
854 state = INITIAL;
855 }
856 else
857 state = from.state;
858
859 return *this;
860}
861
862void Socket::setCompletion(bool immediate)
863{
864 flags.completion = immediate;
865#ifdef WIN32
866 unsigned long flag;
867 // note that this will not work on some versions of Windows for Workgroups. Tough. -- jfc
868 switch( immediate ) {
869 case false:
870 // this will not work if you are using WSAAsyncSelect or WSAEventSelect.
871 // -- perhaps I should throw an exception
872 flag = 1;
873// ioctlsocket( so, FIONBIO, (unsigned long *) 1);
874 break;
875 case true:
876 flag = 0;
877// ioctlsocket( so, FIONBIO, (unsigned long *) 0);
878 break;
879 }
880 ioctlsocket(so, FIONBIO, &flag);
881#else
882 int fflags = fcntl(so, F_GETFL);
883
884 switch( immediate ) {
885 case false:
886 fflags |= O_NONBLOCK;
887 fcntl(so, F_SETFL, fflags);
888 break;
889 case true:
890 fflags &=~ O_NONBLOCK;
891 fcntl(so, F_SETFL, fflags);
892 break;
893 }
894#endif
895}
896
897IPV4Host Socket::getIPV4Sender(tpport_t *port) const
898{
899 struct sockaddr_in from;
900 char buf;
901 socklen_t len = sizeof(from);
902 int rc = ::recvfrom(so, &buf, 1, MSG_PEEK,
903 (struct sockaddr *)&from, &len);
904
905#ifdef WIN32
906 if(rc < 1 && WSAGetLastError() != WSAEMSGSIZE) {
907 if(port)
908 *port = 0;
909
910 memset((void*) &from, 0, sizeof(from));
911 error(errInput,(char *)"Could not read from socket",socket_errno);
912 }
913#else
914 if(rc < 0) {
915 if(port)
916 *port = 0;
917
918 memset((void*) &from, 0, sizeof(from));
919 error(errInput,(char *)"Could not read from socket",socket_errno);
920 }
921#endif
922 else {
923 if(rc < 1)
924 memset((void*) &from, 0, sizeof(from));
925
926 if(port)
927 *port = ntohs(from.sin_port);
928 }
929
930 return IPV4Host(from.sin_addr);
931}
932
933#ifdef CCXX_IPV6
934IPV6Host Socket::getIPV6Sender(tpport_t *port) const
935{
936 struct sockaddr_in6 from;
937 char buf;
938 socklen_t len = sizeof(from);
939 int rc = ::recvfrom(so, &buf, 1, MSG_PEEK,
940 (struct sockaddr *)&from, &len);
941
942#ifdef WIN32
943 if(rc < 1 && WSAGetLastError() != WSAEMSGSIZE) {
944 if(port)
945 *port = 0;
946
947 memset((void*) &from, 0, sizeof(from));
948 error(errInput,(char *)"Could not read from socket",socket_errno);
949 }
950#else
951 if(rc < 0) {
952 if(port)
953 *port = 0;
954
955 memset((void*) &from, 0, sizeof(from));
956 error(errInput,(char *)"Could not read from socket",socket_errno);
957 }
958#endif
959 else {
960 if(rc < 1)
961 memset((void*) &from, 0, sizeof(from));
962
963 if(port)
964 *port = ntohs(from.sin6_port);
965 }
966
967 return IPV6Host(from.sin6_addr);
968}
969#endif
970
971IPV4Host Socket::getIPV4Local(tpport_t *port) const
972{
973 struct sockaddr_in addr;
974 socklen_t len = sizeof(addr);
975
976 if(getsockname(so, (struct sockaddr *)&addr, &len)) {
977 error(errResourceFailure,(char *)"Could not get socket address",socket_errno);
978 if(port)
979 *port = 0;
980 memset(&addr.sin_addr, 0, sizeof(addr.sin_addr));
981 }
982 else {
983 if(port)
984 *port = ntohs(addr.sin_port);
985 }
986 return IPV4Host(addr.sin_addr);
987}
988
989#ifdef CCXX_IPV6
990IPV6Host Socket::getIPV6Local(tpport_t *port) const
991{
992 struct sockaddr_in6 addr;
993 socklen_t len = sizeof(addr);
994
995 if(getsockname(so, (struct sockaddr *)&addr, &len)) {
996 error(errResourceFailure,(char *)"Could not get socket address",socket_errno);
997 if(port)
998 *port = 0;
999 memset(&addr.sin6_addr, 0, sizeof(addr.sin6_addr));
1000 }
1001 else {
1002 if(port)
1003 *port = ntohs(addr.sin6_port);
1004 }
1005 return IPV6Host(addr.sin6_addr);
1006}
1007
1008#endif
1009
1010IPV4Host Socket::getIPV4NAT(tpport_t *port) const
1011{
1012 struct sockaddr_in addr;
1013 natResult res;
1014
1015 if((res=natv4Lookup((int)so, &addr))!=natOK) {
1016 if(res==natNotSupported)
1017 error( errServiceUnavailable, natErrorString( res ) );
1018 else if(res==natSearchErr)
1019 error( errSearchErr, natErrorString( res ) );
1020 else
1021 error( errLookupFail, natErrorString( res ), socket_errno );
1022 if(port)
1023 *port = 0;
1024 memset(&addr.sin_addr, 0, sizeof(addr.sin_addr));
1025 }
1026 else {
1027 if(port)
1028 *port = ntohs(addr.sin_port);
1029 }
1030 return IPV4Host(addr.sin_addr);
1031}
1032
1033#ifdef CCXX_IPV6
1034IPV6Host Socket::getIPV6NAT(tpport_t *port) const
1035{
1036 struct sockaddr_in6 addr;
1037 natResult res;
1038
1039 if((res=natv6Lookup(so, &addr))!=natOK) {
1040 if(res==natNotSupported)
1041 error( errServiceUnavailable, natErrorString( res ) );
1042 else if(res==natSearchErr)
1043 error( errSearchErr, natErrorString( res ) );
1044 else
1045 error( errLookupFail, natErrorString( res ), socket_errno );
1046 if(port)
1047 *port = 0;
1048 memset(&addr.sin6_addr, 0, sizeof(addr.sin6_addr));
1049 }
1050 else {
1051 if(port)
1052 *port = ntohs(addr.sin6_port);
1053 }
1054 return IPV6Host(addr.sin6_addr);
1055}
1056#endif
1057
1058IPV4Host Socket::getIPV4Peer(tpport_t *port) const
1059{
1060 struct sockaddr_in addr;
1061 socklen_t len = sizeof(addr);
1062
1063 if(getpeername(so, (struct sockaddr *)&addr, &len)) {
1064#ifndef WIN32
1065 if(errno == ENOTCONN)
1066 error(errNotConnected,(char *)"Could not get peer address",socket_errno);
1067 else
1068#endif
1069 error(errResourceFailure,(char *)"Could not get peer address",socket_errno);
1070 if(port)
1071 *port = 0;
1072 memset(&addr.sin_addr, 0, sizeof(addr.sin_addr));
1073 }
1074 else {
1075 if(port)
1076 *port = ntohs(addr.sin_port);
1077 }
1078 return IPV4Host(addr.sin_addr);
1079}
1080
1081#ifdef CCXX_IPV6
1082IPV6Host Socket::getIPV6Peer(tpport_t *port) const
1083{
1084 struct sockaddr_in6 addr;
1085 socklen_t len = sizeof(addr);
1086
1087 if(getpeername(so, (struct sockaddr *)&addr, &len)) {
1088#ifndef WIN32
1089 if(errno == ENOTCONN)
1090 error(errNotConnected,(char *)"Could not get peer address",socket_errno);
1091 else
1092#endif
1093 error(errResourceFailure,(char *)"Could not get peer address",socket_errno);
1094 if(port)
1095 *port = 0;
1096 memset(&addr.sin6_addr, 0, sizeof(addr.sin6_addr));
1097 }
1098 else {
1099 if(port)
1100 *port = ntohs(addr.sin6_port);
1101 }
1102 return IPV6Host(addr.sin6_addr);
1103}
1104#endif
1105
1106Socket::Error Socket::setMulticastByFamily(bool enable, Family family)
1107{
1108 socklen_t len;
1109
1110 switch(family) {
1111#ifdef CCXX_IPV6
1112 case IPV6:
1113 struct sockaddr_in6 addr;
1114 len = sizeof(addr);
1115
1116 if(enable == flags.multicast)
1117 return errSuccess;
1118
1119 flags.multicast = enable;
1120 if(enable)
1121 getsockname(so, (struct sockaddr *)&addr, &len);
1122 else
1123 memset(&addr.sin6_addr, 0, sizeof(addr.sin6_addr));
1124
1125 setsockopt(so, IPPROTO_IPV6, IPV6_MULTICAST_IF, (char *)&addr.sin6_addr, sizeof(addr.sin6_addr));
1126 return errSuccess;
1127#endif
1128 case IPV4:
1129#ifdef IP_MULTICAST_IF
1130 struct sockaddr_in addr4;
1131 len = sizeof(addr4);
1132
1133 if(enable == flags.multicast)
1134 return errSuccess;
1135
1136 flags.multicast = enable;
1137 if(enable)
1138 getsockname(so, (struct sockaddr *)&addr4, &len);
1139 else
1140 memset(&addr4.sin_addr, 0, sizeof(addr4.sin_addr));
1141
1142 setsockopt(so, IPPROTO_IP, IP_MULTICAST_IF, (char *)&addr4.sin_addr, sizeof(addr4.sin_addr));
1143 return errSuccess;
1144#endif
1145 default:
1146 return error(errServiceUnavailable,(char *)"Multicast not supported");
1147 }
1148}
1149
1150Socket::Error Socket::join(const IPV4Multicast &ia)
1151{
1152#ifdef IP_ADD_MEMBERSHIP
1153 struct ip_mreq group;
1154 struct sockaddr_in myaddr;
1155 socklen_t len = sizeof(myaddr);
1156
1157 if(!flags.multicast)
1158 return error(errMulticastDisabled,(char *)"Multicast not enabled on socket");
1159
1160 getsockname(so, (struct sockaddr *)&myaddr, &len);
1161 group.imr_interface.s_addr = INADDR_ANY;
1162 group.imr_multiaddr = getaddress(ia);
1163 setsockopt(so, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group));
1164 return errSuccess;
1165#else
1166 return error(errServiceUnavailable,(char *)"Multicast not supported");
1167#endif
1168}
1169
1170#ifdef CCXX_IPV6
1171Socket::Error Socket::join(const IPV6Multicast &ia)
1172{
1173#ifdef IPV6_ADD_MEMBERSHIP
1174 struct ipv6_mreq group;
1175 struct sockaddr_in6 myaddr;
1176 socklen_t len = sizeof(myaddr);
1177
1178 if(!flags.multicast)
1179 return error(errMulticastDisabled,(char *)"Multicast not enabled on socket");
1180
1181 getsockname(so, (struct sockaddr *)&myaddr, &len);
1182 group.ipv6mr_interface = 0;
1183 group.ipv6mr_multiaddr = getaddress(ia);
1184 setsockopt(so, IPPROTO_IPV6, IPV6_ADD_MEMBERSHIP, (char *)&group, sizeof(group));
1185 return errSuccess;
1186#else
1187 return error(errServiceUnavailable,(char *)"Multicast not supported");
1188#endif
1189}
1190
1191#endif
1192
1193Socket::Error Socket::drop(const IPV4Multicast &ia)
1194{
1195#ifdef IP_DROP_MEMBERSHIP
1196 struct ip_mreq group;
1197 struct sockaddr_in myaddr;
1198 socklen_t len = sizeof(myaddr);
1199
1200 if(!flags.multicast)
1201 return error(errMulticastDisabled,(char *)"Multicast not enabled on socket");
1202
1203 getsockname(so, (struct sockaddr *)&myaddr, &len);
1204 group.imr_interface.s_addr = INADDR_ANY;
1205 group.imr_multiaddr = getaddress(ia);
1206 setsockopt(so, IPPROTO_IP, IP_DROP_MEMBERSHIP, (char *)&group, sizeof(group));
1207 return errSuccess;
1208#else
1209 return error(errServiceUnavailable,(char *)"Multicast not supported");
1210#endif
1211}
1212
1213#ifdef CCXX_IPV6
1214Socket::Error Socket::drop(const IPV6Multicast &ia)
1215{
1216#ifdef IPV6_DROP_MEMBERSHIP
1217 struct ipv6_mreq group;
1218 struct sockaddr_in6 myaddr;
1219 socklen_t len = sizeof(myaddr);
1220
1221 if(!flags.multicast)
1222 return error(errMulticastDisabled,(char *)"Multicast not enabled on socket");
1223
1224 getsockname(so, (struct sockaddr *)&myaddr, &len);
1225 group.ipv6mr_interface = 0;
1226 group.ipv6mr_multiaddr = getaddress(ia);
1227 setsockopt(so, IPPROTO_IPV6, IPV6_DROP_MEMBERSHIP, (char *)&group, sizeof(group));
1228 return errSuccess;
1229#else
1230 return error(errServiceUnavailable,(char *)"Multicast not supported");
1231#endif
1232}
1233#endif
1234
1235#ifdef HAVE_GETADDRINFO
1236
1237UDPSocket::UDPSocket(const char *name, Family fam) :
1238Socket(fam, SOCK_DGRAM, IPPROTO_UDP)
1239{
1240 char namebuf[128], *cp;
1241 struct addrinfo hint, *list = NULL, *first;
1242
1243 family = fam;
1244
1245 switch(fam) {
1246#ifdef CCXX_IPV6
1247 case IPV6:
1248 peer.ipv6.sin6_family = family;
1249 break;
1250#endif
1251 case IPV4:
1252 peer.ipv4.sin_family = family;
1253 }
1254
1255 snprintf(namebuf, sizeof(namebuf), "%s", name);
1256 cp = strrchr(namebuf, '/');
1257 if(!cp && family == IPV4)
1258 cp = strrchr(namebuf, ':');
1259
1260 if(!cp) {
1261 cp = namebuf;
1262 name = NULL;
1263 }
1264 else {
1265 name = namebuf;
1266 *(cp++) = 0;
1267 if(!strcmp(name, "*"))
1268 name = NULL;
1269 }
1270
1271 memset(&hint, 0, sizeof(hint));
1272
1273 hint.ai_family = family;
1274 hint.ai_socktype = SOCK_DGRAM;
1275 hint.ai_protocol = IPPROTO_UDP;
1276 hint.ai_flags = AI_PASSIVE;
1277
1278 if(getaddrinfo(name, cp, &hint, &list) || !list) {
1279 error(errBindingFailed, (char *)"Could not find service", errno);
1280 endSocket();
1281 return;
1282 }
1283
1284#if defined(SO_REUSEADDR)
1285 int opt = 1;
1286 setsockopt(so, SOL_SOCKET, SO_REUSEADDR, (char *)&opt,
1287 (socklen_t)sizeof(opt));
1288#endif
1289
1290 first = list;
1291
1292 while(list) {
1293 if(!bind(so, list->ai_addr, (socklen_t)list->ai_addrlen)) {
1294 state = BOUND;
1295 break;
1296 }
1297 list = list->ai_next;
1298 }
1299 freeaddrinfo(first);
1300
1301 if(state != BOUND) {
1302 endSocket();
1303 error(errBindingFailed, (char *)"Count not bind socket", errno);
1304 return;
1305 }
1306}
1307
1308#else
1309
1310UDPSocket::UDPSocket(const char *name, Family fam) :
1311Socket(fam, SOCK_DGRAM, IPPROTO_UDP)
1312{
1313 char namebuf[128], *cp;
1314 tpport_t port;
1315 struct servent *svc;
1316 socklen_t alen;
1317 struct sockaddr *addr;
1318
1319 family = fam;
1320
1321 snprintf(namebuf, sizeof(namebuf), "%s", name);
1322 cp = strrchr(namebuf, '/');
1323 if(!cp && family == IPV4)
1324 cp = strrchr(namebuf, ':');
1325
1326 if(!cp) {
1327 cp = namebuf;
1328 name = "*";
1329 }
1330 else {
1331 name = namebuf;
1332 *(cp++) = 0;
1333 }
1334
1335 if(isdigit(*cp))
1336 port = atoi(cp);
1337 else {
1338 mutex.enter();
1339 svc = getservbyname(cp, "udp");
1340 if(svc)
1341 port = ntohs(svc->s_port);
1342 mutex.leave();
1343 if(!svc) {
1344 error(errBindingFailed, (char *)"Could not find service", errno);
1345 endSocket();
1346 return;
1347 }
1348 }
1349
1350 struct sockaddr_in addr4;
1351 IPV4Address ia4(name);
1352#ifdef CCXX_IPV6
1353 struct sockaddr_in6 addr6;
1354 IPV6Address ia6(name);
1355#endif
1356
1357 switch(family) {
1358#ifdef CCXX_IPV6
1359 case IPV6:
1360 peer.ipv6.sin6_family = family;
1361 memset(&addr6, 0, sizeof(addr6));
1362 addr6.sin6_family = family;
1363 addr6.sin6_addr = getaddress(ia6);
1364 addr6.sin6_port = htons(port);
1365 alen = sizeof(addr6);
1366 addr = (struct sockaddr *)&addr6;
1367 break;
1368#endif
1369 case IPV4:
1370 peer.ipv4.sin_family = family;
1371 memset(&addr4, 0, sizeof(addr4));
1372 addr4.sin_family = family;
1373 addr4.sin_addr = getaddress(ia4);
1374 addr4.sin_port = htons(port);
1375 alen = sizeof(&addr4);
1376 addr = (struct sockaddr *)&addr4;
1377 }
1378
1379#if defined(SO_REUSEADDR)
1380 int opt = 1;
1381 setsockopt(so, SOL_SOCKET, SO_REUSEADDR, (char *)&opt,
1382 (socklen_t)sizeof(opt));
1383#endif
1384
1385 if(!bind(so, addr, alen))
1386 state = BOUND;
1387
1388 if(state != BOUND) {
1389 endSocket();
1390 error(errBindingFailed, (char *)"Count not bind socket", errno);
1391 return;
1392 }
1393}
1394
1395#endif
1396
1397UDPSocket::UDPSocket(Family fam) :
1398Socket(fam, SOCK_DGRAM, IPPROTO_UDP)
1399{
1400 family = fam;
1401 memset(&peer, 0, sizeof(peer));
1402 switch(fam) {
1403#ifdef CCXX_IPV6
1404 case IPV6:
1405 peer.ipv6.sin6_family = family;
1406 break;
1407#endif
1408 case IPV4:
1409 peer.ipv4.sin_family = family;
1410 }
1411}
1412
1413UDPSocket::UDPSocket(const IPV4Address &ia, tpport_t port) :
1414Socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)
1415{
1416 family = IPV4;
1417 memset(&peer.ipv4, 0, sizeof(peer));
1418 peer.ipv4.sin_family = AF_INET;
1419 peer.ipv4.sin_addr = getaddress(ia);
1420 peer.ipv4.sin_port = htons(port);
1421#if defined(SO_REUSEADDR)
1422 int opt = 1;
1423 setsockopt(so, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, (socklen_t)sizeof(opt));
1424#endif
1425 if(bind(so, (struct sockaddr *)&peer.ipv4, sizeof(peer.ipv4))) {
1426 endSocket();
1427 error(errBindingFailed,(char *)"Could not bind socket",socket_errno);
1428 return;
1429 }
1430 state = BOUND;
1431}
1432
1433#ifdef CCXX_IPV6
1434UDPSocket::UDPSocket(const IPV6Address &ia, tpport_t port) :
1435Socket(AF_INET6, SOCK_DGRAM, IPPROTO_UDP)
1436{
1437 family = IPV6;
1438 memset(&peer.ipv6, 0, sizeof(peer));
1439 peer.ipv6.sin6_family = AF_INET6;
1440 peer.ipv6.sin6_addr = getaddress(ia);
1441 peer.ipv6.sin6_port = htons(port);
1442#if defined(SO_REUSEADDR)
1443 int opt = 1;
1444 setsockopt(so, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, (socklen_t)sizeof(opt));
1445#endif
1446 if(bind(so, (struct sockaddr *)&peer.ipv6, sizeof(peer.ipv6))) {
1447 endSocket();
1448 error(errBindingFailed,(char *)"Could not bind socket",socket_errno);
1449 return;
1450 }
1451 state = BOUND;
1452}
1453#endif
1454
1455UDPSocket::~UDPSocket()
1456{
1457 endSocket();
1458}
1459
1460ssize_t UDPSocket::send(const void *buf, size_t len)
1461{
1462 struct sockaddr *addr = NULL;
1463 socklen_t alen = 0;
1464
1465 switch(family) {
1466#ifdef CCXX_IPV6
1467 case IPV6:
1468 addr = (struct sockaddr *)&peer.ipv6;
1469 alen = sizeof(struct sockaddr_in6);
1470 break;
1471#endif
1472 case IPV4:
1473 addr = (struct sockaddr *)&peer.ipv4;
1474 alen = sizeof(struct sockaddr_in);
1475 break;
1476 default:
1477 return -1;
1478 }
1479
1480 if(isConnected()) {
1481 addr = NULL;
1482 alen = 0;
1483 }
1484
1485 return _IORET64 ::sendto(so, (const char *)buf, _IOLEN64 len, MSG_NOSIGNAL, addr, alen);
1486}
1487
1488ssize_t UDPSocket::receive(void *buf, size_t len, bool reply)
1489{
1490 struct sockaddr *addr = NULL;
1491 struct sockaddr_in senderAddress; // DMC 2/7/05 ADD for use below.
1492 socklen_t alen = 0;
1493
1494 switch(family) {
1495#ifdef CCXX_IPV6
1496 case IPV6:
1497 addr = (struct sockaddr *)&peer.ipv6;
1498 alen = sizeof(struct sockaddr_in6);
1499 break;
1500#endif
1501 case IPV4:
1502 addr = (struct sockaddr *)&peer.ipv4;
1503 alen = sizeof(struct sockaddr_in);
1504 break;
1505 default:
1506 return -1;
1507 }
1508
1509 if(isConnected() || !reply) {
1510 // DMC 2/7/05 MOD to use senderAddress instead of NULL, to prevent 10014 error
1511 // from recvfrom.
1512 //addr = NULL;
1513 //alen = 0;
1514 addr = (struct sockaddr*)(&senderAddress);
1515 alen = sizeof(struct sockaddr_in);
1516 }
1517
1518 int bytes = ::recvfrom(so, (char *)buf, _IOLEN64 len, 0, addr, &alen);
1519
1520#ifdef WIN32
1521 int code = 0;
1522
1523 if (bytes == SOCKET_ERROR) {
1524 code = WSAGetLastError();
1525 }
1526#endif
1527
1528 return _IORET64 bytes;
1529}
1530
1531Socket::Error UDPSocket::join(const IPV4Multicast &ia,int InterfaceIndex)
1532{
1533
1534#if defined(WIN32) && defined(IP_ADD_MEMBERSHIP)
1535
1536 // DMC 2/7/05: Added WIN32 block. Win32 does not define the ip_mreqn structure,
1537 // so we must use ip_mreq with INADDR_ANY.
1538 struct ip_mreq group;
1539 struct sockaddr_in myaddr;
1540 socklen_t len = sizeof(myaddr);
1541
1542 if(!flags.multicast)
1543 return error(errMulticastDisabled);
1544
1545 memset(&group, 0, sizeof(group));
1546 getsockname(so, (struct sockaddr *)&myaddr, &len);
1547 group.imr_multiaddr.s_addr = ia.getAddress().s_addr;
1548 group.imr_interface.s_addr = INADDR_ANY;
1549 int retval = setsockopt(so, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group));
1550 return errSuccess;
1551
1552#elif defined(IP_ADD_MEMBERSHIP) && defined(SIOCGIFINDEX) && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) && !defined(_OSF_SOURCE) && !defined(__hpux) && !defined(__GNU__)
1553
1554 struct ip_mreqn group;
1555 struct sockaddr_in myaddr;
1556 socklen_t len = sizeof(myaddr);
1557
1558 if(!flags.multicast)
1559 return error(errMulticastDisabled);
1560
1561 getsockname(so, (struct sockaddr *)&myaddr, &len);
1562 memset(&group, 0, sizeof(group));
1563 memcpy(&group.imr_address, &myaddr.sin_addr, sizeof(&myaddr.sin_addr));
1564 group.imr_multiaddr = getaddress(ia);
1565 group.imr_ifindex = InterfaceIndex;
1566 setsockopt(so, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group));
1567 return errSuccess;
1568#elif defined(IP_ADD_MEMBERSHIP)
1569 // if no by index, use INADDR_ANY
1570 struct ip_mreq group;
1571 struct sockaddr_in myaddr;
1572 socklen_t len = sizeof(myaddr);
1573
1574 if(!flags.multicast)
1575 return error(errMulticastDisabled);
1576
1577 getsockname(so, (struct sockaddr *)&myaddr, &len);
1578 memset(&group, sizeof(group), 0);
1579 group.imr_multiaddr.s_addr = ia.getAddress().s_addr;
1580 group.imr_interface.s_addr = INADDR_ANY;
1581 setsockopt(so, IPPROTO_IP, IP_ADD_MEMBERSHIP, (char *)&group, sizeof(group));
1582 return errSuccess;
1583#else
1584 return error(errServiceUnavailable);
1585#endif
1586}
1587
1588
1589Socket::Error UDPSocket::getInterfaceIndex(const char *DeviceName,int& InterfaceIndex)
1590{
1591#ifndef WIN32
1592#if defined(IP_ADD_MEMBERSHIP) && defined(SIOCGIFINDEX) && !defined(__FreeBSD__) && !defined(__FreeBSD_kernel__) && !defined(_OSF_SOURCE) && !defined(__hpux) && !defined(__GNU__)
1593
1594 struct ip_mreqn mreqn;
1595 struct ifreq m_ifreq;
1596 int i;
1597 sockaddr_in* in4 = (sockaddr_in*) &peer.ipv4;
1598 InterfaceIndex = -1;
1599
1600 memset(&mreqn, 0, sizeof(mreqn));
1601 memcpy(&mreqn.imr_multiaddr.s_addr, &in4->sin_addr, sizeof(mreqn.imr_multiaddr.s_addr));
1602
1603 for (i = 0; i < IFNAMSIZ && DeviceName[i]; ++i)
1604 m_ifreq.ifr_name[i] = DeviceName[i];
1605 for (; i < IFNAMSIZ; ++i)
1606 m_ifreq.ifr_name[i] = 0;
1607
1608 if (ioctl (so, SIOCGIFINDEX, &m_ifreq))
1609 return error(errServiceUnavailable);
1610
1611#if defined(__FreeBSD__) || defined(__GNU__)
1612 InterfaceIndex = m_ifreq.ifr_ifru.ifru_index;
1613#else
1614 InterfaceIndex = m_ifreq.ifr_ifindex;
1615#endif
1616 return errSuccess;
1617#else
1618 return error(errServiceUnavailable);
1619#endif
1620#else
1621 return error(errServiceUnavailable);
1622#endif // WIN32
1623}
1624
1625#ifdef AF_UNSPEC
1626Socket::Error UDPSocket::disconnect(void)
1627{
1628 struct sockaddr_in addr;
1629 int len = sizeof(addr);
1630
1631 if(so == INVALID_SOCKET)
1632 return errSuccess;
1633
1634 Socket::state = BOUND;
1635
1636 memset(&addr, 0, len);
1637#ifndef WIN32
1638 addr.sin_family = AF_UNSPEC;
1639#else
1640 addr.sin_family = AF_INET;
1641 memset(&addr.sin_addr, 0, sizeof(addr.sin_addr));
1642#endif
1643 if(::connect(so, (sockaddr *)&addr, len))
1644 return connectError();
1645 return errSuccess;
1646}
1647#else
1648Socket::Error UDPSocket::disconnect(void)
1649{
1650 if(so == INVALID_SOCKET)
1651 return errSuccess;
1652
1653 Socket::state = BOUND;
1654 return connect(getLocal());
1655}
1656#endif
1657
1658void UDPSocket::setPeer(const IPV4Host &ia, tpport_t port)
1659{
1660 memset(&peer.ipv4, 0, sizeof(peer.ipv4));
1661 peer.ipv4.sin_family = AF_INET;
1662 peer.ipv4.sin_addr = getaddress(ia);
1663 peer.ipv4.sin_port = htons(port);
1664}
1665
1666void UDPSocket::connect(const IPV4Host &ia, tpport_t port)
1667{
1668 setPeer(ia, port);
1669 if(so == INVALID_SOCKET)
1670 return;
1671
1672 if(!::connect(so, (struct sockaddr *)&peer.ipv4, sizeof(struct sockaddr_in)))
1673 Socket::state = CONNECTED;
1674}
1675
1676#ifdef CCXX_IPV6
1677void UDPSocket::setPeer(const IPV6Host &ia, tpport_t port)
1678{
1679 memset(&peer.ipv6, 0, sizeof(peer.ipv6));
1680 peer.ipv6.sin6_family = AF_INET6;
1681 peer.ipv6.sin6_addr = getaddress(ia);
1682 peer.ipv6.sin6_port = htons(port);
1683}
1684
1685void UDPSocket::connect(const IPV6Host &ia, tpport_t port)
1686{
1687 setPeer(ia, port);
1688
1689 if(so == INVALID_SOCKET)
1690 return;
1691
1692 if(!::connect(so, (struct sockaddr *)&peer.ipv6, sizeof(struct sockaddr_in6)))
1693 Socket::state = CONNECTED;
1694
1695}
1696
1697#endif
1698
1699#ifdef HAVE_GETADDRINFO
1700
1701void UDPSocket::setPeer(const char *name)
1702{
1703 char namebuf[128], *cp;
1704 struct addrinfo hint, *list;
1705
1706 snprintf(namebuf, sizeof(namebuf), "%s", name);
1707 cp = strrchr(namebuf, '/');
1708 if(!cp)
1709 cp = strrchr(namebuf, ':');
1710
1711 if(!cp)
1712 return;
1713
1714 memset(&hint, 0, sizeof(hint));
1715 hint.ai_family = family;
1716 hint.ai_socktype = SOCK_DGRAM;
1717 hint.ai_protocol = IPPROTO_UDP;
1718
1719 if(getaddrinfo(namebuf, cp, &hint, &list) || !list)
1720 return;
1721
1722 switch(family) {
1723#ifdef CCXX_IPV6
1724 case IPV6:
1725 memcpy(&peer.ipv6, list->ai_addr, sizeof(peer.ipv6));
1726 break;
1727#endif
1728 case IPV4:
1729 memcpy(&peer.ipv4, list->ai_addr, sizeof(peer.ipv4));
1730 break;
1731 }
1732
1733 freeaddrinfo(list);
1734}
1735
1736#else
1737
1738void UDPSocket::setPeer(const char *name)
1739{
1740 char namebuf[128], *cp;
1741 struct servent *svc;
1742 tpport_t port;
1743
1744 snprintf(namebuf, sizeof(namebuf), "%s", name);
1745 cp = strrchr(namebuf, '/');
1746 if(!cp)
1747 cp = strrchr(namebuf, ':');
1748
1749 if(!cp)
1750 return;
1751
1752 if(isdigit(*cp))
1753 port = atoi(cp);
1754 else {
1755 mutex.enter();
1756 svc = getservbyname(cp, "udp");
1757 if(svc)
1758 port = ntohs(svc->s_port);
1759 mutex.leave();
1760 if(!svc)
1761 return;
1762 }
1763
1764 memset(&peer, 0, sizeof(peer));
1765
1766 switch(family) {
1767#ifdef CCXX_IPV6
1768 case IPV6:
1769 setPeer(IPV6Host(namebuf), port);
1770 break;
1771#endif
1772 case IPV4:
1773 setPeer(IPV4Host(namebuf), port);
1774 break;
1775 }
1776}
1777
1778#endif
1779
1780void UDPSocket::connect(const char *service)
1781{
1782 int rtn = -1;
1783
1784 setPeer(service);
1785
1786 if(so == INVALID_SOCKET)
1787 return;
1788
1789 switch(family) {
1790#ifdef CCXX_IPV6
1791 case IPV6:
1792 rtn = ::connect(so, (struct sockaddr *)&peer.ipv6, sizeof(struct sockaddr_in6));
1793 break;
1794#endif
1795 case IPV4:
1796 rtn = ::connect(so, (struct sockaddr *)&peer.ipv4, sizeof(struct sockaddr_in));
1797 break;
1798 }
1799 if(!rtn)
1800 Socket::state = CONNECTED;
1801}
1802
1803IPV4Host UDPSocket::getIPV4Peer(tpport_t *port) const
1804{
1805 // FIXME: insufficient buffer
1806 // how to retrieve peer ??
1807 char buf;
1808 socklen_t len = sizeof(peer.ipv4);
1809 int rtn = ::recvfrom(so, &buf, 1, MSG_PEEK, (struct sockaddr *)&peer.ipv4, &len);
1810
1811#ifdef WIN32
1812 if(rtn < 1 && WSAGetLastError() != WSAEMSGSIZE) {
1813 if(port)
1814 *port = 0;
1815
1816 memset((void*) &peer.ipv4, 0, sizeof(peer.ipv4));
1817 }
1818#else
1819 if(rtn < 1) {
1820 if(port)
1821 *port = 0;
1822
1823 memset((void*) &peer.ipv4, 0, sizeof(peer.ipv4));
1824 }
1825#endif
1826 else {
1827 if(port)
1828 *port = ntohs(peer.ipv4.sin_port);
1829 }
1830 return IPV4Host(peer.ipv4.sin_addr);
1831}
1832
1833#ifdef CCXX_IPV6
1834IPV6Host UDPSocket::getIPV6Peer(tpport_t *port) const
1835{
1836 // FIXME: insufficient buffer
1837 // how to retrieve peer ??
1838 char buf;
1839 socklen_t len = sizeof(peer.ipv6);
1840 int rtn = ::recvfrom(so, &buf, 1, MSG_PEEK, (struct sockaddr *)&peer.ipv6, &len);
1841
1842#ifdef WIN32
1843 if(rtn < 1 && WSAGetLastError() != WSAEMSGSIZE) {
1844 if(port)
1845 *port = 0;
1846
1847 memset((void*) &peer.ipv6, 0, sizeof(peer.ipv6));
1848 }
1849#else
1850 if(rtn < 1) {
1851 if(port)
1852 *port = 0;
1853
1854 memset((void*) &peer.ipv6, 0, sizeof(peer.ipv6));
1855 }
1856#endif
1857 else {
1858 if(port)
1859 *port = ntohs(peer.ipv6.sin6_port);
1860 }
1861 return IPV6Host(peer.ipv6.sin6_addr);
1862}
1863#endif
1864
1865UDPBroadcast::UDPBroadcast(const IPV4Address &ia, tpport_t port) :
1866UDPSocket(ia, port)
1867{
1868 if(so != INVALID_SOCKET)
1869 setBroadcast(true);
1870}
1871
1872void UDPBroadcast::setPeer(const IPV4Broadcast &ia, tpport_t port)
1873{
1874 memset(&peer.ipv4, 0, sizeof(peer.ipv4));
1875 peer.ipv4.sin_family = AF_INET;
1876 peer.ipv4.sin_addr = getaddress(ia);
1877 peer.ipv4.sin_port = htons(port);
1878}
1879
1880void TCPSocket::setSegmentSize(unsigned mss)
1881{
1882#ifdef TCP_MAXSEG
1883 if(mss > 1)
1884 setsockopt(so, IPPROTO_TCP, TCP_MAXSEG, (char *)&mss, sizeof(mss));
1885#endif
1886 segsize = mss;
1887}
1888
1889#ifdef HAVE_GETADDRINFO
1890TCPSocket::TCPSocket(const char *name, unsigned backlog, unsigned mss) :
1891Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
1892{
1893 char namebuf[128], *cp;
1894 struct addrinfo hint, *list = NULL, *first;
1895 snprintf(namebuf, sizeof(namebuf), "%s", name);
1896 cp = strrchr(namebuf, '/');
1897 if(!cp)
1898 cp = strrchr(namebuf, ':');
1899
1900 if(!cp) {
1901 cp = namebuf;
1902 name = NULL;
1903 }
1904 else {
1905 name = namebuf;
1906 *(cp++) = 0;
1907 if(!strcmp(name, "*"))
1908 name = NULL;
1909 }
1910
1911 memset(&hint, 0, sizeof(hint));
1912 hint.ai_family = AF_INET;
1913 hint.ai_socktype = SOCK_STREAM;
1914 hint.ai_protocol = IPPROTO_TCP;
1915 hint.ai_flags = AI_PASSIVE;
1916
1917 if(getaddrinfo(name, cp, &hint, &list) || !list) {
1918 endSocket();
1919 error(errBindingFailed, (char *)"Could not find service", errno);
1920 return;
1921 }
1922
1923#if defined(SO_REUSEADDR)
1924 int opt = 1;
1925 setsockopt(so, SOL_SOCKET, SO_REUSEADDR, (char *)&opt,
1926 (socklen_t)sizeof(opt));
1927#endif
1928
1929 first = list;
1930 while(list) {
1931 if(!bind(so, list->ai_addr, (socklen_t)list->ai_addrlen)) {
1932 state = BOUND;
1933 break;
1934 }
1935 list = list->ai_next;
1936 }
1937 freeaddrinfo(first);
1938 if(state != BOUND) {
1939 endSocket();
1940 error(errBindingFailed,(char *)"Could not bind socket",socket_errno);
1941 return;
1942 }
1943
1944 setSegmentSize(mss);
1945 if(listen(so, backlog)) {
1946 endSocket();
1947 error(errBindingFailed,(char *)"Could not listen on socket",socket_errno);
1948 return;
1949 }
1950}
1951
1952#else
1953TCPSocket::TCPSocket(const char *name, unsigned backlog, unsigned mss) :
1954Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
1955{
1956 char namebuf[128], *cp;
1957 struct sockaddr_in addr;
1958 struct servent *svc;
1959
1960 memset(&addr, 0, sizeof(addr));
1961 snprintf(namebuf, sizeof(namebuf), "%s", name);
1962 cp = strrchr(namebuf, '/');
1963 if(!cp)
1964 cp = strrchr(namebuf, ':');
1965
1966 if(!cp) {
1967 cp = namebuf;
1968 name = "*";
1969 }
1970 else {
1971 name = namebuf;
1972 *(cp++) = 0;
1973 }
1974
1975 addr.sin_family = AF_INET;
1976 if(isdigit(*cp))
1977 addr.sin_port = htons(atoi(cp));
1978 else {
1979 mutex.enter();
1980 svc = getservbyname(cp, "tcp");
1981 if(svc)
1982 addr.sin_port = svc->s_port;
1983 mutex.leave();
1984 if(!svc) {
1985 endSocket();
1986 error(errBindingFailed, "Could not find service", errno);
1987 return;
1988
1989 }
1990 }
1991
1992 IPV4Address ia(name);
1993 addr.sin_addr = getaddress(ia);
1994
1995#if defined(SO_REUSEADDR)
1996 int opt = 1;
1997 setsockopt(so, SOL_SOCKET, SO_REUSEADDR, (char *)&opt,
1998 (socklen_t)sizeof(opt));
1999#endif
2000
2001 if(bind(so, (struct sockaddr *)&addr, sizeof(addr))) {
2002 endSocket();
2003 error(errBindingFailed,(char *)"Could not bind socket",socket_errno);
2004 return;
2005 }
2006
2007 setSegmentSize(mss);
2008 if(listen(so, backlog)) {
2009 endSocket();
2010 error(errBindingFailed,(char *)"Could not listen on socket",
2011 socket_errno);
2012 return;
2013 }
2014 state = BOUND;
2015}
2016
2017#endif
2018
2019TCPSocket::TCPSocket(const IPV4Address &ia, tpport_t port, unsigned backlog, unsigned mss) :
2020Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
2021{
2022 struct sockaddr_in addr;
2023
2024 memset(&addr, 0, sizeof(addr));
2025 addr.sin_family = AF_INET;
2026 addr.sin_addr = getaddress(ia);
2027 addr.sin_port = htons(port);
2028
2029#if defined(SO_REUSEADDR)
2030 int opt = 1;
2031 setsockopt(so, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, (socklen_t)sizeof(opt));
2032#endif
2033 if(bind(so, (struct sockaddr *)&addr, sizeof(addr))) {
2034 endSocket();
2035 error(errBindingFailed,(char *)"Could not bind socket",socket_errno);
2036 return;
2037 }
2038
2039 setSegmentSize(mss);
2040
2041 if(listen(so, backlog)) {
2042 endSocket();
2043 error(errBindingFailed,(char *)"Could not listen on socket",socket_errno);
2044 return;
2045 }
2046 state = BOUND;
2047}
2048
2049bool TCPSocket::onAccept(const IPV4Host &ia, tpport_t port)
2050{
2051 return true;
2052}
2053
2054TCPSocket::~TCPSocket()
2055{
2056 endSocket();
2057}
2058
2059#ifdef CCXX_IPV6
2060
2061void TCPV6Socket::setSegmentSize(unsigned mss)
2062{
2063#ifdef TCP_MAXSEG
2064 if(mss > 1)
2065 setsockopt(so, IPPROTO_TCP, TCP_MAXSEG, (char *)&mss, sizeof(mss));
2066#endif
2067 segsize = mss;
2068}
2069
2070
2071#ifdef HAVE_GETADDRINFO
2072TCPV6Socket::TCPV6Socket(const char *name, unsigned backlog, unsigned mss) :
2073Socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP)
2074{
2075 char namebuf[128], *cp;
2076 struct addrinfo hint, *list = NULL, *first;
2077
2078 snprintf(namebuf, sizeof(namebuf), "%s", name);
2079 cp = strrchr(namebuf, '/');
2080
2081 if(!cp) {
2082 cp = namebuf;
2083 name = NULL;
2084 }
2085 else {
2086 name = namebuf;
2087 *(cp++) = 0;
2088 if(!strcmp(name, "*"))
2089 name = NULL;
2090 }
2091
2092 memset(&hint, 0, sizeof(hint));
2093 hint.ai_family = AF_INET6;
2094 hint.ai_socktype = SOCK_STREAM;
2095 hint.ai_protocol = IPPROTO_TCP;
2096 hint.ai_flags = AI_PASSIVE;
2097
2098 if(getaddrinfo(name, cp, &hint, &list) || !list) {
2099 endSocket();
2100 error(errBindingFailed, (char *)"Could not find service", errno);
2101 return;
2102 }
2103
2104#if defined(SO_REUSEADDR)
2105 int opt = 1;
2106 setsockopt(so, SOL_SOCKET, SO_REUSEADDR, (char *)&opt,
2107 (socklen_t)sizeof(opt));
2108#endif
2109
2110 first = list;
2111 while(list) {
2112 if(!bind(so, list->ai_addr, (socklen_t)list->ai_addrlen)) {
2113 state = BOUND;
2114 break;
2115 }
2116 list = list->ai_next;
2117 }
2118 freeaddrinfo(first);
2119 if(state != BOUND) {
2120 endSocket();
2121 error(errBindingFailed,(char *)"Could not bind socket",socket_errno);
2122 return;
2123 }
2124
2125 setSegmentSize(mss);
2126
2127 if(listen(so, backlog)) {
2128 endSocket();
2129 error(errBindingFailed,(char *)"Could not listen on socket",socket_errno);
2130 return;
2131 }
2132}
2133
2134#else
2135TCPV6Socket::TCPV6Socket(const char *name, unsigned backlog, unsigned mss) :
2136Socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP)
2137{
2138 char namebuf[128], *cp;
2139 struct sockaddr_in6 addr;
2140 struct servent *svc;
2141
2142 memset(&addr, 0, sizeof(addr));
2143 snprintf(namebuf, sizeof(namebuf), "%s", name);
2144 cp = strrchr(namebuf, '/');
2145
2146 if(!cp) {
2147 cp = namebuf;
2148 name = "*";
2149 }
2150 else {
2151 name = namebuf;
2152 *(cp++) = 0;
2153 }
2154
2155 addr.sin6_family = AF_INET6;
2156 if(isdigit(*cp))
2157 addr.sin6_port = htons(atoi(cp));
2158 else {
2159 mutex.enter();
2160 svc = getservbyname(cp, "tcp");
2161 if(svc)
2162 addr.sin6_port = svc->s_port;
2163 mutex.leave();
2164 if(!svc) {
2165 endSocket();
2166 error(errBindingFailed, "Could not find service", errno);
2167 return;
2168
2169 }
2170 }
2171
2172 IPV6Address ia(name);
2173 addr.sin6_addr = getaddress(ia);
2174
2175#if defined(SO_REUSEADDR)
2176 int opt = 1;
2177 setsockopt(so, SOL_SOCKET, SO_REUSEADDR, (char *)&opt,
2178 (socklen_t)sizeof(opt));
2179#endif
2180
2181 if(bind(so, (struct sockaddr *)&addr, sizeof(addr))) {
2182 endSocket();
2183 error(errBindingFailed,(char *)"Could not bind socket",socket_errno);
2184 return;
2185 }
2186
2187 setSegmentSize(mss);
2188
2189 if(listen(so, backlog)) {
2190 endSocket();
2191 error(errBindingFailed,(char *)"Could not listen on socket",
2192 socket_errno);
2193 return;
2194 }
2195 state = BOUND;
2196}
2197
2198#endif
2199
2200TCPV6Socket::TCPV6Socket(const IPV6Address &ia, tpport_t port, unsigned backlog, unsigned mss) :
2201Socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP)
2202{
2203 struct sockaddr_in6 addr;
2204
2205 memset(&addr, 0, sizeof(addr));
2206 addr.sin6_family = AF_INET6;
2207 addr.sin6_addr = getaddress(ia);
2208 addr.sin6_port = htons(port);
2209
2210#if defined(SO_REUSEADDR)
2211 int opt = 1;
2212 setsockopt(so, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, (socklen_t)sizeof(opt));
2213#endif
2214 if(bind(so, (struct sockaddr *)&addr, sizeof(addr))) {
2215 endSocket();
2216 error(errBindingFailed,(char *)"Could not bind socket",socket_errno);
2217 return;
2218 }
2219
2220 setSegmentSize(mss);
2221
2222 if(listen(so, backlog)) {
2223 endSocket();
2224 error(errBindingFailed,(char *)"Could not listen on socket",socket_errno);
2225 return;
2226 }
2227 state = BOUND;
2228}
2229
2230bool TCPV6Socket::onAccept(const IPV6Host &ia, tpport_t port)
2231{
2232 return true;
2233}
2234
2235TCPV6Socket::~TCPV6Socket()
2236{
2237 endSocket();
2238}
2239
2240#endif
2241
2242void TCPSocket::reject(void)
2243{
2244 SOCKET rej = accept(so, NULL, NULL);
2245 shutdown(rej, 2);
2246#ifdef WIN32
2247 closesocket(rej);
2248#else
2249 close(rej);
2250#endif
2251}
2252
2253#ifdef CCXX_IPV6
2254void TCPV6Socket::reject(void)
2255{
2256 SOCKET rej = accept(so, NULL, NULL);
2257 shutdown(rej, 2);
2258#ifdef WIN32
2259 closesocket(rej);
2260#else
2261 close(rej);
2262#endif
2263}
2264#endif
2265
2266DCCPSocket::DCCPSocket(Family fam) :
2267Socket(fam, SOCK_DCCP, IPPROTO_DCCP)
2268{
2269 family = fam;
2270}
2271
2272DCCPSocket::DCCPSocket(DCCPSocket& server, timeout_t timeout) :
2273Socket(accept(server.so, NULL, NULL))
2274{
2275 family = server.family;
2276 Socket::state = CONNECTED;
2277 socklen_t alen = sizeof(peer);
2278
2279 getpeername(so, (struct sockaddr *)&peer, &alen);
2280
2281 switch(family) {
2282#ifdef CCXX_IPV6
2283 case IPV6:
2284 if(!server.onAccept(IPV6Host(peer.ipv6.sin6_addr), peer.ipv6.sin6_port))
2285 endSocket();
2286 break;
2287#endif
2288 case IPV4:
2289 if(!server.onAccept(IPV4Host(peer.ipv4.sin_addr), peer.ipv4.sin_port))
2290 endSocket();
2291 break;
2292 }
2293}
2294
2295#ifdef HAVE_GETADDRINFO
2296DCCPSocket::DCCPSocket(const char *name, Family fam, unsigned backlog) :
2297Socket(fam, SOCK_DCCP, IPPROTO_DCCP)
2298{
2299 char namebuf[128], *cp;
2300 struct addrinfo hint, *list = NULL, *first;
2301 snprintf(namebuf, sizeof(namebuf), "%s", name);
2302 cp = strrchr(namebuf, '/');
2303 if(!cp)
2304 cp = strrchr(namebuf, ':');
2305
2306 if(!cp) {
2307 cp = namebuf;
2308 name = NULL;
2309 }
2310 else {
2311 name = namebuf;
2312 *(cp++) = 0;
2313 if(!strcmp(name, "*"))
2314 name = NULL;
2315 }
2316
2317 family = fam;
2318 memset(&hint, 0, sizeof(hint));
2319 hint.ai_family = family;
2320 hint.ai_socktype = SOCK_DCCP;
2321 hint.ai_protocol = IPPROTO_DCCP;
2322 hint.ai_flags = AI_PASSIVE;
2323
2324 if(getaddrinfo(name, cp, &hint, &list) || !list) {
2325 endSocket();
2326 error(errBindingFailed, (char *)"Could not find service", errno);
2327 return;
2328 }
2329
2330#if defined(SO_REUSEADDR)
2331 int opt = 1;
2332 setsockopt(so, SOL_SOCKET, SO_REUSEADDR, (char *)&opt,
2333 (socklen_t)sizeof(opt));
2334#endif
2335
2336 first = list;
2337 while(list) {
2338 if(!bind(so, list->ai_addr, (socklen_t)list->ai_addrlen)) {
2339 state = BOUND;
2340 break;
2341 }
2342 list = list->ai_next;
2343 }
2344 freeaddrinfo(first);
2345 if(state != BOUND) {
2346 endSocket();
2347 error(errBindingFailed,(char *)"Could not bind socket",socket_errno);
2348 return;
2349 }
2350
2351 if(listen(so, backlog)) {
2352 endSocket();
2353 error(errBindingFailed,(char *)"Could not listen on socket",socket_errno);
2354 return;
2355 }
2356}
2357#else
2358DCCPSocket::DCCPSocket(const char *name, Family fam, unsigned backlog) :
2359Socket(fam, SOCK_DCCP, IPPROTO_DCCP)
2360{
2361 char namebuf[128], *cp;
2362 struct sockaddr_in addr;
2363#ifdef CCXX_IPV6
2364 struct sockaddr_in6 addr6;
2365#endif
2366 struct sockaddr_in *ap;
2367 socklen_t alen = 0;
2368
2369 struct servent *svc;
2370
2371 family = fam;
2372 memset(&addr, 0, sizeof(addr));
2373 snprintf(namebuf, sizeof(namebuf), "%s", name);
2374 cp = strrchr(namebuf, '/');
2375 if(!cp)
2376 cp = strrchr(namebuf, ':');
2377
2378 if(!cp) {
2379 cp = namebuf;
2380 name = "*";
2381 }
2382 else {
2383 name = namebuf;
2384 *(cp++) = 0;
2385 }
2386
2387 addr.sin_family = family;
2388 if(isdigit(*cp))
2389 addr.sin_port = htons(atoi(cp));
2390 else {
2391 mutex.enter();
2392 svc = getservbyname(cp, "dccp");
2393 if(svc)
2394 addr.sin_port = svc->s_port;
2395 mutex.leave();
2396 if(!svc) {
2397 endSocket();
2398 error(errBindingFailed, "Could not find service", errno);
2399 return;
2400
2401 }
2402 }
2403
2404#if defined(SO_REUSEADDR)
2405 int opt = 1;
2406 setsockopt(so, SOL_SOCKET, SO_REUSEADDR, (char *)&opt,
2407 (socklen_t)sizeof(opt));
2408#endif
2409
2410 switch(family) {
2411#ifdef CCXX_IPV6
2412 case IPV6:
2413 IPV6Address ia6(name);
2414 addr6.sin6_port = addr.sin_port;
2415 addr6.sin6_family = family;
2416 ap = &addr6;
2417 alen = sizeof(addr6);
2418 break;
2419#endif
2420 case IPV4:
2421 IPV4Address ia(name);
2422 addr.sin_addr = getaddress(ia);
2423 ap = &addr;
2424 alen = sizeof(addr);
2425 }
2426
2427 if(bind(so, (struct sockaddr *)ap, alen)) {
2428 endSocket();
2429 error(errBindingFailed,(char *)"Could not bind socket",socket_errno);
2430 return;
2431 }
2432
2433 if(listen(so, backlog)) {
2434 endSocket();
2435 error(errBindingFailed,(char *)"Could not listen on socket",
2436 socket_errno);
2437 return;
2438 }
2439 state = BOUND;
2440}
2441#endif
2442
2443DCCPSocket::DCCPSocket(const IPV4Address &ia, tpport_t port, unsigned backlog) :
2444Socket(AF_INET, SOCK_DCCP, IPPROTO_DCCP)
2445{
2446 struct sockaddr_in addr;
2447
2448 memset(&addr, 0, sizeof(addr));
2449 addr.sin_family = AF_INET;
2450 addr.sin_addr = getaddress(ia);
2451 addr.sin_port = htons(port);
2452 family = IPV4;
2453
2454 memset(&peer, 0, sizeof(peer));
2455 peer.ipv4 = addr;
2456
2457#if defined(SO_REUSEADDR)
2458 int opt = 1;
2459 setsockopt(so, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, (socklen_t)sizeof(opt));
2460#endif
2461 if(bind(so, (struct sockaddr *)&addr, sizeof(addr))) {
2462 endSocket();
2463 error(errBindingFailed,(char *)"Could not bind socket",socket_errno);
2464 return;
2465 }
2466
2467 if(listen(so, backlog)) {
2468 endSocket();
2469 error(errBindingFailed,(char *)"Could not listen on socket",socket_errno);
2470 return;
2471 }
2472 state = BOUND;
2473}
2474
2475#ifdef CCXX_IPV6
2476DCCPSocket::DCCPSocket(const IPV6Address &ia, tpport_t port, unsigned backlog) :
2477Socket(AF_INET6, SOCK_DCCP, IPPROTO_DCCP)
2478{
2479 struct sockaddr_in6 addr;
2480
2481 memset(&addr, 0, sizeof(addr));
2482 addr.sin6_family = AF_INET6;
2483 addr.sin6_addr = getaddress(ia);
2484 addr.sin6_port = htons(port);
2485
2486 family = IPV6;
2487 memset(&peer, 0, sizeof(peer));
2488 peer.ipv6 = addr;
2489
2490#if defined(SO_REUSEADDR)
2491 int opt = 1;
2492 setsockopt(so, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, (socklen_t)sizeof(opt));
2493#endif
2494 if(bind(so, (struct sockaddr *)&addr, sizeof(addr))) {
2495 endSocket();
2496 error(errBindingFailed,(char *)"Could not bind socket",socket_errno);
2497 return;
2498 }
2499
2500 if(listen(so, backlog)) {
2501 endSocket();
2502 error(errBindingFailed,(char *)"Could not listen on socket",socket_errno);
2503 return;
2504 }
2505 state = BOUND;
2506}
2507
2508bool DCCPSocket::onAccept(const IPV6Host &ia, tpport_t port)
2509{
2510 return true;
2511}
2512
2513#endif
2514
2515bool DCCPSocket::onAccept(const IPV4Host &ia, tpport_t port)
2516{
2517 return true;
2518}
2519
2520IPV4Host DCCPSocket::getIPV4Sender(tpport_t *port) const
2521{
2522 if(port)
2523 *port = ntohs(peer.ipv4.sin_port);
2524 return IPV4Host(peer.ipv4.sin_addr);
2525}
2526
2527#ifdef CCXX_IPV6
2528IPV6Host DCCPSocket::getIPV6Sender(tpport_t *port) const
2529{
2530 return IPV6Host(peer.ipv6.sin6_addr);
2531}
2532#endif
2533
2534DCCPSocket::~DCCPSocket()
2535{
2536 endSocket();
2537}
2538
2539void DCCPSocket::disconnect(void)
2540{
2541 if(Socket::state != CONNECTED)
2542 return;
2543
2544 endSocket();
2545 so = socket(family, SOCK_DCCP, IPPROTO_DCCP);
2546 if(so != INVALID_SOCKET)
2547 Socket::state = AVAILABLE;
2548}
2549
2550#ifdef HAVE_GETADDRINFO
2551void DCCPSocket::connect(const char *target)
2552{
2553 char namebuf[128];
2554 char *cp;
2555 struct addrinfo hint, *list = NULL, *next, *first;
2556 bool connected = false;
2557
2558 snprintf(namebuf, sizeof(namebuf), "%s", target);
2559 cp = strrchr(namebuf, '/');
2560 if(!cp)
2561 cp = strrchr(namebuf, ':');
2562
2563 if(!cp) {
2564 connectError();
2565 return;
2566 }
2567
2568 *(cp++) = 0;
2569
2570 memset(&hint, 0, sizeof(hint));
2571 hint.ai_family = family;
2572 hint.ai_socktype = SOCK_DCCP;
2573 hint.ai_protocol = IPPROTO_DCCP;
2574
2575 if(getaddrinfo(namebuf, cp, &hint, &list) || !list) {
2576 connectError();
2577 return;
2578 }
2579
2580 first = list;
2581
2582 while(list) {
2583 if(!::connect(so, list->ai_addr, (socklen_t)list->ai_addrlen)) {
2584 connected = true;
2585 break;
2586 }
2587 next = list->ai_next;
2588 list = next;
2589 }
2590
2591 freeaddrinfo(first);
2592
2593 if(!connected) {
2594 connectError();
2595 return;
2596 }
2597
2598 Socket::state = CONNECTED;
2599}
2600#else
2601void DCCPSocket::connect(const char *target)
2602{
2603 char namebuf[128];
2604 char *cp;
2605 bool connected = false;
2606 struct servent *svc;
2607 tpport_t port;
2608
2609 snprintf(namebuf, sizeof(namebuf), "%s", target);
2610 cp = strrchr(namebuf, '/');
2611 if(!cp)
2612 cp = strrchr(namebuf, ':');
2613
2614 if(!cp) {
2615 connectError();
2616 return;
2617 }
2618
2619 *(cp++) = 0;
2620
2621 if(isdigit(*cp))
2622 port = atoi(cp);
2623 else {
2624 mutex.enter();
2625 svc = getservbyname(cp, "dccp");
2626 if(svc)
2627 port = ntohs(svc->s_port);
2628 mutex.leave();
2629 if(!svc) {
2630 connectError();
2631 return;
2632 }
2633 }
2634
2635 switch(family) {
2636 case IPV4:
2637 connect(IPV4Host(namebuf), port);
2638 break;
2639#ifdef CCXX_IPV6
2640 case IPV6:
2641 connect(IPV6Host(namebuf), port);
2642 break;
2643#endif
2644 default:
2645 connectError();
2646 }
2647}
2648#endif
2649
2650void DCCPSocket::connect(const IPV4Host &host, tpport_t port, timeout_t timeout)
2651{
2652 size_t i;
2653 fd_set fds;
2654 struct timeval to;
2655 bool connected = false;
2656 int rtn;
2657 int sockopt;
2658 socklen_t len = sizeof(sockopt);
2659
2660 for(i = 0 ; i < host.getAddressCount(); i++) {
2661 struct sockaddr_in addr;
2662 memset(&addr, 0, sizeof(addr));
2663 addr.sin_family = AF_INET;
2664 addr.sin_addr = host.getAddress(i);
2665 addr.sin_port = htons(port);
2666
2667 if(timeout)
2668 setCompletion(false);
2669
2670 // Win32 will crash if you try to connect to INADDR_ANY.
2671 if ( INADDR_ANY == addr.sin_addr.s_addr )
2672 addr.sin_addr.s_addr = INADDR_LOOPBACK;
2673 rtn = ::connect(so, (struct sockaddr *)&addr, (socklen_t)sizeof(addr));
2674 if(!rtn) {
2675 connected = true;
2676 break;
2677 }
2678
2679#ifndef WIN32
2680 if(errno == EINPROGRESS)
2681#else
2682 if(WSAGetLastError() == WSAEINPROGRESS)
2683#endif
2684 {
2685 FD_ZERO(&fds);
2686 FD_SET(so, &fds);
2687 to.tv_sec = timeout / 1000;
2688 to.tv_usec = timeout % 1000 * 1000;
2689
2690 // timeout check for connect completion
2691
2692 if(::select((int)so + 1, NULL, &fds, NULL, &to) < 1)
2693 continue;
2694
2695 getsockopt(so, SOL_SOCKET, SO_ERROR, (char *)&sockopt, &len);
2696 if(!sockopt) {
2697 connected = true;
2698 break;
2699 }
2700 endSocket();
2701 so = socket(AF_INET, SOCK_DCCP, IPPROTO_DCCP);
2702 if(so == INVALID_SOCKET)
2703 break;
2704 }
2705 }
2706
2707 setCompletion(true);
2708 if(!connected) {
2709 rtn = errno;
2710 errno = rtn;
2711 connectError();
2712 return;
2713 }
2714
2715 Socket::state = CONNECTED;
2716}
2717
2718#ifdef CCXX_IPV6
2719void DCCPSocket::connect(const IPV6Host &host, tpport_t port, timeout_t timeout)
2720{
2721 size_t i;
2722 fd_set fds;
2723 struct timeval to;
2724 bool connected = false;
2725 int rtn;
2726 int sockopt;
2727 socklen_t len = sizeof(sockopt);
2728
2729 for(i = 0 ; i < host.getAddressCount(); i++) {
2730 struct sockaddr_in6 addr;
2731 memset(&addr, 0, sizeof(addr));
2732 addr.sin6_family = AF_INET6;
2733 addr.sin6_addr = host.getAddress(i);
2734 addr.sin6_port = htons(port);
2735
2736 if(timeout)
2737 setCompletion(false);
2738
2739 // Win32 will crash if you try to connect to INADDR_ANY.
2740 if ( !memcmp(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any)))
2741 memcpy(&addr.sin6_addr, &in6addr_loopback, sizeof(in6addr_loopback));
2742 rtn = ::connect(so, (struct sockaddr *)&addr, (socklen_t)sizeof(addr));
2743 if(!rtn) {
2744 connected = true;
2745 break;
2746 }
2747
2748#ifndef WIN32
2749 if(errno == EINPROGRESS)
2750#else
2751 if(WSAGetLastError() == WSAEINPROGRESS)
2752#endif
2753 {
2754 FD_ZERO(&fds);
2755 FD_SET(so, &fds);
2756 to.tv_sec = timeout / 1000;
2757 to.tv_usec = timeout % 1000 * 1000;
2758
2759 // timeout check for connect completion
2760
2761 if(::select((int)so + 1, NULL, &fds, NULL, &to) < 1)
2762 continue;
2763
2764 getsockopt(so, SOL_SOCKET, SO_ERROR, (char *)&sockopt, &len);
2765 if(!sockopt) {
2766 connected = true;
2767 break;
2768 }
2769 endSocket();
2770 so = socket(AF_INET6, SOCK_DCCP, IPPROTO_DCCP);
2771 if(so == INVALID_SOCKET)
2772 break;
2773 }
2774 }
2775
2776 setCompletion(true);
2777 if(!connected) {
2778 rtn = errno;
2779 errno = rtn;
2780 connectError();
2781 return;
2782 }
2783
2784 Socket::state = CONNECTED;
2785}
2786#endif
2787
2788bool DCCPSocket::setCCID(uint8 ccid)
2789{
2790 uint8 ccids[16]; /* for getting the available CCIDs, should be large enough */
2791 socklen_t len = sizeof(ccids);
2792 int ret;
2793 bool ccid_supported = false;
2794
2795 /*
2796 * Determine which CCIDs are available on the host
2797 */
2798 ret = getsockopt(so, SOL_DCCP, DCCP_SOCKOPT_AVAILABLE_CCIDS, (char *)&ccids, &len);
2799 if (ret < 0) {
2800 error(errInput,(char *)"Can not determine available CCIDs",socket_errno);
2801 return false;
2802 }
2803
2804 for (unsigned i = 0; i < sizeof(ccids); i++) {
2805 if (ccid == ccids[i]) {
2806 ccid_supported = true;
2807 break;
2808 }
2809 }
2810
2811 if (!ccid_supported) {
2812 error(errInput,(char *)"CCID specified is not supported",socket_errno);
2813 return false;
2814 }
2815
2816 if (setsockopt(so, SOL_DCCP, DCCP_SOCKOPT_CCID, (char *)&ccid, sizeof (ccid)) < 0) {
2817 error(errInput,(char *)"Can not set CCID",socket_errno);
2818 return false;
2819 }
2820
2821 return true;
2822}
2823
2824int DCCPSocket::getTxCCID()
2825{
2826 int ccid, ret;
2827 socklen_t ccidlen;
2828
2829 ccidlen = sizeof(ccid);
2830 ret = getsockopt(so, SOL_DCCP, DCCP_SOCKOPT_TX_CCID, (char *)&ccid, &ccidlen);
2831 if (ret < 0) {
2832 error(errInput,(char *)"Can not determine get current TX CCID value",socket_errno);
2833 return -1;
2834 }
2835 return ccid;
2836}
2837
2838int DCCPSocket::getRxCCID()
2839{
2840 int ccid, ret;
2841 socklen_t ccidlen;
2842
2843 ccidlen = sizeof(ccid);
2844 ret = getsockopt(so, SOL_DCCP, DCCP_SOCKOPT_RX_CCID, (char *)&ccid, &ccidlen);
2845 if (ret < 0) {
2846 error(errInput,(char *)"Can not determine get current DX CCID value",socket_errno);
2847 return -1;
2848 }
2849 return ccid;
2850}
2851
2852#ifndef WIN32
2853#include <sys/ioctl.h>
2854#endif
2855size_t DCCPSocket::available()
2856{
2857 size_t readsize;
2858#ifndef WIN32
2859 if (ioctl (so, FIONREAD, &readsize) < 0) {
2860 error(errInput,(char *)"Error on retrieve the FIONREAD option.",socket_errno);
2861 }
2862#else
2863 if (ioctlsocket(so, FIOREAD, &readsize)){
2864 error(errInput,(char *)"Error on retrieve the FIONREAD option.",socket_errno);
2865 }
2866#endif
2867 return readsize;
2868}
2869
2870TCPStream::TCPStream(TCPSocket &server, bool throwflag, timeout_t to) :
2871 streambuf(), Socket(accept(server.getSocket(), NULL, NULL)),
2872#ifdef HAVE_OLD_IOSTREAM
2873 iostream()
2874#else
2875 iostream((streambuf *)this)
2876#endif
2877 ,bufsize(0)
2878 ,gbuf(NULL)
2879 ,pbuf(NULL) {
2880 tpport_t port;
2881 family = IPV4;
2882
2883#ifdef HAVE_OLD_IOSTREAM
2884 init((streambuf *)this);
2885#endif
2886
2887 timeout = to;
2888 setError(throwflag);
2889 IPV4Host host = getPeer(&port);
2890 if(!server.onAccept(host, port)) {
2891 endSocket();
2892 error(errConnectRejected);
2893 clear(ios::failbit | rdstate());
2894 return;
2895 }
2896
2897 segmentBuffering(server.getSegmentSize());
2898 Socket::state = CONNECTED;
2899}
2900
2901#ifdef CCXX_IPV6
2902TCPStream::TCPStream(TCPV6Socket &server, bool throwflag, timeout_t to) :
2903 streambuf(), Socket(accept(server.getSocket(), NULL, NULL)),
2904#ifdef HAVE_OLD_IOSTREAM
2905 iostream()
2906#else
2907 iostream((streambuf *)this)
2908#endif
2909 ,bufsize(0)
2910 ,gbuf(NULL)
2911 ,pbuf(NULL) {
2912 tpport_t port;
2913
2914 family = IPV6;
2915
2916#ifdef HAVE_OLD_IOSTREAM
2917 init((streambuf *)this);
2918#endif
2919
2920 timeout = to;
2921 setError(throwflag);
2922 IPV6Host host = getIPV6Peer(&port);
2923 if(!server.onAccept(host, port)) {
2924 endSocket();
2925 error(errConnectRejected);
2926 clear(ios::failbit | rdstate());
2927 return;
2928 }
2929
2930 segmentBuffering(server.getSegmentSize());
2931 Socket::state = CONNECTED;
2932}
2933#endif
2934
2935TCPStream::TCPStream(const IPV4Host &host, tpport_t port, unsigned size, bool throwflag, timeout_t to) :
2936 streambuf(), Socket(AF_INET, SOCK_STREAM, IPPROTO_TCP),
2937#ifdef HAVE_OLD_IOSTREAM
2938 iostream(),
2939#else
2940 iostream((streambuf *)this),
2941#endif
2942 bufsize(0),gbuf(NULL),pbuf(NULL) {
2943#ifdef HAVE_OLD_IOSTREAM
2944 init((streambuf *)this);
2945#endif
2946 family = IPV4;
2947 timeout = to;
2948 setError(throwflag);
2949 connect(host, port, size);
2950}
2951
2952#ifdef CCXX_IPV6
2953TCPStream::TCPStream(const IPV6Host &host, tpport_t port, unsigned size, bool throwflag, timeout_t to) :
2954 streambuf(), Socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP),
2955#ifdef HAVE_OLD_IOSTREAM
2956 iostream(),
2957#else
2958 iostream((streambuf *)this),
2959#endif
2960 bufsize(0),gbuf(NULL),pbuf(NULL) {
2961 family = IPV6;
2962
2963#ifdef HAVE_OLD_IOSTREAM
2964 init((streambuf *)this);
2965#endif
2966 timeout = to;
2967 setError(throwflag);
2968 connect(host, port, size);
2969}
2970#endif
2971
2972TCPStream::~TCPStream()
2973{
2974#ifdef CCXX_EXCEPTIONS
2975 try { endStream(); }
2976 catch( ... ) { if ( ! std::uncaught_exception()) throw;};
2977#else
2978 endStream();
2979#endif
2980}
2981
2982#ifdef HAVE_GETADDRINFO
2983
2984void TCPStream::connect(const char *target, unsigned mss)
2985{
2986 char namebuf[128];
2987 char *cp;
2988 struct addrinfo hint, *list = NULL, *next, *first;
2989 bool connected = false;
2990
2991 snprintf(namebuf, sizeof(namebuf), "%s", target);
2992 cp = strrchr(namebuf, '/');
2993 if(!cp)
2994 cp = strrchr(namebuf, ':');
2995
2996 if(!cp) {
2997 endStream();
2998 connectError();
2999 return;
3000 }
3001
3002 *(cp++) = 0;
3003
3004 memset(&hint, 0, sizeof(hint));
3005 hint.ai_family = family;
3006 hint.ai_socktype = SOCK_STREAM;
3007 hint.ai_protocol = IPPROTO_TCP;
3008
3009 if(getaddrinfo(namebuf, cp, &hint, &list) || !list) {
3010 endStream();
3011 connectError();
3012 return;
3013 }
3014
3015 first = list;
3016
3017#ifdef TCP_MAXSEG
3018 if(mss)
3019 setsockopt(so, IPPROTO_TCP, TCP_MAXSEG, (char *)&mss, sizeof(mss));
3020#endif
3021
3022 while(list) {
3023 if(!::connect(so, list->ai_addr, (socklen_t)list->ai_addrlen)) {
3024 connected = true;
3025 break;
3026 }
3027 next = list->ai_next;
3028 list = next;
3029 }
3030
3031 freeaddrinfo(first);
3032
3033 if(!connected) {
3034 endStream();
3035 connectError();
3036 return;
3037 }
3038
3039 segmentBuffering(mss);
3040 Socket::state = CONNECTED;
3041}
3042
3043#else
3044
3045void TCPStream::connect(const char *target, unsigned mss)
3046{
3047 char namebuf[128];
3048 char *cp;
3049 bool connected = false;
3050 struct servent *svc;
3051 tpport_t port;
3052
3053 snprintf(namebuf, sizeof(namebuf), "%s", target);
3054 cp = strrchr(namebuf, '/');
3055 if(!cp)
3056 cp = strrchr(namebuf, ':');
3057
3058 if(!cp) {
3059 endStream();
3060 connectError();
3061 return;
3062 }
3063
3064 *(cp++) = 0;
3065
3066 if(isdigit(*cp))
3067 port = atoi(cp);
3068 else {
3069 mutex.enter();
3070 svc = getservbyname(cp, "tcp");
3071 if(svc)
3072 port = ntohs(svc->s_port);
3073 mutex.leave();
3074 if(!svc) {
3075 endStream();
3076 connectError();
3077 return;
3078 }
3079 }
3080
3081 switch(family) {
3082 case IPV4:
3083 connect(IPV4Host(namebuf), port, mss);
3084 break;
3085#ifdef CCXX_IPV6
3086 case IPV6:
3087 connect(IPV6Host(namebuf), port, mss);
3088 break;
3089#endif
3090 default:
3091 endStream();
3092 connectError();
3093 }
3094}
3095
3096#endif
3097
3098void TCPStream::connect(const IPV4Host &host, tpport_t port, unsigned mss)
3099{
3100 size_t i;
3101 fd_set fds;
3102 struct timeval to;
3103 bool connected = false;
3104 int rtn;
3105 int sockopt;
3106 socklen_t len = sizeof(sockopt);
3107
3108#ifdef TCP_MAXSEG
3109 if(mss)
3110 setsockopt(so, IPPROTO_TCP, TCP_MAXSEG, (char *)&mss, sizeof(mss));
3111#endif
3112
3113 for(i = 0 ; i < host.getAddressCount(); i++) {
3114 struct sockaddr_in addr;
3115 memset(&addr, 0, sizeof(addr));
3116 addr.sin_family = AF_INET;
3117 addr.sin_addr = host.getAddress(i);
3118 addr.sin_port = htons(port);
3119
3120 if(timeout)
3121 setCompletion(false);
3122
3123 // Win32 will crash if you try to connect to INADDR_ANY.
3124 if ( INADDR_ANY == addr.sin_addr.s_addr )
3125 addr.sin_addr.s_addr = INADDR_LOOPBACK;
3126 rtn = ::connect(so, (struct sockaddr *)&addr, (socklen_t)sizeof(addr));
3127 if(!rtn) {
3128 connected = true;
3129 break;
3130 }
3131
3132#ifndef WIN32
3133 if(errno == EINPROGRESS)
3134#else
3135 if(WSAGetLastError() == WSAEINPROGRESS)
3136#endif
3137 {
3138 FD_ZERO(&fds);
3139 FD_SET(so, &fds);
3140 to.tv_sec = timeout / 1000;
3141 to.tv_usec = timeout % 1000 * 1000;
3142
3143 // timeout check for connect completion
3144
3145 if(::select((int)so + 1, NULL, &fds, NULL, &to) < 1)
3146 continue;
3147
3148 getsockopt(so, SOL_SOCKET, SO_ERROR, (char *)&sockopt, &len);
3149 if(!sockopt) {
3150 connected = true;
3151 break;
3152 }
3153 endSocket();
3154 so = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
3155 if(so == INVALID_SOCKET)
3156 break;
3157 }
3158 }
3159
3160 setCompletion(true);
3161 if(!connected) {
3162 rtn = errno;
3163 endStream();
3164 errno = rtn;
3165 connectError();
3166 return;
3167 }
3168
3169 segmentBuffering(mss);
3170 Socket::state = CONNECTED;
3171}
3172
3173#ifdef CCXX_IPV6
3174void TCPStream::connect(const IPV6Host &host, tpport_t port, unsigned mss)
3175{
3176 size_t i;
3177 fd_set fds;
3178 struct timeval to;
3179 bool connected = false;
3180 int rtn;
3181 int sockopt;
3182 socklen_t len = sizeof(sockopt);
3183
3184#ifdef TCP_MAXSEG
3185 if(mss)
3186 setsockopt(so, IPPROTO_TCP, TCP_MAXSEG, (char *)&mss, sizeof(mss));
3187#endif
3188
3189 for(i = 0 ; i < host.getAddressCount(); i++) {
3190 struct sockaddr_in6 addr;
3191 memset(&addr, 0, sizeof(addr));
3192 addr.sin6_family = AF_INET6;
3193 addr.sin6_addr = host.getAddress(i);
3194 addr.sin6_port = htons(port);
3195
3196 if(timeout)
3197 setCompletion(false);
3198
3199 // Win32 will crash if you try to connect to INADDR_ANY.
3200 if ( !memcmp(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any)))
3201 memcpy(&addr.sin6_addr, &in6addr_loopback, sizeof(in6addr_loopback));
3202 rtn = ::connect(so, (struct sockaddr *)&addr, (socklen_t)sizeof(addr));
3203 if(!rtn) {
3204 connected = true;
3205 break;
3206 }
3207
3208#ifndef WIN32
3209 if(errno == EINPROGRESS)
3210#else
3211 if(WSAGetLastError() == WSAEINPROGRESS)
3212#endif
3213 {
3214 FD_ZERO(&fds);
3215 FD_SET(so, &fds);
3216 to.tv_sec = timeout / 1000;
3217 to.tv_usec = timeout % 1000 * 1000;
3218
3219 // timeout check for connect completion
3220
3221 if(::select((int)so + 1, NULL, &fds, NULL, &to) < 1)
3222 continue;
3223
3224 getsockopt(so, SOL_SOCKET, SO_ERROR, (char *)&sockopt, &len);
3225 if(!sockopt) {
3226 connected = true;
3227 break;
3228 }
3229 endSocket();
3230 so = socket(AF_INET6, SOCK_STREAM, IPPROTO_TCP);
3231 if(so == INVALID_SOCKET)
3232 break;
3233 }
3234 }
3235
3236 setCompletion(true);
3237 if(!connected) {
3238 rtn = errno;
3239 endStream();
3240 errno = rtn;
3241 connectError();
3242 return;
3243 }
3244
3245 segmentBuffering(mss);
3246 Socket::state = CONNECTED;
3247}
3248#endif
3249
3250TCPStream::TCPStream(const char *target, Family fam, unsigned mss, bool throwflag, timeout_t to) :
3251streambuf(), Socket(PF_INET, SOCK_STREAM, IPPROTO_TCP),
3252#ifdef HAVE_OLD_IOSTREAM
3253iostream(),
3254#else
3255iostream((streambuf *)this),
3256#endif
3257timeout(to), bufsize(0),gbuf(NULL),pbuf(NULL)
3258{
3259 family = fam;
3260#ifdef HAVE_OLD_IOSTREAM
3261 init((streambuf *)this);
3262#endif
3263 setError(throwflag);
3264 connect(target, mss);
3265}
3266
3267TCPStream::TCPStream(Family fam, bool throwflag, timeout_t to) :
3268streambuf(), Socket(PF_INET, SOCK_STREAM, IPPROTO_TCP),
3269#ifdef HAVE_OLD_IOSTREAM
3270iostream(),
3271#else
3272iostream((streambuf *)this),
3273#endif
3274timeout(to), bufsize(0),gbuf(NULL),pbuf(NULL)
3275{
3276 family = fam;
3277#ifdef HAVE_OLD_IOSTREAM
3278 init((streambuf *)this);
3279#endif
3280 setError(throwflag);
3281}
3282
3283TCPStream::TCPStream(const TCPStream &source) :
3284streambuf(), Socket(DUP_SOCK(source.so,source.state)),
3285#ifdef HAVE_OLD_IOSTREAM
3286iostream()
3287#else
3288iostream((streambuf *)this)
3289#endif
3290{
3291 family = source.family;
3292#ifdef HAVE_OLD_IOSTREAM
3293 init((streambuf *)this);
3294#endif
3295 bufsize = source.bufsize;
3296 allocate(bufsize);
3297}
3298
3299void TCPStream::connect(TCPSocket &tcpip)
3300{
3301 tpport_t port;
3302
3303 endStream();
3304 family = IPV4;
3305 so = accept(tcpip.getSocket(), NULL, NULL);
3306 if(so == INVALID_SOCKET)
3307 return;
3308
3309 IPV4Host host = getPeer(&port);
3310 if(!tcpip.onAccept(host, port)) {
3311 endSocket();
3312 clear(ios::failbit | rdstate());
3313 return;
3314 }
3315
3316 segmentBuffering(tcpip.getSegmentSize());
3317 Socket::state = CONNECTED;
3318}
3319
3320#ifdef CCXX_IPV6
3321
3322void TCPStream::connect(TCPV6Socket &tcpip)
3323{
3324 tpport_t port;
3325
3326 endStream();
3327 family = IPV6;
3328 so = accept(tcpip.getSocket(), NULL, NULL);
3329 if(so == INVALID_SOCKET)
3330 return;
3331
3332 IPV6Host host = getIPV6Peer(&port);
3333 if(!tcpip.onAccept(host, port)) {
3334 endSocket();
3335 clear(ios::failbit | rdstate());
3336 return;
3337 }
3338
3339 segmentBuffering(tcpip.getSegmentSize());
3340 Socket::state = CONNECTED;
3341}
3342#endif
3343
3344void TCPStream::segmentBuffering(unsigned mss)
3345{
3346 unsigned max = 0;
3347 socklen_t alen = sizeof(max);
3348
3349 if(mss == 1) { // special interactive
3350 allocate(1);
3351 return;
3352 }
3353
3354#ifdef TCP_MAXSEG
3355 if(mss)
3356 setsockopt(so, IPPROTO_TCP, TCP_MAXSEG, (char *)&max, sizeof(max));
3357 getsockopt(so, IPPROTO_TCP, TCP_MAXSEG, (char *)&max, &alen);
3358#endif
3359
3360 if(max && max < mss)
3361 mss = max;
3362
3363 if(!mss) {
3364 if(max)
3365 mss = max;
3366 else
3367 mss = 536;
3368 allocate(mss);
3369 return;
3370 }
3371
3372#ifdef TCP_MAXSEG
3373 setsockopt(so, IPPROTO_TCP, TCP_MAXSEG, (char *)&mss, sizeof(mss));
3374#endif
3375
3376 if(mss < 80)
3377 mss = 80;
3378
3379 if(mss * 7 < 64000)
3380 bufferSize(mss * 7);
3381 else if(mss * 6 < 64000)
3382 bufferSize(mss * 6);
3383 else
3384 bufferSize(mss * 5);
3385
3386 if(mss < 512)
3387 sendLimit(mss * 4);
3388
3389 allocate(mss);
3390}
3391
3392int TCPStream::getSegmentSize(void)
3393{
3394 unsigned mss = 0;
3395#ifdef TCP_MAXSEG
3396 socklen_t alen = sizeof(mss);
3397
3398 getsockopt(so, IPPROTO_TCP, TCP_MAXSEG, (char *)&mss, &alen);
3399#endif
3400 if(!mss)
3401 return (int)bufsize;
3402
3403 return mss;
3404}
3405
3406void TCPStream::disconnect(void)
3407{
3408 if(Socket::state == AVAILABLE)
3409 return;
3410
3411 endStream();
3412 so = socket(family, SOCK_STREAM, IPPROTO_TCP);
3413 if(so != INVALID_SOCKET)
3414 Socket::state = AVAILABLE;
3415}
3416
3417void TCPStream::endStream(void)
3418{
3419 if(bufsize)
3420 sync();
3421 if(gbuf)
3422 delete[] gbuf;
3423 if(pbuf)
3424 delete[] pbuf;
3425 gbuf = pbuf = NULL;
3426 bufsize = 0;
3427 clear();
3428 endSocket();
3429}
3430
3431void TCPStream::allocate(size_t size)
3432{
3433 if(size < 2) {
3434 bufsize = 1;
3435 gbuf = pbuf = 0;
3436 return;
3437 }
3438
3439 gbuf = new char[size];
3440 pbuf = new char[size];
3441 if(!pbuf || !gbuf) {
3442 error(errResourceFailure, (char *)"Could not allocate socket stream buffers");
3443 return;
3444 }
3445 bufsize = size;
3446 clear();
3447
3448#if (defined(__GNUC__) && (__GNUC__ < 3)) && !defined(WIN32) && !defined(STLPORT)
3449 setb(gbuf, gbuf + size, 0);
3450#endif
3451 setg(gbuf, gbuf + size, gbuf + size);
3452 setp(pbuf, pbuf + size);
3453}
3454
3455int TCPStream::doallocate()
3456{
3457 if(bufsize)
3458 return 0;
3459
3460 allocate(1);
3461 return 1;
3462}
3463
3464int TCPStream::uflow()
3465{
3466 int ret = underflow();
3467
3468 if (ret == EOF)
3469 return EOF;
3470
3471 if (bufsize != 1)
3472 gbump(1);
3473
3474 return ret;
3475}
3476
3477int TCPStream::underflow()
3478{
3479 ssize_t rlen = 1;
3480 unsigned char ch;
3481
3482 if(bufsize == 1) {
3483 if(Socket::state == STREAM)
3484 rlen = ::read((int)so, (char *)&ch, 1);
3485 else if(timeout && !Socket::isPending(pendingInput, timeout)) {
3486 clear(ios::failbit | rdstate());
3487 error(errTimeout,(char *)"Socket read timed out",socket_errno);
3488 return EOF;
3489 }
3490 else
3491 rlen = readData(&ch, 1);
3492 if(rlen < 1) {
3493 if(rlen < 0) {
3494 clear(ios::failbit | rdstate());
3495 error(errInput,(char *)"Could not read from socket",socket_errno);
3496 }
3497 return EOF;
3498 }
3499 return ch;
3500 }
3501
3502 if(!gptr())
3503 return EOF;
3504
3505 if(gptr() < egptr())
3506 return (unsigned char)*gptr();
3507
3508 rlen = (ssize_t)((gbuf + bufsize) - eback());
3509 if(Socket::state == STREAM)
3510 rlen = ::read((int)so, (char *)eback(), _IOLEN64 rlen);
3511 else if(timeout && !Socket::isPending(pendingInput, timeout)) {
3512 clear(ios::failbit | rdstate());
3513 error(errTimeout,(char *)"Socket read timed out",socket_errno);
3514 return EOF;
3515 }
3516 else
3517 rlen = readData(eback(), rlen);
3518 if(rlen < 1) {
3519// clear(ios::failbit | rdstate());
3520 if(rlen < 0)
3521 error(errNotConnected,(char *)"Connection error",socket_errno);
3522 else {
3523 error(errInput,(char *)"Could not read from socket",socket_errno);
3524 clear(ios::failbit | rdstate());
3525 }
3526 return EOF;
3527 }
3528 error(errSuccess);
3529
3530 setg(eback(), eback(), eback() + rlen);
3531 return (unsigned char) *gptr();
3532}
3533
3534bool TCPStream::isPending(Pending pending, timeout_t timer)
3535{
3536 if(pending == pendingInput && in_avail())
3537 return true;
3538 else if(pending == pendingOutput)
3539 flush();
3540
3541 return Socket::isPending(pending, timer);
3542}
3543
3544int TCPStream::sync(void)
3545{
3546 overflow(EOF);
3547 setg(gbuf, gbuf + bufsize, gbuf + bufsize);
3548 return 0;
3549}
3550
3551#ifdef HAVE_SNPRINTF
3552size_t TCPStream::printf(const char *format, ...)
3553{
3554 va_list args;
3555 size_t len;
3556 char *buf;
3557
3558 va_start(args, format);
3559 overflow(EOF);
3560 len = pptr() - pbase();
3561 buf = pptr();
3562 vsnprintf(buf, len, format, args);
3563 va_end(args);
3564 len = strlen(buf);
3565 if(Socket::state == STREAM)
3566 return ::write((int)so, buf, _IOLEN64 len);
3567 else
3568 return writeData(buf, len);
3569}
3570#endif
3571
3572int TCPStream::overflow(int c)
3573{
3574 unsigned char ch;
3575 ssize_t rlen, req;
3576
3577 if(bufsize == 1) {
3578 if(c == EOF)
3579 return 0;
3580
3581 ch = (unsigned char)(c);
3582 if(Socket::state == STREAM)
3583 rlen = ::write((int)so, (const char *)&ch, 1);
3584 else
3585 rlen = writeData(&ch, 1);
3586 if(rlen < 1) {
3587 if(rlen < 0) {
3588 clear(ios::failbit | rdstate());
3589 error(errOutput,(char *)"Could not write to socket",socket_errno);
3590 }
3591 return EOF;
3592 }
3593 else
3594 return c;
3595 }
3596
3597 if(!pbase())
3598 return EOF;
3599
3600 req = (ssize_t)(pptr() - pbase());
3601 if(req) {
3602 if(Socket::state == STREAM)
3603 rlen = ::write((int)so, (const char *)pbase(), req);
3604 else
3605 rlen = writeData(pbase(), req);
3606 if(rlen < 1) {
3607 if(rlen < 0) {
3608 clear(ios::failbit | rdstate());
3609 error(errOutput,(char *)"Could not write to socket",socket_errno);
3610 }
3611 return EOF;
3612 }
3613 req -= rlen;
3614 }
3615
3616 // if write "partial", rebuffer remainder
3617
3618 if(req)
3619// memmove(pbuf, pptr() + rlen, req);
3620 memmove(pbuf, pbuf + rlen, req);
3621 setp(pbuf, pbuf + bufsize);
3622 pbump(req);
3623
3624 if(c != EOF) {
3625 *pptr() = (unsigned char)c;
3626 pbump(1);
3627 }
3628 return c;
3629}
3630
3631TCPSession::TCPSession(const IPV4Host &ia, tpport_t port, size_t size, int pri, size_t stack) :
3632Thread(pri, stack), TCPStream(IPV4)
3633{
3634 setCompletion(false);
3635 setError(false);
3636 allocate(size);
3637
3638 size_t i;
3639 for(i = 0 ; i < ia.getAddressCount(); i++) {
3640 struct sockaddr_in addr;
3641 memset(&addr, 0, sizeof(addr));
3642 addr.sin_family = AF_INET;
3643 addr.sin_addr = ia.getAddress(i);
3644 addr.sin_port = htons(port);
3645
3646 // Win32 will crash if you try to connect to INADDR_ANY.
3647 if ( INADDR_ANY == addr.sin_addr.s_addr )
3648 addr.sin_addr.s_addr = INADDR_LOOPBACK;
3649 if(::connect(so, (struct sockaddr *)&addr, (socklen_t)sizeof(addr)) == 0)
3650 break;
3651
3652#ifdef WIN32
3653 if(WSAGetLastError() == WSAEISCONN || WSAGetLastError() == WSAEWOULDBLOCK)
3654#else
3655 if(errno == EINPROGRESS)
3656#endif
3657 {
3658 Socket::state = CONNECTING;
3659 return;
3660 }
3661 }
3662
3663 if(i == ia.getAddressCount()) {
3664 endSocket();
3665 Socket::state = INITIAL;
3666 return;
3667 }
3668
3669 setCompletion(true);
3670 Socket::state = CONNECTED;
3671}
3672
3673#ifdef CCXX_IPV6
3674TCPSession::TCPSession(const IPV6Host &ia, tpport_t port, size_t size, int pri, size_t stack) :
3675Thread(pri, stack), TCPStream(IPV6)
3676{
3677 setCompletion(false);
3678 setError(false);
3679 allocate(size);
3680
3681 size_t i;
3682 for(i = 0 ; i < ia.getAddressCount(); i++) {
3683 struct sockaddr_in6 addr;
3684 memset(&addr, 0, sizeof(addr));
3685 addr.sin6_family = AF_INET6;
3686 addr.sin6_addr = ia.getAddress(i);
3687 addr.sin6_port = htons(port);
3688
3689 // Win32 will crash if you try to connect to INADDR_ANY.
3690 if(!memcmp(&addr.sin6_addr, &in6addr_any, sizeof(in6addr_any)))
3691 memcpy(&addr.sin6_addr, &in6addr_loopback, sizeof(in6addr_loopback));
3692 if(::connect(so, (struct sockaddr *)&addr, (socklen_t)sizeof(addr)) == 0)
3693 break;
3694
3695#ifdef WIN32
3696// if(WSAGetLastError() == WSAEWOULDBLOCK)
3697 if(WSAGetLastError() == WSAEISCONN)
3698#else
3699 if(errno == EINPROGRESS)
3700#endif
3701 {
3702 Socket::state = CONNECTING;
3703 return;
3704 }
3705 }
3706
3707 if(i == ia.getAddressCount()) {
3708 endSocket();
3709 Socket::state = INITIAL;
3710 return;
3711 }
3712
3713 setCompletion(true);
3714 Socket::state = CONNECTED;
3715}
3716#endif
3717
3718
3719TCPSession::TCPSession(TCPSocket &s, int pri, size_t stack) :
3720Thread(pri, stack), TCPStream(s)
3721{
3722 setCompletion(true);
3723 setError(false);
3724}
3725
3726#ifdef CCXX_IPV6
3727TCPSession::TCPSession(TCPV6Socket &s, int pri, size_t stack) :
3728Thread(pri, stack), TCPStream(s)
3729{
3730 setCompletion(true);
3731 setError(false);
3732}
3733#endif
3734
3735TCPSession::~TCPSession()
3736{
3737 endStream();
3738}
3739
3740int TCPSession::waitConnection(timeout_t timer)
3741{
3742 int sockopt = 0;
3743 socklen_t len = sizeof(sockopt);
3744
3745 switch(Socket::state) {
3746 case INITIAL:
3747 return -1;
3748 case CONNECTED:
3749 break;
3750 case CONNECTING:
3751 if(!Socket::isPending(pendingOutput, timer)) {
3752 endSocket();
3753 Socket::state = INITIAL;
3754 return -1;
3755 }
3756
3757 getsockopt(so, SOL_SOCKET, SO_ERROR, (char *)&sockopt, &len);
3758 if(sockopt) {
3759 endSocket();
3760 Socket::state = INITIAL;
3761 return -1;
3762 }
3763 default:
3764 break;
3765 }
3766 Socket::state = CONNECTED;
3767 return 0;
3768}
3769
3770void TCPSession::initial(void)
3771{
3772 if(waitConnection(60000))
3773 exit();
3774}
3775
3776ostream& operator<<(ostream &os, const IPV4Address &ia)
3777{
3778 os << inet_ntoa(getaddress(ia));
3779 return os;
3780}
3781
3782#ifdef WIN32
3783init_WSA::init_WSA()
3784{
3785 //-initialize OS socket resources!
3786 WSADATA wsaData;
3787
3788 if (WSAStartup(MAKEWORD(2, 2), &wsaData)) {
3789 abort();
3790 }
3791};
3792
3793init_WSA::~init_WSA()
3794{
3795 WSACleanup();
3796}
3797
3798init_WSA init_wsa;
3799#endif
3800
3801#ifdef CCXX_NAMESPACES
3802}
3803#endif
3804
3805/** EMACS **
3806 * Local variables:
3807 * mode: c++
3808 * c-basic-offset: 4
3809 * End:
3810 */