1 module tango.net.device.Berkeley;
2 
3 private import tango.sys.Common;
4 
5 private import tango.core.Exception;
6 
7 import  consts=tango.sys.consts.socket;
8 
9 private import tango.stdc.string : strlen;
10 private import  tango.stdc.stringz;
11 
12 /*******************************************************************************
13 
14 *******************************************************************************/
15 
16 enum {SOCKET_ERROR = consts.SOCKET_ERROR}
17 
18 /*******************************************************************************
19 
20 *******************************************************************************/
21 
22 enum SocketOption
23 {
24         DEBUG        =   consts.SO_DEBUG     ,       /* turn on debugging info recording */
25         BROADCAST    =   consts.SO_BROADCAST ,       /* permit sending of broadcast msgs */
26         REUSEADDR    =   consts.SO_REUSEADDR ,       /* allow local address reuse */
27         LINGER       =   consts.SO_LINGER    ,       /* linger on close if data present */
28         DONTLINGER   = ~(consts.SO_LINGER),
29 
30         OOBINLINE    =   consts.SO_OOBINLINE ,       /* leave received OOB data in line */
31         ACCEPTCONN   =   consts.SO_ACCEPTCONN,       /* socket has had listen() */
32         KEEPALIVE    =   consts.SO_KEEPALIVE ,       /* keep connections alive */
33         DONTROUTE    =   consts.SO_DONTROUTE ,       /* just use interface addresses */
34         TYPE         =   consts.SO_TYPE      ,       /* get socket type */
35 
36         /*
37          * Additional options, not kept in so_options.
38          */
39         SNDBUF       = consts.SO_SNDBUF,               /* send buffer size */
40         RCVBUF       = consts.SO_RCVBUF,               /* receive buffer size */
41         ERROR        = consts.SO_ERROR ,               /* get error status and clear */
42 
43         // OptionLevel.IP settings
44         MULTICAST_TTL   = consts.IP_MULTICAST_TTL  ,
45         MULTICAST_LOOP  = consts.IP_MULTICAST_LOOP ,
46         ADD_MEMBERSHIP  = consts.IP_ADD_MEMBERSHIP ,
47         DROP_MEMBERSHIP = consts.IP_DROP_MEMBERSHIP,
48 
49         // OptionLevel.TCP settings
50         TCP_NODELAY     = consts.TCP_NODELAY ,
51 
52         // Windows specifics
53         WIN_UPDATE_ACCEPT_CONTEXT  = 0x700B,
54         WIN_CONNECT_TIME           = 0x700C,
55         WIN_UPDATE_CONNECT_CONTEXT = 0x7010,
56 }
57 
58 /*******************************************************************************
59 
60 *******************************************************************************/
61 
62 enum SocketOptionLevel
63 {
64         SOCKET = consts.SOL_SOCKET    ,
65         IP     = consts.IPPROTO_IP    ,
66         TCP    = consts.IPPROTO_TCP   ,
67         UDP    = consts.IPPROTO_UDP   ,
68 }
69 
70 /*******************************************************************************
71 
72 *******************************************************************************/
73 
74 enum SocketType
75 {
76         STREAM    = consts.SOCK_STREAM   , /++ sequential, reliable +/
77         DGRAM     = consts.SOCK_DGRAM    , /++ connectionless unreliable, max length +/
78         SEQPACKET = consts.SOCK_SEQPACKET, /++ sequential, reliable, max length +/
79 }
80 
81 /*******************************************************************************
82 
83 *******************************************************************************/
84 
85 enum ProtocolType
86 {
87         IP   = consts.IPPROTO_IP   ,     /// default internet protocol (probably 4 for compatibility)
88         IPV4 = consts.IPPROTO_IP   ,     /// internet protocol version 4
89         IPV6 = consts.IPPROTO_IPV6 ,     /// internet protocol version 6
90         ICMP = consts.IPPROTO_ICMP ,     /// internet control message protocol
91         IGMP = consts.IPPROTO_IGMP ,     /// internet group management protocol
92         TCP  = consts.IPPROTO_TCP  ,     /// transmission control protocol
93         PUP  = consts.IPPROTO_PUP  ,     /// PARC universal packet protocol
94         UDP  = consts.IPPROTO_UDP  ,     /// user datagram protocol
95         IDP  = consts.IPPROTO_IDP  ,     /// Xerox NS protocol
96 }
97 
98 /*******************************************************************************
99 
100 *******************************************************************************/
101 
102 enum AddressFamily
103 {
104         UNSPEC    = consts.AF_UNSPEC   ,
105         UNIX      = consts.AF_UNIX     ,
106         INET      = consts.AF_INET     ,
107         IPX       = consts.AF_IPX      ,
108         APPLETALK = consts.AF_APPLETALK,
109         INET6     = consts.AF_INET6    ,
110 }
111 
112 /*******************************************************************************
113 
114 *******************************************************************************/
115 
116 enum SocketShutdown
117 {
118         RECEIVE =  consts.SHUT_RD,
119         SEND =     consts.SHUT_WR,
120         BOTH =     consts.SHUT_RDWR,
121 }
122 
123 /*******************************************************************************
124 
125 *******************************************************************************/
126 
127 enum SocketFlags
128 {
129         NONE =           0,
130         OOB =            consts.MSG_OOB,        /// out of band
131         PEEK =           consts.MSG_PEEK,       /// only for receiving
132         DONTROUTE =      consts.MSG_DONTROUTE,  /// only for sending
133         NOSIGNAL =       0x4000,                /// inhibit signals
134 }
135 
136 enum AIFlags: int
137 {
138         PASSIVE = consts.AI_PASSIVE,            /// get address to use bind()
139         CANONNAME = consts.AI_CANONNAME,        /// fill ai_canonname
140         NUMERICHOST = consts.AI_NUMERICHOST,    /// prevent host name resolution
141         NUMERICSERV = consts.AI_NUMERICSERV,    /// prevent service name resolution valid
142                                                 /// flags for addrinfo (not a standard def,
143                                                 /// apps should not use it)
144         ALL = consts.AI_ALL,                    /// IPv6 and IPv4-mapped (with AI_V4MAPPED)
145         ADDRCONFIG = consts.AI_ADDRCONFIG,      /// only if any address is assigned
146         V4MAPPED = consts.AI_V4MAPPED,          /// accept IPv4-mapped IPv6 address special
147                                                 /// recommended flags for getipnodebyname
148         MASK = consts.AI_MASK,
149         DEFAULT = consts.AI_DEFAULT,
150 }
151 
152 enum AIError
153 {
154         BADFLAGS = consts.EAI_BADFLAGS,	        /// Invalid value for `ai_flags' field.
155         NONAME = consts.EAI_NONAME,	        /// NAME or SERVICE is unknown.
156         AGAIN = consts.EAI_AGAIN,	        /// Temporary failure in name resolution.
157         FAIL = consts.EAI_FAIL,	                /// Non-recoverable failure in name res.
158         NODATA = consts.EAI_NODATA,	        /// No address associated with NAME.
159         FAMILY = consts.EAI_FAMILY,	        /// `ai_family' not supported.
160         SOCKTYPE = consts.EAI_SOCKTYPE,	        /// `ai_socktype' not supported.
161         SERVICE = consts.EAI_SERVICE,	        /// SERVICE not supported for `ai_socktype'.
162         MEMORY = consts.EAI_MEMORY,	        /// Memory allocation failure.
163 }
164 
165 
166 enum NIFlags: int
167 {
168         MAXHOST = consts.NI_MAXHOST,
169         MAXSERV = consts.NI_MAXSERV,
170         NUMERICHOST = consts.NI_NUMERICHOST,    /// Don't try to look up hostname.
171         NUMERICSERV = consts.NI_NUMERICSERV,    /// Don't convert port number to name.
172         NOFQDN = consts.NI_NOFQDN,              /// Only return nodename portion.
173         NAMEREQD = consts.NI_NAMEREQD,          /// Don't return numeric addresses.
174         DGRAM = consts.NI_DGRAM,                /// Look up UDP service rather than TCP.
175 }
176 
177 
178 /*******************************************************************************
179 
180         conversions for network byte-order
181 
182 *******************************************************************************/
183 
184 version(BigEndian)
185 {
186         private ushort htons (ushort x)
187         {
188                 return x;
189         }
190 
191         private uint htonl (uint x)
192         {
193                 return x;
194         }
195 }
196 else
197 {
198         private import tango.core.BitManip;
199 
200         private ushort htons (ushort x)
201         {
202                 return cast(ushort) ((x >> 8) | (x << 8));
203         }
204 
205         private uint htonl (uint x)
206         {
207                 return bswap(x);
208         }
209 }
210 
211 /*******************************************************************************
212 
213 
214 *******************************************************************************/
215 
216 version (Win32)
217 {
218         pragma (lib, "ws2_32.lib");
219     
220         private import tango.sys.win32.WsaSock;
221 
222         enum socket_t: int
223         {
224             init  = ~0
225         }
226 
227         package extern (Windows)
228         {
229                 alias closesocket close;
230 
231                 socket_t socket(int af, int type, int protocol);
232                 int ioctlsocket(socket_t s, int cmd, uint* argp);
233                 uint inet_addr(const(char)* cp);
234                 int bind(socket_t s, Address.sockaddr* name, int namelen);
235                 int connect(socket_t s, Address.sockaddr* name, int namelen);
236                 int listen(socket_t s, int backlog);
237                 socket_t accept(socket_t s, Address.sockaddr* addr, int* addrlen);
238                 int closesocket(socket_t s);
239                 int shutdown(socket_t s, int how);
240                 int getpeername(socket_t s, Address.sockaddr* name, int* namelen);
241                 int getsockname(socket_t s, Address.sockaddr* name, int* namelen);
242                 int send(socket_t s, const(void)* buf, int len, int flags);
243                 int sendto(socket_t s, const(void)* buf, int len, int flags, Address.sockaddr* to, int tolen);
244                 int recv(socket_t s, void* buf, int len, int flags);
245                 int recvfrom(socket_t s, void* buf, int len, int flags, Address.sockaddr* from, int* fromlen);
246                 int select(int nfds, SocketSet.fd* readfds, SocketSet.fd* writefds, SocketSet.fd* errorfds, SocketSet.timeval* timeout);
247                 int getsockopt(socket_t s, int level, int optname, void* optval, int* optlen);
248                 int setsockopt(socket_t s, int level, int optname, const(void)* optval, int optlen);
249                 int gethostname(void* namebuffer, int buflen);
250                 char* inet_ntoa(uint ina);
251                 NetHost.hostent* gethostbyname(const(char)* name);
252                 NetHost.hostent* gethostbyaddr(const(void)* addr, int len, int type);
253                 /**
254                 The gai_strerror function translates error codes of getaddrinfo,
255                 freeaddrinfo and getnameinfo to a human readable string, suitable
256                 for error reporting. (C) MAN
257                 */
258                 //char* gai_strerror(int errcode);
259 
260                 /**
261                 Given node and service, which identify an Internet host and a service,
262                 getaddrinfo() returns one or more addrinfo structures, each of which
263                 contains an Internet address that can be specified in a call to bind
264                 or connect. The getaddrinfo() function combines the functionality
265                 provided by the getservbyname and getservbyport functions into a single
266                 interface, but unlike the latter functions, getaddrinfo() is reentrant
267                 and allows programs to eliminate IPv4-versus-IPv6 dependencies.(C) MAN
268                 */
269                 int function(const(char)* node, const(char)* service, Address.addrinfo* hints, Address.addrinfo** res) getaddrinfo;
270 
271                 /**
272                 The freeaddrinfo() function frees the memory that was allocated for the
273                 dynamically allocated linked list res.  (C) MAN
274                 */
275                 void function(Address.addrinfo *res) freeaddrinfo;
276 
277                 /**
278                 The getnameinfo() function is the inverse of getaddrinfo: it converts
279                 a socket address to a corresponding host and service, in a protocol-
280                 independent manner. It combines the functionality of gethostbyaddr and
281                 getservbyport, but unlike those functions, getaddrinfo is reentrant and
282                 allows programs to eliminate IPv4-versus-IPv6 dependencies. (C) MAN
283                 */
284                 int function(Address.sockaddr* sa, int salen, char* host, int hostlen, char* serv, int servlen, int flags) getnameinfo;
285 
286                 bool function (socket_t, uint, void*, DWORD, DWORD, DWORD, DWORD*, OVERLAPPED*) AcceptEx;
287                 bool function (socket_t, HANDLE, DWORD, DWORD, OVERLAPPED*, void*, DWORD) TransmitFile;
288                 bool function (socket_t, void*, int, void*, DWORD, DWORD*, OVERLAPPED*) ConnectEx;
289 
290                 //char* inet_ntop(int af, void *src, char *dst, int len);
291         }
292 
293         private __gshared HMODULE lib;
294 
295         shared static this()
296         {
297                 lib = LoadLibraryA ("Ws2_32.dll");
298                 getnameinfo = cast(typeof(getnameinfo)) GetProcAddress(lib, "getnameinfo");
299                 if (!getnameinfo)
300                    {
301                    FreeLibrary (lib);
302                    lib = LoadLibraryA ("Wship6.dll");
303                    }
304                 getnameinfo = cast(typeof(getnameinfo)) GetProcAddress(lib, "getnameinfo");
305                 getaddrinfo = cast(typeof(getaddrinfo)) GetProcAddress(lib, "getaddrinfo");
306                 freeaddrinfo = cast(typeof(freeaddrinfo)) GetProcAddress(lib, "freeaddrinfo");
307                 if (!getnameinfo)
308                    {
309                    FreeLibrary (lib);
310                    lib = null;
311                    }
312 
313                 WSADATA wd = void;
314                 if (WSAStartup (0x0202, &wd))
315                     throw new SocketException("version of socket library is too old");
316 
317                 DWORD result;
318                 Guid acceptG   = {0xb5367df1, 0xcbac, 0x11cf, [0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92]};
319                 Guid connectG  = {0x25a207b9, 0xddf3, 0x4660, [0x8e,0xe9,0x76,0xe5,0x8c,0x74,0x06,0x3e]};
320                 Guid transmitG = {0xb5367df0, 0xcbac, 0x11cf, [0x95,0xca,0x00,0x80,0x5f,0x48,0xa1,0x92]};
321 
322                 auto s = cast(HANDLE) socket (AddressFamily.INET, SocketType.STREAM, ProtocolType.TCP);
323                 assert (s != cast(HANDLE) -1);
324 
325                 WSAIoctl (s, SIO_GET_EXTENSION_FUNCTION_POINTER,
326                           &connectG, connectG.sizeof, &ConnectEx,
327                           ConnectEx.sizeof, &result, null, null);
328 
329                 WSAIoctl (s, SIO_GET_EXTENSION_FUNCTION_POINTER,
330                           &acceptG, acceptG.sizeof, &AcceptEx,
331                           AcceptEx.sizeof, &result, null, null);
332 
333                 WSAIoctl (s, SIO_GET_EXTENSION_FUNCTION_POINTER,
334                           &transmitG, transmitG.sizeof, &TransmitFile,
335                           TransmitFile.sizeof, &result, null, null);
336                 closesocket (cast(socket_t)(cast(int)s));
337         }
338 
339         shared static ~this()
340         {
341                 if (lib)
342                     FreeLibrary (lib);
343                 WSACleanup();
344         }
345 }
346 else
347 {
348         private import tango.stdc.errno;
349 
350         //private alias int socket_t = -1;
351         enum socket_t: int
352         {
353             init  = -1
354         }
355 
356         package extern (C)
357         {
358                 socket_t socket(int af, int type, int protocol);
359                 int fcntl(socket_t s, int f, ...);
360                 uint inet_addr(const(char)* cp);
361                 int bind(socket_t s, const(Address.sockaddr)* name, int namelen);
362                 int connect(socket_t s, const(Address.sockaddr)* name, int namelen);
363                 int listen(socket_t s, int backlog);
364                 socket_t accept(socket_t s, Address.sockaddr* addr, int* addrlen);
365                 int close(socket_t s);
366                 int shutdown(socket_t s, int how);
367                 int getpeername(socket_t s, Address.sockaddr* name, int* namelen);
368                 int getsockname(socket_t s, Address.sockaddr* name, int* namelen);
369                 int send(socket_t s, const(void)* buf, size_t len, int flags);
370                 int sendto(socket_t s, const(void)* buf, size_t len, int flags, Address.sockaddr* to, int tolen);
371                 int recv(socket_t s, void* buf, size_t len, int flags);
372                 int recvfrom(socket_t s, void* buf, size_t len, int flags, Address.sockaddr* from, int* fromlen);
373                 int select(int nfds, SocketSet.fd* readfds, SocketSet.fd* writefds, SocketSet.fd* errorfds, SocketSet.timeval* timeout);
374                 int getsockopt(socket_t s, int level, int optname, void* optval, int* optlen);
375                 int setsockopt(socket_t s, int level, int optname, const(void)* optval, int optlen);
376                 int gethostname(void* namebuffer, int buflen);
377                 char* inet_ntoa(uint ina);
378                 NetHost.hostent* gethostbyname(const(char)* name);
379                 NetHost.hostent* gethostbyaddr(const(void)* addr, int len, int type);
380 
381                 /**
382                 Given node and service, which identify an Internet host and a service,
383                 getaddrinfo() returns one or more addrinfo structures, each of which
384                 contains an Internet address that can be specified in a call to bind or
385                 connect. The getaddrinfo() function combines the functionality provided
386                 by the getservbyname and getservbyport functions into a single interface,
387                 but unlike the latter functions, getaddrinfo() is reentrant and allows
388                 programs to eliminate IPv4-versus-IPv6 dependencies. (C) MAN
389                 */
390                 int getaddrinfo(const(char)* node, const(char)* service, Address.addrinfo* hints, Address.addrinfo** res);
391 
392                 /**
393                 The freeaddrinfo() function frees the memory that was allocated for the
394                 dynamically allocated linked list res.  (C) MAN
395                 */
396                 void freeaddrinfo(Address.addrinfo *res);
397 
398                 /**
399                 The getnameinfo() function is the inverse of getaddrinfo: it converts a socket
400                 address to a corresponding host and service, in a protocol-independent manner.
401                 It combines the functionality of gethostbyaddr and getservbyport, but unlike
402                 those functions, getaddrinfo is reentrant and allows programs to eliminate
403                 IPv4-versus-IPv6 dependencies. (C) MAN
404                 */
405                 int getnameinfo(Address.sockaddr* sa, int salen, char* host, int hostlen, char* serv, int servlen, int flags);
406 
407                 /**
408                 The gai_strerror function translates error codes of getaddrinfo, freeaddrinfo
409                 and getnameinfo to a human readable string, suitable for error reporting. (C) MAN
410                 */
411                 const(char)* gai_strerror(int errcode);
412 
413                 const(char)* inet_ntop(int af, const(void) *src, char *dst, int len);
414        }
415 }
416 
417 
418 /*******************************************************************************
419 
420 *******************************************************************************/
421 
422 public struct Berkeley
423 {
424         socket_t        sock;
425         SocketType      type;
426         AddressFamily   family;
427         ProtocolType    protocol;
428 version (Windows)
429          bool           synchronous;
430 
431         enum INVALID_SOCKET = socket_t.init;
432 
433         enum
434         {
435                 Error = -1
436         }
437 
438         alias Error        ERROR;               // backward compatibility
439         alias noDelay      setNoDelay;          // backward compatibility
440         alias addressReuse setAddressReuse;     // backward compatibility
441 
442 
443         /***********************************************************************
444 
445                 Configure this instance
446 
447         ***********************************************************************/
448 
449         void open (AddressFamily family, SocketType type, ProtocolType protocol, bool create=true)
450         {
451                 this.type = type;
452                 this.family = family;
453                 this.protocol = protocol;
454                 if (create)
455                     reopen();
456         }
457 
458         /***********************************************************************
459 
460                 Open/reopen a native socket for this instance
461 
462         ***********************************************************************/
463 
464         void reopen (socket_t sock = sock.init)
465         {
466                 if (this.sock != sock.init)
467                     this.detach();
468 
469                 if (sock is sock.init)
470                    {
471                    sock = cast(socket_t) socket (family, type, protocol);
472                    if (sock is sock.init)
473                        exception ("Unable to create socket: ");
474                    }
475 
476                 this.sock = sock;
477         }
478 
479         /***********************************************************************
480 
481                 calling shutdown() before this is recommended for connection-
482                 oriented sockets
483 
484         ***********************************************************************/
485 
486         void detach ()
487         {
488                 if (sock != sock.init)
489                     .close (sock);
490                 sock = sock.init;
491         }
492 
493         /***********************************************************************
494 
495                 Return the underlying OS handle of this Conduit
496 
497         ***********************************************************************/
498 
499         @property const socket_t handle ()
500         {
501                 return sock;
502         }
503 
504         /***********************************************************************
505 
506                 Return socket error status
507 
508         ***********************************************************************/
509 
510         @property const int error ()
511         {
512                 int errcode;
513                 getOption (SocketOptionLevel.SOCKET, SocketOption.ERROR, (&errcode)[0..1]);
514                 return errcode;
515         }
516 
517         /***********************************************************************
518 
519                 Return the last error
520 
521         ***********************************************************************/
522 
523         @property static int lastError ()
524         {
525                 version (Win32)
526                          return WSAGetLastError();
527                    else
528                       return errno;
529         }
530 
531         /***********************************************************************
532 
533                 Is this socket still alive? A closed socket is considered to
534                 be dead, but a shutdown socket is still alive.
535 
536         ***********************************************************************/
537 
538         @property const bool isAlive ()
539         {
540                 int type, typesize = type.sizeof;
541                 return getsockopt (sock, SocketOptionLevel.SOCKET,
542                                    SocketOption.TYPE, cast(char*) &type,
543                                    &typesize) != Error;
544         }
545 
546         /***********************************************************************
547 
548         ***********************************************************************/
549 
550         @property AddressFamily addressFamily ()
551         {
552                 return family;
553         }
554 
555         /***********************************************************************
556 
557         ***********************************************************************/
558 
559         Berkeley* bind (Address addr)
560         {
561                 if(Error == .bind (sock, addr.name, addr.nameLen))
562                    exception ("Unable to bind socket: ");
563                 return &this;
564         }
565 
566         /***********************************************************************
567 
568         ***********************************************************************/
569 
570         Berkeley* connect (Address to)
571         {
572                 if (Error == .connect (sock, to.name, to.nameLen))
573                    {
574                    if (! blocking)
575                       {
576                       auto err = lastError;
577                       version (Windows)
578                               {
579                               if (err is WSAEWOULDBLOCK)
580                                   return &this;
581                               }
582                            else
583                               {
584                               if (err is EINPROGRESS)
585                                   return &this;
586                               }
587                       }
588                    exception ("Unable to connect socket: ");
589                    }
590                 return &this;
591         }
592 
593         /***********************************************************************
594 
595                 need to bind() first
596 
597         ***********************************************************************/
598 
599         Berkeley* listen (int backlog)
600         {
601                 if (Error == .listen (sock, backlog))
602                     exception ("Unable to listen on socket: ");
603                 return &this;
604         }
605 
606         /***********************************************************************
607 
608                 need to bind() first
609 
610         ***********************************************************************/
611 
612         void accept (ref Berkeley target)
613         {
614                 auto newsock = .accept (sock, null, null);
615                 if (socket_t.init is newsock)
616                     exception ("Unable to accept socket connection: ");
617 
618                 target.reopen (newsock);
619                 target.protocol = protocol;            //same protocol
620                 target.family = family;                //same family
621                 target.type = type;                    //same type
622         }
623 
624         /***********************************************************************
625 
626                 The shutdown function shuts down the connection of the socket.
627                 Depending on the argument value, it will:
628 
629                     -   stop receiving data for this socket. If further data
630                         arrives, it is rejected.
631 
632                     -   stop trying to transmit data from this socket. Also
633                         discards any data waiting to be sent. Stop looking for
634                         acknowledgement of data already sent; don't retransmit
635                         if any data is lost.
636 
637         ***********************************************************************/
638 
639         Berkeley* shutdown (SocketShutdown how)
640         {
641                 .shutdown (sock, how);
642                 return &this;
643         }
644 
645         /***********************************************************************
646 
647                 set linger timeout
648 
649         ***********************************************************************/
650 
651         @property Berkeley* linger (int period)
652         {
653                 version (Win32)
654                          alias ushort attr;
655                    else
656                        alias uint attr;
657 
658                 union linger
659                 {
660                         struct {
661                                attr l_onoff;            // option on/off
662                                attr l_linger;           // linger time
663                                };
664                         attr[2] array;                  // combined
665                 }
666 
667                 linger l;
668                 l.l_onoff = 1;                          // option on/off
669                 l.l_linger = cast(ushort) period;       // linger time
670 
671                 return setOption (SocketOptionLevel.SOCKET, SocketOption.LINGER, l.array);
672         }
673 
674         /***********************************************************************
675 
676                 enable/disable address reuse
677 
678         ***********************************************************************/
679 
680         @property Berkeley* addressReuse (bool enabled)
681         {
682                 int[1] x = enabled;
683                 return setOption (SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, x);
684         }
685 
686         /***********************************************************************
687 
688                 enable/disable noDelay option (nagle)
689 
690         ***********************************************************************/
691 
692         @property Berkeley* noDelay (bool enabled)
693         {
694                 int[1] x = enabled;
695                 return setOption (SocketOptionLevel.TCP, SocketOption.TCP_NODELAY, x);
696         }
697 
698         /***********************************************************************
699 
700                 Helper function to handle the adding and dropping of group
701                 membership.
702 
703         ***********************************************************************/
704 
705         void joinGroup (IPv4Address address, bool onOff)
706         {
707                 assert (address, "Socket.joinGroup :: invalid null address");
708 
709                 struct ip_mreq
710                 {
711                 uint  imr_multiaddr;  /* IP multicast address of group */
712                 uint  imr_interface;  /* local IP address of interface */
713                 }
714 
715                 ip_mreq mrq;
716 
717                 auto option = (onOff) ? SocketOption.ADD_MEMBERSHIP : SocketOption.DROP_MEMBERSHIP;
718                 mrq.imr_interface = 0;
719                 mrq.imr_multiaddr = address.sin.sin_addr;
720 
721                 if (.setsockopt(sock, SocketOptionLevel.IP, option, &mrq, mrq.sizeof) == Error)
722                     exception ("Unable to perform multicast join: ");
723         }
724 
725         /***********************************************************************
726 
727         ***********************************************************************/
728 
729         const Address newFamilyObject ()
730         {
731                 if (family is AddressFamily.INET)
732                    return new IPv4Address;
733                 if (family is AddressFamily.INET6)
734                    return new IPv6Address;
735                 return new UnknownAddress;
736         }
737 
738         /***********************************************************************
739 
740                 return the hostname
741 
742         ***********************************************************************/
743 
744         @property static char[] hostName ()
745         {
746                 char[64] name;
747 
748                 if(Error == .gethostname (name.ptr, name.length))
749                    exception ("Unable to obtain host name: ");
750                 return name [0 .. strlen(name.ptr)].dup;
751         }
752 
753         /***********************************************************************
754 
755                 return the default host address (IPv4)
756 
757         ***********************************************************************/
758 
759         @property static uint hostAddress ()
760         {
761                 auto ih = new NetHost;
762                 ih.getHostByName (hostName);
763                 assert (ih.addrList.length);
764                 return ih.addrList[0];
765         }
766 
767         /***********************************************************************
768 
769                 return the remote address of the current connection (IPv4)
770 
771         ***********************************************************************/
772 
773         @property const Address remoteAddress ()
774         {
775                 auto addr = newFamilyObject();
776                 auto nameLen = addr.nameLen;
777                 if(Error == .getpeername (sock, addr.name, &nameLen))
778                    exception ("Unable to obtain remote socket address: ");
779                 assert (addr.addressFamily is family);
780                 return addr;
781         }
782 
783         /***********************************************************************
784 
785                 return the local address of the current connection (IPv4)
786 
787         ***********************************************************************/
788 
789         @property const Address localAddress ()
790         {
791                 auto addr = newFamilyObject();
792                 auto nameLen = addr.nameLen;
793                 if(Error == .getsockname (sock, addr.name, &nameLen))
794                    exception ("Unable to obtain local socket address: ");
795                 assert (addr.addressFamily is family);
796                 return addr;
797         }
798 
799         /***********************************************************************
800 
801                 Send data on the connection. Returns the number of bytes
802                 actually sent, or ERROR on failure. If the socket is blocking
803                 and there is no buffer space left, send waits.
804 
805                 Returns number of bytes actually sent, or -1 on error
806 
807         ***********************************************************************/
808 
809         const int send (const(void)[] buf, SocketFlags flags=SocketFlags.NONE)
810         {
811                 if (buf.length is 0)
812                     return 0;
813 
814                 version (Posix)
815                         {
816                         auto ret = .send (sock, buf.ptr, buf.length,
817                                           SocketFlags.NOSIGNAL + cast(int) flags);
818                         if (errno is EPIPE)
819                             ret = -1;
820                         return ret;
821                         }
822                      else
823                         return .send (sock, buf.ptr, buf.length, cast(int) flags);
824         }
825 
826         /***********************************************************************
827 
828                 Send data to a specific destination Address. If the
829                 destination address is not specified, a connection
830                 must have been made and that address is used. If the
831                 socket is blocking and there is no buffer space left,
832                 sendTo waits.
833 
834         ***********************************************************************/
835 
836         const int sendTo (const(void)[] buf, SocketFlags flags, Address to)
837         {
838                 return sendTo (buf, cast(int) flags, to.name, to.nameLen);
839         }
840 
841         /***********************************************************************
842 
843                 ditto
844 
845         ***********************************************************************/
846 
847         const int sendTo (const(void)[] buf, Address to)
848         {
849                 return sendTo (buf, SocketFlags.NONE, to);
850         }
851 
852         /***********************************************************************
853 
854                 ditto - assumes you connect()ed
855 
856         ***********************************************************************/
857 
858         const int sendTo (const(void)[] buf, SocketFlags flags=SocketFlags.NONE)
859         {
860                 return sendTo (buf, cast(int) flags, null, 0);
861         }
862 
863         /***********************************************************************
864 
865                 Send data to a specific destination Address. If the
866                 destination address is not specified, a connection
867                 must have been made and that address is used. If the
868                 socket is blocking and there is no buffer space left,
869                 sendTo waits.
870 
871         ***********************************************************************/
872 
873         private const int sendTo (const(void)[] buf, int flags, Address.sockaddr* to, int len)
874         {
875                 if (buf.length is 0)
876                     return 0;
877 
878                 version (Posix)
879                         {
880                         auto ret = .sendto (sock, buf.ptr, buf.length,
881                                             flags | SocketFlags.NOSIGNAL, to, len);
882                         if (errno is EPIPE)
883                             ret = -1;
884                         return ret;
885                         }
886                      else
887                         return .sendto (sock, buf.ptr, buf.length, flags, to, len);
888         }
889 
890         /***********************************************************************
891                 Receive data on the connection. Returns the number of
892                 bytes actually received, 0 if the remote side has closed
893                 the connection, or ERROR on failure. If the socket is blocking,
894                 receive waits until there is data to be received.
895 
896                 Returns number of bytes actually received, 0 on connection
897                 closure, or -1 on error
898 
899         ***********************************************************************/
900 
901         const int receive (void[] buf, SocketFlags flags=SocketFlags.NONE)
902         {
903                 if (!buf.length)
904                      badArg ("Socket.receive :: target buffer has 0 length");
905 
906                 return .recv(sock, buf.ptr, buf.length, cast(int)flags);
907         }
908 
909         /***********************************************************************
910 
911                 Receive data and get the remote endpoint Address. Returns
912                 the number of bytes actually received, 0 if the remote side
913                 has closed the connection, or ERROR on failure. If the socket
914                 is blocking, receiveFrom waits until there is data to be
915                 received.
916 
917         ***********************************************************************/
918 
919         const int receiveFrom (void[] buf, SocketFlags flags, Address from)
920         {
921                 if (!buf.length)
922                      badArg ("Socket.receiveFrom :: target buffer has 0 length");
923 
924                 assert(from.addressFamily() == family);
925                 int nameLen = from.nameLen();
926                 return .recvfrom(sock, buf.ptr, buf.length, cast(int)flags, from.name(), &nameLen);
927         }
928 
929         /***********************************************************************
930 
931                 ditto
932 
933         ***********************************************************************/
934 
935         const int receiveFrom (void[] buf, Address from)
936         {
937                 return receiveFrom(buf, SocketFlags.NONE, from);
938         }
939 
940         /***********************************************************************
941 
942                 ditto - assumes you connect()ed
943 
944         ***********************************************************************/
945 
946         const int receiveFrom (void[] buf, SocketFlags flags = SocketFlags.NONE)
947         {
948                 if (!buf.length)
949                      badArg ("Socket.receiveFrom :: target buffer has 0 length");
950 
951                 return .recvfrom(sock, buf.ptr, buf.length, cast(int)flags, null, null);
952         }
953 
954         /***********************************************************************
955 
956                 returns the length, in bytes, of the actual result - very
957                 different from getsockopt()
958 
959         ***********************************************************************/
960 
961         const int getOption (SocketOptionLevel level, SocketOption option, void[] result)
962         {
963                 int len = cast(int) result.length;
964                 if(Error == .getsockopt (sock, cast(int)level, cast(int)option, result.ptr, &len))
965                    exception ("Unable to get socket option: ");
966                 return len;
967         }
968 
969         /***********************************************************************
970 
971         ***********************************************************************/
972 
973         Berkeley* setOption (SocketOptionLevel level, SocketOption option, const(void)[] value)
974         {
975                 if(Error == .setsockopt (sock, cast(int)level, cast(int)option, value.ptr, cast(int) value.length))
976                    exception ("Unable to set socket option: ");
977                 return &this;
978         }
979 
980         /***********************************************************************
981 
982                 getter
983 
984         ***********************************************************************/
985 
986         @property const bool blocking()
987         {
988                 version (Windows)
989                          return synchronous;
990                 else
991                    return !(fcntl(sock, F_GETFL, 0) & O_NONBLOCK);
992         }
993 
994         /***********************************************************************
995 
996                 setter
997 
998         ***********************************************************************/
999 
1000         @property void blocking(bool yes)
1001         {
1002                 version (Windows)
1003                         {
1004                         uint num = !yes;
1005                         if(ioctlsocket(sock, consts.FIONBIO, &num) is ERROR)
1006                            exception("Unable to set socket blocking: ");
1007                         synchronous = yes;
1008                         }
1009                      else
1010                         {
1011                         int x = fcntl(sock, F_GETFL, 0);
1012                         if(yes)
1013                            x &= ~O_NONBLOCK;
1014                         else
1015                            x |= O_NONBLOCK;
1016                         if(fcntl(sock, F_SETFL, x) is ERROR)
1017                            exception("Unable to set socket blocking: ");
1018                         }
1019                 return;
1020         }
1021 
1022         /***********************************************************************
1023 
1024         ***********************************************************************/
1025 
1026         static void exception (immutable(char)[] msg)
1027         {
1028                 throw new SocketException (msg ~ SysError.lookup(lastError).idup);
1029         }
1030 
1031         /***********************************************************************
1032 
1033         ***********************************************************************/
1034 
1035         protected static void badArg (immutable(char)[] msg)
1036         {
1037                 throw new IllegalArgumentException (msg);
1038         }
1039 }
1040 
1041 
1042 
1043 /*******************************************************************************
1044 
1045 
1046 *******************************************************************************/
1047 
1048 public abstract class Address
1049 {
1050         public struct sockaddr
1051         {
1052                 ushort   sa_family;
1053                 char[14] sa_data = 0;
1054         }
1055 
1056         struct addrinfo
1057         {
1058                 int       ai_flags;
1059                 int       ai_family;
1060                 int       ai_socktype;
1061                 int       ai_protocol;
1062                 uint      ai_addrlen;
1063                 version (FreeBSD)
1064                         {
1065                         char*     ai_canonname;
1066                         sockaddr* ai_addr;
1067                         }
1068                      else
1069                         {
1070                         sockaddr* ai_addr;
1071                         char*     ai_canonname;
1072                         }
1073                 addrinfo* ai_next;
1074         }
1075 
1076         @property abstract sockaddr* name();
1077         @property abstract const int nameLen();
1078 
1079         /***********************************************************************
1080 
1081                 Internal usage
1082 
1083         ***********************************************************************/
1084 
1085         private static ushort ntohs (ushort x)
1086         {
1087                 return htons(x);
1088         }
1089 
1090         /***********************************************************************
1091 
1092                 Internal usage
1093 
1094         ***********************************************************************/
1095 
1096         private static uint ntohl (uint x)
1097         {
1098                 return htonl(x);
1099         }
1100 
1101         /***********************************************************************
1102 
1103                 Internal usage
1104 
1105         ***********************************************************************/
1106 
1107         private static char[] fromInt (char[] tmp, int i)
1108         {
1109                 size_t j = tmp.length;
1110                 do {
1111                    tmp[--j] = cast(char)(i % 10 + '0');
1112                    } while (i /= 10);
1113                 return tmp [j .. $];
1114         }
1115 
1116         /***********************************************************************
1117 
1118                 Internal usage
1119 
1120         ***********************************************************************/
1121 
1122         private static int toInt (const(char)[] s)
1123         {
1124                 uint value;
1125 
1126                 foreach (c; s)
1127                          if (c >= '0' && c <= '9')
1128                              value = value * 10 + (c - '0');
1129                          else
1130                             break;
1131                 return value;
1132         }
1133 
1134         /***********************************************************************
1135 
1136                 Tango: added this common function
1137 
1138         ***********************************************************************/
1139 
1140         static void exception (immutable(char)[] msg)
1141         {
1142                 throw new SocketException (msg);
1143         }
1144 
1145         /***********************************************************************
1146 
1147                 Address factory
1148 
1149         ***********************************************************************/
1150 
1151         static Address create (sockaddr* sa)
1152         {
1153                 switch  (sa.sa_family)
1154                         {
1155                         case AddressFamily.INET:
1156                              return new IPv4Address(sa);
1157                         case AddressFamily.INET6:
1158                              return new IPv6Address(sa);
1159                         default:
1160                              return null;
1161                         }
1162         }
1163 
1164         /***********************************************************************
1165 
1166         ***********************************************************************/
1167 
1168         static Address resolve (const(char)[] host, const(char)[] service = null,
1169                                 AddressFamily af = AddressFamily.UNSPEC,
1170                                 AIFlags flags = cast(AIFlags)0)
1171         {
1172                 return resolveAll (host, service, af, flags)[0];
1173         }
1174 
1175         /***********************************************************************
1176 
1177         ***********************************************************************/
1178 
1179         static Address resolve (const(char)[] host, ushort port,
1180                                 AddressFamily af = AddressFamily.UNSPEC,
1181                                 AIFlags flags = cast(AIFlags)0)
1182         {
1183                 return resolveAll (host, port, af, flags)[0];
1184         }
1185 
1186         /***********************************************************************
1187 
1188         ***********************************************************************/
1189 
1190         static Address[] resolveAll (const(char)[] host, const(char)[] service = null,
1191                                      AddressFamily af = AddressFamily.UNSPEC,
1192                                      AIFlags flags = cast(AIFlags)0)
1193         {
1194                 Address[] retVal;
1195                 version (Win32)
1196                         {
1197                         if (!getaddrinfo)
1198                            { // *old* windows, let's fall back to NetHost
1199                            uint port = toInt(service);
1200                            if (flags & AIFlags.PASSIVE && host is null)
1201                                return [new IPv4Address(0, cast(ushort)port)];
1202 
1203                            auto nh = new NetHost;
1204                            if (!nh.getHostByName(host))
1205                                 throw new AddressException("couldn't resolve " ~ host.idup);
1206 
1207                            retVal.length = nh.addrList.length;
1208                            foreach (i, addr; nh.addrList)
1209                                     retVal[i] = new IPv4Address(addr, cast(ushort)port);
1210                            return retVal;
1211                            }
1212                         }
1213 
1214                 addrinfo* info;
1215                 addrinfo hints;
1216                 hints.ai_flags = flags;
1217                 hints.ai_family = (flags & AIFlags.PASSIVE && af == AddressFamily.UNSPEC) ? AddressFamily.INET6 : af;
1218                 hints.ai_socktype = SocketType.STREAM;
1219                 int error = getaddrinfo(toStringz(host), service.length == 0 ? null : toStringz(service), &hints, &info);
1220                 if (error != 0)
1221                     throw new AddressException("couldn't resolve " ~ host.idup);
1222 
1223                 retVal.length = 16;
1224                 retVal.length = 0;
1225                 while (info)
1226                       {
1227                       if (auto addr = create(info.ai_addr))
1228                           retVal ~= addr;
1229                       info = info.ai_next;
1230                       }
1231                 freeaddrinfo (info);
1232                 return retVal;
1233         }
1234 
1235         /***********************************************************************
1236 
1237         ***********************************************************************/
1238 
1239         static Address[] resolveAll (const(char)[] host, ushort port,
1240                                      AddressFamily af = AddressFamily.UNSPEC,
1241                                      AIFlags flags = cast(AIFlags)0)
1242         {
1243                 char[16] buf;
1244                 return resolveAll (host, fromInt(buf, port), af, flags);
1245         }
1246 
1247         /***********************************************************************
1248 
1249         ***********************************************************************/
1250 
1251         static Address passive (const(char)[] service,
1252                                 AddressFamily af = AddressFamily.UNSPEC,
1253                                 AIFlags flags = cast(AIFlags)0)
1254         {
1255                 return resolve (null, service, af, flags | AIFlags.PASSIVE);
1256         }
1257 
1258         /***********************************************************************
1259 
1260          ***********************************************************************/
1261 
1262         static Address passive (ushort port, AddressFamily af = AddressFamily.UNSPEC,
1263                                 AIFlags flags = cast(AIFlags)0)
1264         {
1265                 return resolve (null, port, af, flags | AIFlags.PASSIVE);
1266         }
1267 
1268         /***********************************************************************
1269 
1270         ***********************************************************************/
1271 
1272         @property char[] toAddrString()
1273         {
1274                 char[1025] host = void;
1275                 // Getting name info. Don't look up hostname, returns
1276                 // numeric name. (NIFlags.NUMERICHOST)
1277                 getnameinfo (name, nameLen, host.ptr, host.length, null, 0, NIFlags.NUMERICHOST);
1278                 return fromStringz (host.ptr).dup;
1279         }
1280 
1281         /***********************************************************************
1282 
1283          ***********************************************************************/
1284 
1285         @property char[] toPortString()
1286         {
1287                 char[32] service = void;
1288                 // Getting name info. Returns port number, not
1289                 // service name. (NIFlags.NUMERICSERV)
1290                 getnameinfo (name, nameLen, null, 0, service.ptr, service.length, NIFlags.NUMERICSERV);
1291                 foreach (i, c; service)
1292                          if (c == '\0')
1293                              return service[0..i].dup;
1294                 return null;
1295         }
1296 
1297         /***********************************************************************
1298 
1299         ***********************************************************************/
1300 
1301         override string toString()
1302         {
1303                 return toAddrString.idup ~ ":" ~ toPortString.idup;
1304         }
1305 
1306         /***********************************************************************
1307 
1308          ***********************************************************************/
1309 
1310         @property AddressFamily addressFamily()
1311         {
1312                 return cast(AddressFamily)name.sa_family;
1313         }
1314 }
1315 
1316 
1317 /*******************************************************************************
1318 
1319 *******************************************************************************/
1320 
1321 public class UnknownAddress : Address
1322 {
1323         sockaddr sa;
1324 
1325         /***********************************************************************
1326 
1327         ***********************************************************************/
1328 
1329         @property override sockaddr* name()
1330         {
1331                 return &sa;
1332         }
1333 
1334         /***********************************************************************
1335 
1336         ***********************************************************************/
1337 
1338         @property override const int nameLen()
1339         {
1340                 return sa.sizeof;
1341         }
1342 
1343         /***********************************************************************
1344 
1345         ***********************************************************************/
1346 
1347         @property override AddressFamily addressFamily()
1348         {
1349                 return cast(AddressFamily) sa.sa_family;
1350         }
1351 
1352         /***********************************************************************
1353 
1354         ***********************************************************************/
1355 
1356         override string toString()
1357         {
1358                 return "Unknown";
1359         }
1360 }
1361 
1362 
1363 /*******************************************************************************
1364 
1365 
1366 *******************************************************************************/
1367 
1368 public class IPv4Address : Address
1369 {
1370         /***********************************************************************
1371 
1372         ***********************************************************************/
1373 
1374         enum
1375         {
1376                 ADDR_ANY = 0,
1377                 ADDR_NONE = cast(uint)-1,
1378                 PORT_ANY = 0
1379         }
1380 
1381         /***********************************************************************
1382 
1383         ***********************************************************************/
1384 
1385         struct sockaddr_in
1386         {
1387                 version (FreeBSD)
1388                         {
1389                         ubyte sin_len;
1390                         ubyte sinfamily  = AddressFamily.INET;
1391                         }
1392                      else
1393                         {
1394                         ushort sinfamily = AddressFamily.INET;
1395                         }
1396                 ushort sin_port;
1397                 uint sin_addr; //in_addr
1398                 char[8] sin_zero = 0;
1399         }
1400 
1401         static assert(sockaddr_in.sizeof is 16);
1402 
1403         private sockaddr_in sin;
1404 
1405         /***********************************************************************
1406 
1407         ***********************************************************************/
1408 
1409         protected this ()
1410         {
1411         }
1412 
1413         /***********************************************************************
1414 
1415         ***********************************************************************/
1416 
1417         this (ushort port)
1418         {
1419                 sin.sin_addr = 0; //any, "0.0.0.0"
1420                 sin.sin_port = htons(port);
1421         }
1422 
1423         /***********************************************************************
1424 
1425         ***********************************************************************/
1426 
1427         this (uint addr, ushort port)
1428         {
1429                 sin.sin_addr = htonl(addr);
1430                 sin.sin_port = htons(port);
1431         }
1432 
1433         /***********************************************************************
1434 
1435                 -port- can be PORT_ANY
1436                 -addr- is an IP address or host name
1437 
1438         ***********************************************************************/
1439 
1440         this (const(char)[] addr, ushort port = PORT_ANY)
1441         {
1442                 uint uiaddr = parse(addr);
1443                 if (ADDR_NONE == uiaddr)
1444                    {
1445                    auto ih = new NetHost;
1446                    if (!ih.getHostByName(addr))
1447                       {
1448                       char[16] tmp = void;
1449                       exception ("Unable to resolve "~addr.idup~":"~fromInt(tmp, port).idup);
1450                       }
1451                    uiaddr = ih.addrList[0];
1452                    }
1453                 sin.sin_addr = htonl(uiaddr);
1454                 sin.sin_port = htons(port);
1455         }
1456 
1457         /***********************************************************************
1458 
1459         ***********************************************************************/
1460 
1461         this (sockaddr* addr)
1462         {
1463                 sin = *(cast(sockaddr_in*)addr);
1464         }
1465 
1466         /***********************************************************************
1467 
1468         ***********************************************************************/
1469 
1470         @property override sockaddr* name()
1471         {
1472                 return cast(sockaddr*)&sin;
1473         }
1474 
1475         /***********************************************************************
1476 
1477         ***********************************************************************/
1478 
1479         @property override const int nameLen()
1480         {
1481                 return cast(int)sin.sizeof;
1482         }
1483 
1484         /***********************************************************************
1485 
1486         ***********************************************************************/
1487 
1488         @property override AddressFamily addressFamily()
1489         {
1490                 return AddressFamily.INET;
1491         }
1492 
1493         /***********************************************************************
1494 
1495         ***********************************************************************/
1496 
1497         @property const ushort port()
1498         {
1499                 return ntohs(sin.sin_port);
1500         }
1501 
1502         /***********************************************************************
1503 
1504         ***********************************************************************/
1505 
1506         @property const uint addr()
1507         {
1508                 return ntohl(sin.sin_addr);
1509         }
1510 
1511         /***********************************************************************
1512 
1513         ***********************************************************************/
1514 
1515         @property override const char[] toAddrString()
1516         {
1517                 char[16] buff = 0;
1518                 version (Windows)
1519                          return fromStringz(inet_ntoa(sin.sin_addr)).dup;
1520                 else
1521                    return fromStringz(inet_ntop(AddressFamily.INET, &sin.sin_addr, buff.ptr, 16)).dup;
1522         }
1523 
1524         /***********************************************************************
1525 
1526         ***********************************************************************/
1527 
1528         @property override const char[] toPortString()
1529         {
1530                 char[8] _port;
1531                 return fromInt (_port, port()).dup;
1532         }
1533 
1534         /***********************************************************************
1535 
1536         ***********************************************************************/
1537 
1538         override string toString()
1539         {
1540                 return toAddrString().idup ~ ":" ~ toPortString().idup;
1541         }
1542 
1543         /***********************************************************************
1544 
1545                 -addr- is an IP address in the format "a.b.c.d"
1546                 returns ADDR_NONE on failure
1547 
1548         ***********************************************************************/
1549 
1550         static uint parse(const(char)[] addr)
1551         {
1552                 char[64] tmp;
1553 
1554                 synchronized (IPv4Address.classinfo)
1555                               return ntohl(inet_addr(toStringz(addr, tmp)));
1556         }
1557 }
1558 
1559 /*******************************************************************************
1560 
1561 *******************************************************************************/
1562 
1563 debug(UnitTest)
1564 {
1565         unittest
1566         {
1567         IPv4Address ia = new IPv4Address("63.105.9.61", 80);
1568         assert(ia.toString() == "63.105.9.61:80");
1569         }
1570 }
1571 
1572 /*******************************************************************************
1573 
1574         IPv6 is the next-generation Internet Protocol version
1575         designated as the successor to IPv4, the first
1576         implementation used in the Internet that is still in
1577         dominant use currently.
1578 
1579         More information: http://ipv6.com/
1580 
1581         IPv6 supports 128-bit address space as opposed to 32-bit
1582         address space of IPv4.
1583 
1584         IPv6 is written as 8 blocks of 4 octal digits (16 bit)
1585         separated by a colon (":"). Zero block can be replaced by "::".
1586 
1587         For example:
1588         ---
1589         0000:0000:0000:0000:0000:0000:0000:0001
1590         is equal
1591         ::0001
1592         is equal
1593         ::1
1594         is analogue IPv4 127.0.0.1
1595 
1596         0000:0000:0000:0000:0000:0000:0000:0000
1597         is equal
1598         ::
1599         is analogue IPv4 0.0.0.0
1600 
1601         2001:cdba:0000:0000:0000:0000:3257:9652
1602         is equal
1603         2001:cdba::3257:9652
1604 
1605         IPv4 address can be submitted through IPv6 as ::ffff:xx.xx.xx.xx,
1606         where xx.xx.xx.xx 32-bit IPv4 addresses.
1607 
1608         ::ffff:51b0:ec6d
1609         is equal
1610         ::ffff:81.176.236.109
1611         is analogue IPv4 81.176.236.109
1612 
1613         The URL for the IPv6 address will be of the form:
1614         http://[2001:cdba:0000:0000:0000:0000:3257:9652]/
1615 
1616         If needed to specify a port, it will be listed after the
1617         closing square bracket followed by a colon.
1618 
1619         http://[2001:cdba:0000:0000:0000:0000:3257:9652]:8080/
1620         address: "2001:cdba:0000:0000:0000:0000:3257:9652"
1621         port: 8080
1622 
1623         IPv6Address can be used as well as IPv4Address.
1624 
1625         scope addr = new IPv6Address(8080);
1626         address: "::"
1627         port: 8080
1628 
1629         scope addr_2 = new IPv6Address("::1", 8081);
1630         address: "::1"
1631         port: 8081
1632 
1633         scope addr_3 = new IPv6Address("::1");
1634         address: "::1"
1635         port: PORT_ANY
1636 
1637         Also in the IPv6Address constructor can specify the service name
1638         or port as string
1639 
1640         scope addr_3 = new IPv6Address("::", "ssh");
1641         address: "::"
1642         port: 22 (ssh service port)
1643 
1644         scope addr_4 = new IPv6Address("::", "8080");
1645         address: "::"
1646         port: 8080
1647         ---
1648 
1649 *******************************************************************************/
1650 
1651 class IPv6Address : Address
1652 {
1653 protected:
1654         /***********************************************************************
1655 
1656         ***********************************************************************/
1657 
1658         struct sockaddr_in6
1659         {
1660                 ushort sin_family;
1661                 ushort sin_port;
1662 
1663                 uint sin6_flowinfo;
1664                 ubyte[16] sin6_addr;
1665                 uint sin6_scope_id;
1666         }
1667 
1668         sockaddr_in6 sin;
1669 
1670         /***********************************************************************
1671 
1672          ***********************************************************************/
1673 
1674         this ()
1675         {
1676         }
1677 
1678         /***********************************************************************
1679 
1680         ***********************************************************************/
1681 
1682         this (sockaddr* sa)
1683         {
1684                 sin = *cast(sockaddr_in6*)sa;
1685         }
1686 
1687         /***********************************************************************
1688 
1689         ***********************************************************************/
1690 
1691         @property override sockaddr* name()
1692         {
1693                 return cast(sockaddr*)&sin;
1694         }
1695 
1696         /***********************************************************************
1697 
1698         ***********************************************************************/
1699 
1700         @property override const int nameLen()
1701         {
1702                 return cast(int)sin.sizeof;
1703         }
1704 
1705  public:
1706 
1707         /***********************************************************************
1708 
1709         ***********************************************************************/
1710 
1711        @property override AddressFamily addressFamily()
1712         {
1713                 return AddressFamily.INET6;
1714         }
1715 
1716 
1717         enum ushort PORT_ANY = 0;
1718 
1719         /***********************************************************************
1720 
1721          ***********************************************************************/
1722 
1723         @property const ushort port()
1724         {
1725                 return ntohs(sin.sin_port);
1726         }
1727 
1728         /***********************************************************************
1729 
1730                 Create IPv6Address with zero address
1731 
1732         ***********************************************************************/
1733 
1734         this (int port)
1735         {
1736           this ("::", port);
1737         }
1738 
1739         /***********************************************************************
1740 
1741                 -port- can be PORT_ANY
1742                 -addr- is an IP address or host name
1743 
1744         ***********************************************************************/
1745 
1746         this (const(char)[] addr, int port = PORT_ANY)
1747         {
1748                 version (Win32)
1749                         {
1750                         if (!getaddrinfo)
1751                              exception ("This platform does not support IPv6.");
1752                         }
1753                 addrinfo* info;
1754                 addrinfo hints;
1755                 hints.ai_family = AddressFamily.INET6;
1756                 int error = getaddrinfo((addr ~ '\0').ptr, null, &hints, &info);
1757                 if (error != 0)
1758                     exception("failed to create IPv6Address: ");
1759 
1760                 sin = *cast(sockaddr_in6*)(info.ai_addr);
1761                 sin.sin_port = htons(cast(ushort) port);
1762         }
1763 
1764         /***********************************************************************
1765 
1766                 -service- can be a port number or service name
1767                 -addr- is an IP address or host name
1768 
1769         ***********************************************************************/
1770 
1771         this (const(char)[] addr, const(char)[] service)
1772         {
1773                 version (Win32)
1774                         {
1775                         if(! getaddrinfo)
1776                              exception ("This platform does not support IPv6.");
1777                         }
1778                 addrinfo* info;
1779                 addrinfo hints;
1780                 hints.ai_family = AddressFamily.INET6;
1781                 int error = getaddrinfo((addr ~ '\0').ptr, (service ~ '\0').ptr, &hints, &info);
1782                 if (error != 0)
1783                     exception ("failed to create IPv6Address: ");
1784                 sin = *cast(sockaddr_in6*)(info.ai_addr);
1785         }
1786 
1787         /***********************************************************************
1788 
1789         ***********************************************************************/
1790 
1791         @property ubyte[] addr()
1792         {
1793                 return sin.sin6_addr;
1794         }
1795 
1796         /***********************************************************************
1797 
1798         ***********************************************************************/
1799 
1800         version (Posix)
1801         @property override const char[] toAddrString()
1802         {
1803 
1804                 char[100] buff = 0;
1805                 return fromStringz(inet_ntop(AddressFamily.INET6, &sin.sin6_addr, buff.ptr, 100)).dup;
1806         }
1807 
1808         /***********************************************************************
1809 
1810         ***********************************************************************/
1811 
1812         @property override const char[] toPortString()
1813         {
1814                 char[8] _port;
1815                 return fromInt (_port, port()).dup;
1816         }
1817 
1818         /***********************************************************************
1819 
1820         ***********************************************************************/
1821 
1822         override string toString()
1823         {
1824                 return "[" ~ toAddrString.idup ~ "]:" ~ toPortString.idup;
1825         }
1826 }
1827 
1828 /*******************************************************************************
1829 
1830 *******************************************************************************/
1831 
1832 debug(UnitTest)
1833 {
1834         unittest
1835         {
1836         IPv6Address ia = new IPv6Address("7628:0d18:11a3:09d7:1f34:8a2e:07a0:765d", 8080);
1837         assert(ia.toString() == "[7628:d18:11a3:9d7:1f34:8a2e:7a0:765d]:8080");
1838         //assert(ia.toString() == "[7628:0d18:11a3:09d7:1f34:8a2e:07a0:765d]:8080");
1839         }
1840 }
1841 
1842 
1843 /*******************************************************************************
1844 
1845 
1846 *******************************************************************************/
1847 
1848 public class NetHost
1849 {
1850         const(char)[]          name;
1851         const(char)[][]        aliases;
1852         uint[]          addrList;
1853 
1854         /***********************************************************************
1855 
1856         ***********************************************************************/
1857 
1858         struct hostent
1859         {
1860                 const(char)* h_name;
1861                 const(char)** h_aliases;
1862                 version (Win32)
1863                         {
1864                         short h_addrtype;
1865                         short h_length;
1866                         }
1867                      else
1868                         {
1869                         int h_addrtype;
1870                         int h_length;
1871                         }
1872                 const(char)** h_addr_list;
1873 
1874                 const(char)* h_addr()
1875                 {
1876                         return h_addr_list[0];
1877                 }
1878         }
1879 
1880         /***********************************************************************
1881 
1882         ***********************************************************************/
1883 
1884         protected void validHostent(hostent* he)
1885         {
1886                 if (he.h_addrtype != AddressFamily.INET || he.h_length != 4)
1887                     throw new SocketException("Address family mismatch.");
1888         }
1889 
1890         /***********************************************************************
1891 
1892         ***********************************************************************/
1893 
1894         void populate (hostent* he)
1895         {
1896                 int i;
1897                 const(char)* p;
1898 
1899                 name = fromStringz(he.h_name);
1900 
1901                 for (i = 0;; i++)
1902                     {
1903                     p = he.h_aliases[i];
1904                     if(!p)
1905                         break;
1906                     }
1907 
1908                 if (i)
1909                    {
1910                    aliases = new const(char)[][i];
1911                    for (i = 0; i != aliases.length; i++)
1912                         aliases[i] = fromStringz(he.h_aliases[i]);
1913                    }
1914                 else
1915                    aliases = null;
1916 
1917                 for (i = 0;; i++)
1918                     {
1919                     p = he.h_addr_list[i];
1920                     if(!p)
1921                         break;
1922                     }
1923 
1924                 if (i)
1925                    {
1926                    addrList = new uint[i];
1927                    for (i = 0; i != addrList.length; i++)
1928                         addrList[i] = Address.ntohl(*(cast(uint*)he.h_addr_list[i]));
1929                    }
1930                 else
1931                    addrList = null;
1932         }
1933 
1934         /***********************************************************************
1935 
1936         ***********************************************************************/
1937 
1938         bool getHostByName(const(char)[] name)
1939         {
1940                 char[1024] tmp;
1941 
1942                 synchronized (NetHost.classinfo)
1943                              {
1944                              auto he = gethostbyname(toStringz(name, tmp));
1945                              if(!he)
1946                                 return false;
1947                              validHostent(he);
1948                              populate(he);
1949                              }
1950                 return true;
1951         }
1952 
1953         /***********************************************************************
1954 
1955         ***********************************************************************/
1956 
1957         bool getHostByAddr(uint addr)
1958         {
1959                 uint x = htonl(addr);
1960                 synchronized (NetHost.classinfo)
1961                              {
1962                              auto he = gethostbyaddr(&x, 4, cast(int)AddressFamily.INET);
1963                              if(!he)
1964                                  return false;
1965                              validHostent(he);
1966                              populate(he);
1967                              }
1968                 return true;
1969         }
1970 
1971         /***********************************************************************
1972 
1973         ***********************************************************************/
1974 
1975         //shortcut
1976         bool getHostByAddr(const(char)[] addr)
1977         {
1978                 char[64] tmp;
1979 
1980                 synchronized (NetHost.classinfo)
1981                              {
1982                              uint x = inet_addr(toStringz(addr, tmp));
1983                              auto he = gethostbyaddr(&x, 4, cast(int)AddressFamily.INET);
1984                              if(!he)
1985                                  return false;
1986                              validHostent(he);
1987                              populate(he);
1988                              }
1989                 return true;
1990         }
1991 }
1992 
1993 
1994 /*******************************************************************************
1995 
1996 *******************************************************************************/
1997 
1998 debug (UnitTest)
1999 {
2000         import tango.io.Stdout;
2001         unittest
2002         {
2003         NetHost ih = new NetHost;
2004         ih.getHostByName(Berkeley.hostName());
2005         assert(ih.addrList.length > 0);
2006         IPv4Address ia = new IPv4Address(ih.addrList[0], IPv4Address.PORT_ANY);
2007         Stdout.formatln("addrses: {} {}\n", ia.toAddrString, ih.name);
2008         Stdout.formatln("IP address = {}\nname = {}\n", ia.toAddrString(), ih.name);
2009         foreach(int i, const(char)[] s; ih.aliases)
2010         {
2011                 Stdout.formatln("aliases[%d] = {}\n", i, s);
2012         }
2013 
2014         Stdout("---\n");
2015 
2016         assert(ih.getHostByAddr(ih.addrList[0]));
2017         Stdout.formatln("name = {}\n", ih.name);
2018         foreach(int i, const(char)[] s; ih.aliases)
2019         {
2020                 Stdout.formatln("aliases[{}] = {}\n", i, s);
2021         }
2022         }
2023 }
2024 
2025 
2026 /*******************************************************************************
2027 
2028         a set of sockets for Berkeley.select()
2029 
2030 *******************************************************************************/
2031 
2032 public class SocketSet
2033 {
2034         import tango.stdc.config;
2035 
2036         struct timeval
2037         {
2038                 c_long  seconds, microseconds;
2039         }
2040 
2041         private size_t  nbytes; //Win32: excludes uint.size "count"
2042         private byte* buf;
2043 
2044         struct fd {}
2045 
2046         version(Windows)
2047         {
2048                 @property uint count()
2049                 {
2050                         return *(cast(uint*)buf);
2051                 }
2052 
2053                 @property void count(int setter)
2054                 {
2055                         *(cast(uint*)buf) = setter;
2056                 }
2057 
2058 
2059                 @property socket_t* first()
2060                 {
2061                         return cast(socket_t*)(buf + uint.sizeof);
2062                 }
2063         }
2064         else version (Posix)
2065         {
2066                 import tango.core.BitManip;
2067 
2068                 size_t nfdbits;
2069                 socket_t _maxfd = cast(socket_t)0;
2070 
2071                 const uint fdelt(socket_t s)
2072                 {
2073                         return cast(uint)(s / nfdbits);
2074                 }
2075 
2076 
2077                 const uint fdmask(socket_t s)
2078                 {
2079                         return 1 << cast(uint)(s % nfdbits);
2080                 }
2081 
2082 
2083                 @property uint* first()
2084                 {
2085                         return cast(uint*)buf;
2086                 }
2087 
2088                 @property public socket_t maxfd()
2089                 {
2090                         return _maxfd;
2091                 }
2092         }
2093 
2094 
2095         public:
2096 
2097         this (uint max)
2098         {
2099                 version(Win32)
2100                 {
2101                         nbytes = max * socket_t.sizeof;
2102                         buf = (new byte[nbytes + uint.sizeof]).ptr;
2103                         count = 0;
2104                 }
2105                 else version (Posix)
2106                 {
2107                         if (max <= 32)
2108                             nbytes = 32 * uint.sizeof;
2109                         else
2110                            nbytes = max * uint.sizeof;
2111 
2112                         buf = (new byte[nbytes]).ptr;
2113                         nfdbits = nbytes * 8;
2114                         //clear(); //new initializes to 0
2115                 }
2116                 else
2117                 {
2118                         static assert(0);
2119                 }
2120         }
2121 
2122         this (SocketSet o)
2123         {
2124                 nbytes = o.nbytes;
2125                 auto size = nbytes;
2126                 version (Win32)
2127                          size += uint.sizeof;
2128 
2129                 version (Posix)
2130                         {
2131                         nfdbits = o.nfdbits;
2132                         _maxfd = o._maxfd;
2133                         }
2134 
2135                 auto b = new byte[size];
2136                 b[] = o.buf[0..size];
2137                 buf = b.ptr;
2138         }
2139 
2140         this()
2141         {
2142                 version(Win32)
2143                 {
2144                         this(64);
2145                 }
2146                 else version (Posix)
2147                 {
2148                         this(32);
2149                 }
2150                 else
2151                 {
2152                         static assert(0);
2153                 }
2154         }
2155 
2156         SocketSet dup()
2157         {
2158                 return new SocketSet (this);
2159         }
2160 
2161         SocketSet reset()
2162         {
2163                 version(Win32)
2164                 {
2165                         count = 0;
2166                 }
2167                 else version (Posix)
2168                 {
2169                         buf[0 .. nbytes] = 0;
2170                         _maxfd = cast(socket_t)0;
2171                 }
2172                 else
2173                 {
2174                         static assert(0);
2175                 }
2176                 return this;
2177         }
2178 
2179         void add(socket_t s)
2180         in
2181         {
2182                 version(Win32)
2183                 {
2184                         assert(count < max); //added too many sockets; specify a higher max in the constructor
2185                 }
2186         }
2187         body
2188         {
2189                 version(Win32)
2190                 {
2191                         uint c = count;
2192                         first[c] = s;
2193                         count = c + 1;
2194                 }
2195                 else version (Posix)
2196                 {
2197                         if (s > _maxfd)
2198                                 _maxfd = s;
2199                         
2200                         bts(cast(size_t*)&first[fdelt(s)], cast(size_t)s % nfdbits);
2201                 }
2202                 else
2203                 {
2204                         static assert(0);
2205                 }
2206         }
2207 
2208         void add(Berkeley* s)
2209         {
2210                 add(s.handle);
2211         }
2212 
2213         void remove(socket_t s)
2214         {
2215                 version(Win32)
2216                 {
2217                         uint c = count;
2218                         socket_t* start = first;
2219                         socket_t* stop = start + c;
2220 
2221                         for(; start != stop; start++)
2222                         {
2223                                 if(*start == s)
2224                                         goto found;
2225                         }
2226                         return; //not found
2227 
2228                         found:
2229                         for(++start; start != stop; start++)
2230                         {
2231                                 *(start - 1) = *start;
2232                         }
2233 
2234                         count = c - 1;
2235                 }
2236                 else version (Posix)
2237                 {
2238                         btr(cast(size_t*)&first[fdelt(s)], cast(size_t)s % nfdbits);
2239 
2240                         // If we're removing the biggest file descriptor we've
2241                         // entered so far we need to recalculate this value
2242                         // for the socket set.
2243                         if (s == _maxfd)
2244                         {
2245                                 while (--_maxfd >= 0)
2246                                 {
2247                                         if (isSet(_maxfd))
2248                                         {
2249                                                 break;
2250                                         }
2251                                 }
2252                         }
2253                 }
2254                 else
2255                 {
2256                         static assert(0);
2257                 }
2258         }
2259 
2260         void remove(Berkeley* s)
2261         {
2262                 remove(s.handle);
2263         }
2264 
2265         int isSet(socket_t s)
2266         {
2267                 version(Win32)
2268                 {
2269                         socket_t* start = first;
2270                         socket_t* stop = start + count;
2271 
2272                         for(; start != stop; start++)
2273                         {
2274                                 if(*start == s)
2275                                         return true;
2276                         }
2277                         return false;
2278                 }
2279                 else version (Posix)
2280                 {
2281                         //return bt(cast(uint*)&first[fdelt(s)], cast(uint)s % nfdbits);
2282                         int index = cast(int)(cast(uint)s % nfdbits);
2283                         return (cast(uint*)&first[fdelt(s)])[index / (uint.sizeof*8)] & (1 << (index & ((uint.sizeof*8) - 1)));
2284                 }
2285                 else
2286                 {
2287                         static assert(0);
2288                 }
2289         }
2290 
2291         int isSet(Berkeley* s)
2292         {
2293                 return isSet(s.handle);
2294         }
2295 
2296         @property const size_t max()
2297         {
2298                 return nbytes / socket_t.sizeof;
2299         }
2300 
2301         fd* toFd_set()
2302         {
2303                 return cast(fd*)buf;
2304         }
2305 
2306         /***********************************************************************
2307 
2308                 SocketSet's are updated to include only those sockets which an
2309                 event occured.
2310 
2311                 Returns the number of events, 0 on timeout, or -1 on error
2312 
2313                 for a connect()ing socket, writeability means connected
2314                 for a listen()ing socket, readability means listening
2315 
2316                 Winsock: possibly internally limited to 64 sockets per set
2317 
2318         ***********************************************************************/
2319 
2320         static int select (SocketSet checkRead, SocketSet checkWrite, SocketSet checkError, timeval* tv)
2321         {
2322                 fd* fr, fw, fe;
2323 
2324                 //make sure none of the SocketSet's are the same object
2325                 if (checkRead)
2326                    {
2327                    assert(checkRead !is checkWrite);
2328                    assert(checkRead !is checkError);
2329                    }
2330 
2331                 if (checkWrite)
2332                     assert(checkWrite !is checkError);
2333 
2334                 version(Win32)
2335                 {
2336                         //Windows has a problem with empty fd_set's that aren't null
2337                         fr = (checkRead && checkRead.count()) ? checkRead.toFd_set() : null;
2338                         fw = (checkWrite && checkWrite.count()) ? checkWrite.toFd_set() : null;
2339                         fe = (checkError && checkError.count()) ? checkError.toFd_set() : null;
2340                 }
2341                 else
2342                 {
2343                         fr = checkRead ? checkRead.toFd_set() : null;
2344                         fw = checkWrite ? checkWrite.toFd_set() : null;
2345                         fe = checkError ? checkError.toFd_set() : null;
2346                 }
2347 
2348                 int result;
2349 
2350                 version(Win32)
2351                 {
2352                         while ((result = .select (socket_t.max - 1, fr, fw, fe, tv)) == -1)
2353                         {
2354                                 if(WSAGetLastError() != WSAEINTR)
2355                                    break;
2356                         }
2357                 }
2358                 else version (Posix)
2359                 {
2360                         socket_t maxfd = cast(socket_t)0;
2361 
2362                         if (checkRead)
2363                                 maxfd = checkRead.maxfd;
2364 
2365                         if (checkWrite && checkWrite.maxfd > maxfd)
2366                                 maxfd = checkWrite.maxfd;
2367 
2368                         if (checkError && checkError.maxfd > maxfd)
2369                                 maxfd = checkError.maxfd;
2370 
2371                         while ((result = .select (maxfd + 1, fr, fw, fe, tv)) == -1)
2372                         {
2373                                 if(errno() != EINTR)
2374                                    break;
2375                         }
2376                 }
2377                 else
2378                 {
2379                         static assert(0);
2380                 }
2381 
2382                 return result;
2383         }
2384 
2385         /***********************************************************************
2386 
2387                 select with specified timeout
2388 
2389         ***********************************************************************/
2390 
2391         static int select (SocketSet checkRead, SocketSet checkWrite, SocketSet checkError, long microseconds)
2392         {
2393                 timeval tv = {
2394                              cast(typeof(timeval.seconds)) (microseconds / 1000000),
2395                              cast(typeof(timeval.microseconds)) (microseconds % 1000000)
2396                              };
2397                 return select (checkRead, checkWrite, checkError, &tv);
2398         }
2399 
2400         /***********************************************************************
2401 
2402                 select with maximum timeout
2403 
2404         ***********************************************************************/
2405 
2406         static int select (SocketSet checkRead, SocketSet checkWrite, SocketSet checkError)
2407         {
2408                 return select (checkRead, checkWrite, checkError, null);
2409         }
2410 }
2411 
2412