xref: /netbsd-src/external/gpl3/gcc.old/dist/libphobos/src/std/socket.d (revision 82d56013d7b633d116a93943de88e08335357a7c)
1 // Written in the D programming language
2 
3 /*
4         Copyright (C) 2004-2011 Christopher E. Miller
5 
6         Boost Software License - Version 1.0 - August 17th, 2003
7 
8         Permission is hereby granted, free of charge, to any person or organization
9         obtaining a copy of the software and accompanying documentation covered by
10         this license (the "Software") to use, reproduce, display, distribute,
11         execute, and transmit the Software, and to prepare derivative works of the
12         Software, and to permit third-parties to whom the Software is furnished to
13         do so, all subject to the following:
14 
15         The copyright notices in the Software and this entire statement, including
16         the above license grant, this restriction and the following disclaimer,
17         must be included in all copies of the Software, in whole or in part, and
18         all derivative works of the Software, unless such copies or derivative
19         works are solely in the form of machine-executable object code generated by
20         a source language processor.
21 
22         THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23         IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24         FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
25         SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
26         FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
27         ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28         DEALINGS IN THE SOFTWARE.
29 
30         socket.d 1.4
31         Jan 2011
32 
33         Thanks to Benjamin Herr for his assistance.
34  */
35 
36 /**
37  * Socket primitives.
38  * Example: See $(SAMPLESRC listener.d) and $(SAMPLESRC htmlget.d)
39  * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
40  * Authors: Christopher E. Miller, $(HTTP klickverbot.at, David Nadlinger),
41  *      $(HTTP thecybershadow.net, Vladimir Panteleev)
42  * Source:  $(PHOBOSSRC std/_socket.d)
43  */
44 
45 module std.socket;
46 
47 import core.stdc.stdint, core.stdc.stdlib, core.stdc.string, std.conv, std.string;
48 
49 import core.stdc.config;
50 import core.time : dur, Duration;
51 import std.exception;
52 
53 import std.internal.cstring;
54 
55 
56 @safe:
57 
58 version (Windows)
59 {
60     pragma (lib, "ws2_32.lib");
61     pragma (lib, "wsock32.lib");
62 
63     import core.sys.windows.windows, std.windows.syserror;
64     public import core.sys.windows.winsock2;
65     private alias _ctimeval = core.sys.windows.winsock2.timeval;
66     private alias _clinger = core.sys.windows.winsock2.linger;
67 
68     enum socket_t : SOCKET { INVALID_SOCKET }
69     private const int _SOCKET_ERROR = SOCKET_ERROR;
70 
71 
72     private int _lasterr() nothrow @nogc
73     {
74         return WSAGetLastError();
75     }
76 }
77 else version (Posix)
78 {
79     version (linux)
80     {
81         enum : int
82         {
83             TCP_KEEPIDLE  = 4,
84             TCP_KEEPINTVL = 5
85         }
86     }
87 
88     import core.sys.posix.arpa.inet;
89     import core.sys.posix.fcntl;
90     import core.sys.posix.netdb;
91     import core.sys.posix.netinet.in_;
92     import core.sys.posix.netinet.tcp;
93     import core.sys.posix.sys.select;
94     import core.sys.posix.sys.socket;
95     import core.sys.posix.sys.time;
96     import core.sys.posix.sys.un : sockaddr_un;
97     import core.sys.posix.unistd;
98     private alias _ctimeval = core.sys.posix.sys.time.timeval;
99     private alias _clinger = core.sys.posix.sys.socket.linger;
100 
101     import core.stdc.errno;
102 
103     enum socket_t : int32_t { init = -1 }
104     private const int _SOCKET_ERROR = -1;
105 
106     private enum : int
107     {
108         SD_RECEIVE = SHUT_RD,
109         SD_SEND    = SHUT_WR,
110         SD_BOTH    = SHUT_RDWR
111     }
112 
113     private int _lasterr() nothrow @nogc
114     {
115         return errno;
116     }
117 }
118 else
119 {
120     static assert(0);     // No socket support yet.
121 }
122 
123 version (unittest)
124 {
125     static assert(is(uint32_t == uint));
126     static assert(is(uint16_t == ushort));
127 
128     import std.stdio : writefln;
129 
130     // Print a message on exception instead of failing the unittest.
131     private void softUnittest(void delegate() @safe test, int line = __LINE__) @trusted
132     {
133         try
134             test();
135         catch (Throwable e)
136         {
137             writefln(" --- std.socket(%d) test fails depending on environment ---", line);
138             writefln(" (%s)", e);
139         }
140     }
141 }
142 
143 /// Base exception thrown by $(D std.socket).
144 class SocketException: Exception
145 {
146     mixin basicExceptionCtors;
147 }
148 
149 
150 /*
151  * Needs to be public so that SocketOSException can be thrown outside of
152  * std.socket (since it uses it as a default argument), but it probably doesn't
153  * need to actually show up in the docs, since there's not really any public
154  * need for it outside of being a default argument.
155  */
156 string formatSocketError(int err) @trusted
157 {
158     version (Posix)
159     {
160         char[80] buf;
161         const(char)* cs;
162         version (CRuntime_Glibc)
163         {
164             cs = strerror_r(err, buf.ptr, buf.length);
165         }
166         else version (OSX)
167         {
168             auto errs = strerror_r(err, buf.ptr, buf.length);
169             if (errs == 0)
170                 cs = buf.ptr;
171             else
172                 return "Socket error " ~ to!string(err);
173         }
174         else version (FreeBSD)
175         {
176             auto errs = strerror_r(err, buf.ptr, buf.length);
177             if (errs == 0)
178                 cs = buf.ptr;
179             else
180                 return "Socket error " ~ to!string(err);
181         }
182         else version (NetBSD)
183         {
184             auto errs = strerror_r(err, buf.ptr, buf.length);
185             if (errs == 0)
186                 cs = buf.ptr;
187             else
188                 return "Socket error " ~ to!string(err);
189         }
190         else version (DragonFlyBSD)
191         {
192             auto errs = strerror_r(err, buf.ptr, buf.length);
193             if (errs == 0)
194                 cs = buf.ptr;
195             else
196                 return "Socket error " ~ to!string(err);
197         }
198         else version (Solaris)
199         {
200             auto errs = strerror_r(err, buf.ptr, buf.length);
201             if (errs == 0)
202                 cs = buf.ptr;
203             else
204                 return "Socket error " ~ to!string(err);
205         }
206         else version (CRuntime_Bionic)
207         {
208             auto errs = strerror_r(err, buf.ptr, buf.length);
209             if (errs == 0)
210                 cs = buf.ptr;
211             else
212                 return "Socket error " ~ to!string(err);
213         }
214         else
215             static assert(0);
216 
217         auto len = strlen(cs);
218 
219         if (cs[len - 1] == '\n')
220             len--;
221         if (cs[len - 1] == '\r')
222             len--;
223         return cs[0 .. len].idup;
224     }
225     else
226     version (Windows)
227     {
228         return sysErrorString(err);
229     }
230     else
231         return "Socket error " ~ to!string(err);
232 }
233 
234 /// Retrieve the error message for the most recently encountered network error.
235 @property string lastSocketError()
236 {
237     return formatSocketError(_lasterr());
238 }
239 
240 /**
241  * Socket exceptions representing network errors reported by the operating
242  * system.
243  */
244 class SocketOSException: SocketException
245 {
246     int errorCode;     /// Platform-specific error code.
247 
248     ///
249     this(string msg,
250          string file = __FILE__,
251          size_t line = __LINE__,
252          Throwable next = null,
253          int err = _lasterr(),
254          string function(int) @trusted errorFormatter = &formatSocketError)
255     {
256         errorCode = err;
257 
258         if (msg.length)
259             super(msg ~ ": " ~ errorFormatter(err), file, line, next);
260         else
261             super(errorFormatter(err), file, line, next);
262     }
263 
264     ///
265     this(string msg,
266          Throwable next,
267          string file = __FILE__,
268          size_t line = __LINE__,
269          int err = _lasterr(),
270          string function(int) @trusted errorFormatter = &formatSocketError)
271     {
272         this(msg, file, line, next, err, errorFormatter);
273     }
274 
275     ///
276     this(string msg,
277          int err,
278          string function(int) @trusted errorFormatter = &formatSocketError,
279          string file = __FILE__,
280          size_t line = __LINE__,
281          Throwable next = null)
282     {
283         this(msg, file, line, next, err, errorFormatter);
284     }
285 }
286 
287 /// Socket exceptions representing invalid parameters specified by user code.
288 class SocketParameterException: SocketException
289 {
290     mixin basicExceptionCtors;
291 }
292 
293 /**
294  * Socket exceptions representing attempts to use network capabilities not
295  * available on the current system.
296  */
297 class SocketFeatureException: SocketException
298 {
299     mixin basicExceptionCtors;
300 }
301 
302 
303 /**
304  * Returns:
305  * $(D true) if the last socket operation failed because the socket
306  * was in non-blocking mode and the operation would have blocked.
307  */
308 bool wouldHaveBlocked() nothrow @nogc
309 {
310     version (Windows)
311         return _lasterr() == WSAEWOULDBLOCK;
312     else version (Posix)
313         return _lasterr() == EAGAIN;
314     else
315         static assert(0);
316 }
317 
318 
319 private immutable
320 {
321     typeof(&getnameinfo) getnameinfoPointer;
322     typeof(&getaddrinfo) getaddrinfoPointer;
323     typeof(&freeaddrinfo) freeaddrinfoPointer;
324 }
325 
326 shared static this() @system
327 {
328     version (Windows)
329     {
330         WSADATA wd;
331 
332         // Winsock will still load if an older version is present.
333         // The version is just a request.
334         int val;
335         val = WSAStartup(0x2020, &wd);
336         if (val)         // Request Winsock 2.2 for IPv6.
337             throw new SocketOSException("Unable to initialize socket library", val);
338 
339         // These functions may not be present on older Windows versions.
340         // See the comment in InternetAddress.toHostNameString() for details.
341         auto ws2Lib = GetModuleHandleA("ws2_32.dll");
342         if (ws2Lib)
343         {
344             getnameinfoPointer = cast(typeof(getnameinfoPointer))
345                                  GetProcAddress(ws2Lib, "getnameinfo");
346             getaddrinfoPointer = cast(typeof(getaddrinfoPointer))
347                                  GetProcAddress(ws2Lib, "getaddrinfo");
348             freeaddrinfoPointer = cast(typeof(freeaddrinfoPointer))
349                                  GetProcAddress(ws2Lib, "freeaddrinfo");
350         }
351     }
352     else version (Posix)
353     {
354         getnameinfoPointer = &getnameinfo;
355         getaddrinfoPointer = &getaddrinfo;
356         freeaddrinfoPointer = &freeaddrinfo;
357     }
358 }
359 
360 
361 shared static ~this() @system nothrow @nogc
362 {
363     version (Windows)
364     {
365         WSACleanup();
366     }
367 }
368 
369 /**
370  * The communication domain used to resolve an address.
371  */
372 enum AddressFamily: int
373 {
374     UNSPEC =     AF_UNSPEC,     /// Unspecified address family
375     UNIX =       AF_UNIX,       /// Local communication
376     INET =       AF_INET,       /// Internet Protocol version 4
377     IPX =        AF_IPX,        /// Novell IPX
378     APPLETALK =  AF_APPLETALK,  /// AppleTalk
379     INET6 =      AF_INET6,      /// Internet Protocol version 6
380 }
381 
382 
383 /**
384  * Communication semantics
385  */
386 enum SocketType: int
387 {
388     STREAM =     SOCK_STREAM,           /// Sequenced, reliable, two-way communication-based byte streams
389     DGRAM =      SOCK_DGRAM,            /// Connectionless, unreliable datagrams with a fixed maximum length; data may be lost or arrive out of order
390     RAW =        SOCK_RAW,              /// Raw protocol access
391     RDM =        SOCK_RDM,              /// Reliably-delivered message datagrams
392     SEQPACKET =  SOCK_SEQPACKET,        /// Sequenced, reliable, two-way connection-based datagrams with a fixed maximum length
393 }
394 
395 
396 /**
397  * Protocol
398  */
399 enum ProtocolType: int
400 {
401     IP =    IPPROTO_IP,         /// Internet Protocol version 4
402     ICMP =  IPPROTO_ICMP,       /// Internet Control Message Protocol
403     IGMP =  IPPROTO_IGMP,       /// Internet Group Management Protocol
404     GGP =   IPPROTO_GGP,        /// Gateway to Gateway Protocol
405     TCP =   IPPROTO_TCP,        /// Transmission Control Protocol
406     PUP =   IPPROTO_PUP,        /// PARC Universal Packet Protocol
407     UDP =   IPPROTO_UDP,        /// User Datagram Protocol
408     IDP =   IPPROTO_IDP,        /// Xerox NS protocol
409     RAW =   IPPROTO_RAW,        /// Raw IP packets
410     IPV6 =  IPPROTO_IPV6,       /// Internet Protocol version 6
411 }
412 
413 
414 /**
415  * $(D Protocol) is a class for retrieving protocol information.
416  *
417  * Example:
418  * ---
419  * auto proto = new Protocol;
420  * writeln("About protocol TCP:");
421  * if (proto.getProtocolByType(ProtocolType.TCP))
422  * {
423  *     writefln("  Name: %s", proto.name);
424  *     foreach (string s; proto.aliases)
425  *          writefln("  Alias: %s", s);
426  * }
427  * else
428  *     writeln("  No information found");
429  * ---
430  */
431 class Protocol
432 {
433     /// These members are populated when one of the following functions are called successfully:
434     ProtocolType type;
435     string name;                /// ditto
436     string[] aliases;           /// ditto
437 
438 
439     void populate(protoent* proto) @system pure nothrow
440     {
441         type = cast(ProtocolType) proto.p_proto;
442         name = to!string(proto.p_name);
443 
444         int i;
445         for (i = 0;; i++)
446         {
447             if (!proto.p_aliases[i])
448                 break;
449         }
450 
451         if (i)
452         {
453             aliases = new string[i];
454             for (i = 0; i != aliases.length; i++)
455             {
456                 aliases[i] =
457                     to!string(proto.p_aliases[i]);
458             }
459         }
460         else
461         {
462             aliases = null;
463         }
464     }
465 
466     /** Returns: false on failure */
467     bool getProtocolByName(in char[] name) @trusted nothrow
468     {
469         protoent* proto;
470         proto = getprotobyname(name.tempCString());
471         if (!proto)
472             return false;
473         populate(proto);
474         return true;
475     }
476 
477 
478     /** Returns: false on failure */
479     // Same as getprotobynumber().
480     bool getProtocolByType(ProtocolType type) @trusted nothrow
481     {
482         protoent* proto;
483         proto = getprotobynumber(type);
484         if (!proto)
485             return false;
486         populate(proto);
487         return true;
488     }
489 }
490 
491 
492 // Skip this test on Android because getprotobyname/number are
493 // unimplemented in bionic.
494 version (CRuntime_Bionic) {} else
495 @safe unittest
496 {
497     softUnittest({
498         Protocol proto = new Protocol;
499         assert(proto.getProtocolByType(ProtocolType.TCP));
500         //writeln("About protocol TCP:");
501         //writefln("\tName: %s", proto.name);
502         // foreach (string s; proto.aliases)
503         // {
504         //      writefln("\tAlias: %s", s);
505         // }
506         assert(proto.name == "tcp");
507         assert(proto.aliases.length == 1 && proto.aliases[0] == "TCP");
508     });
509 }
510 
511 
512 /**
513  * $(D Service) is a class for retrieving service information.
514  *
515  * Example:
516  * ---
517  * auto serv = new Service;
518  * writeln("About service epmap:");
519  * if (serv.getServiceByName("epmap", "tcp"))
520  * {
521  *     writefln("  Service: %s", serv.name);
522  *     writefln("  Port: %d", serv.port);
523  *     writefln("  Protocol: %s", serv.protocolName);
524  *     foreach (string s; serv.aliases)
525  *          writefln("  Alias: %s", s);
526  * }
527  * else
528  *     writefln("  No service for epmap.");
529  * ---
530  */
531 class Service
532 {
533     /// These members are populated when one of the following functions are called successfully:
534     string name;
535     string[] aliases;           /// ditto
536     ushort port;                /// ditto
537     string protocolName;        /// ditto
538 
539 
540     void populate(servent* serv) @system pure nothrow
541     {
542         name = to!string(serv.s_name);
543         port = ntohs(cast(ushort) serv.s_port);
544         protocolName = to!string(serv.s_proto);
545 
546         int i;
547         for (i = 0;; i++)
548         {
549             if (!serv.s_aliases[i])
550                 break;
551         }
552 
553         if (i)
554         {
555             aliases = new string[i];
556             for (i = 0; i != aliases.length; i++)
557             {
558                 aliases[i] =
559                     to!string(serv.s_aliases[i]);
560             }
561         }
562         else
563         {
564             aliases = null;
565         }
566     }
567 
568     /**
569      * If a protocol name is omitted, any protocol will be matched.
570      * Returns: false on failure.
571      */
572     bool getServiceByName(in char[] name, in char[] protocolName = null) @trusted nothrow
573     {
574         servent* serv;
575         serv = getservbyname(name.tempCString(), protocolName.tempCString());
576         if (!serv)
577             return false;
578         populate(serv);
579         return true;
580     }
581 
582 
583     /// ditto
584     bool getServiceByPort(ushort port, in char[] protocolName = null) @trusted nothrow
585     {
586         servent* serv;
587         serv = getservbyport(port, protocolName.tempCString());
588         if (!serv)
589             return false;
590         populate(serv);
591         return true;
592     }
593 }
594 
595 
596 @safe unittest
597 {
598     softUnittest({
599         Service serv = new Service;
600         if (serv.getServiceByName("epmap", "tcp"))
601         {
602             // writefln("About service epmap:");
603             // writefln("\tService: %s", serv.name);
604             // writefln("\tPort: %d", serv.port);
605             // writefln("\tProtocol: %s", serv.protocolName);
606             // foreach (string s; serv.aliases)
607             // {
608             //      writefln("\tAlias: %s", s);
609             // }
610             // For reasons unknown this is loc-srv on Wine and epmap on Windows
611             assert(serv.name == "loc-srv" || serv.name == "epmap", serv.name);
612             assert(serv.port == 135);
613             assert(serv.protocolName == "tcp");
614         }
615         else
616         {
617             writefln("No service for epmap.");
618         }
619     });
620 }
621 
622 
623 private mixin template socketOSExceptionCtors()
624 {
625     ///
626     this(string msg, string file = __FILE__, size_t line = __LINE__,
627          Throwable next = null, int err = _lasterr())
628     {
629         super(msg, file, line, next, err);
630     }
631 
632     ///
633     this(string msg, Throwable next, string file = __FILE__,
634          size_t line = __LINE__, int err = _lasterr())
635     {
636         super(msg, next, file, line, err);
637     }
638 
639     ///
640     this(string msg, int err, string file = __FILE__, size_t line = __LINE__,
641          Throwable next = null)
642     {
643         super(msg, next, file, line, err);
644     }
645 }
646 
647 
648 /**
649  * Class for exceptions thrown from an `InternetHost`.
650  */
651 class HostException: SocketOSException
652 {
653     mixin socketOSExceptionCtors;
654 }
655 
656 /**
657  * `InternetHost` is a class for resolving IPv4 addresses.
658  *
659  * Consider using `getAddress`, `parseAddress` and `Address` methods
660  * instead of using this class directly.
661  */
662 class InternetHost
663 {
664     /// These members are populated when one of the following functions are called successfully:
665     string name;
666     string[] aliases;           /// ditto
667     uint[] addrList;            /// ditto
668 
669 
670     void validHostent(in hostent* he)
671     {
672         if (he.h_addrtype != cast(int) AddressFamily.INET || he.h_length != 4)
673             throw new HostException("Address family mismatch");
674     }
675 
676 
677     void populate(hostent* he) @system pure nothrow
678     {
679         int i;
680         char* p;
681 
682         name = to!string(he.h_name);
683 
684         for (i = 0;; i++)
685         {
686             p = he.h_aliases[i];
687             if (!p)
688                 break;
689         }
690 
691         if (i)
692         {
693             aliases = new string[i];
694             for (i = 0; i != aliases.length; i++)
695             {
696                 aliases[i] =
697                     to!string(he.h_aliases[i]);
698             }
699         }
700         else
701         {
702             aliases = null;
703         }
704 
705         for (i = 0;; i++)
706         {
707             p = he.h_addr_list[i];
708             if (!p)
709                 break;
710         }
711 
712         if (i)
713         {
714             addrList = new uint[i];
715             for (i = 0; i != addrList.length; i++)
716             {
717                 addrList[i] = ntohl(*(cast(uint*) he.h_addr_list[i]));
718             }
719         }
720         else
721         {
722             addrList = null;
723         }
724     }
725 
726     private bool getHostNoSync(string opMixin, T)(T param) @system
727     {
728         mixin(opMixin);
729         if (!he)
730             return false;
731         validHostent(he);
732         populate(he);
733         return true;
734     }
735 
736     version (Windows)
737         alias getHost = getHostNoSync;
738     else
739     {
740         // posix systems use global state for return value, so we
741         // must synchronize across all threads
742         private bool getHost(string opMixin, T)(T param) @system
743         {
744             synchronized(this.classinfo)
745                 return getHostNoSync!(opMixin, T)(param);
746         }
747     }
748 
749     /**
750      * Resolve host name.
751      * Returns: false if unable to resolve.
752      */
753     bool getHostByName(in char[] name) @trusted
754     {
755         static if (is(typeof(gethostbyname_r)))
756         {
757             return getHostNoSync!q{
758                 hostent he_v;
759                 hostent* he;
760                 ubyte[256] buffer_v = void;
761                 auto buffer = buffer_v[];
762                 auto param_zTmp = param.tempCString();
763                 while (true)
764                 {
765                     he = &he_v;
766                     int errno;
767                     if (gethostbyname_r(param_zTmp, he, buffer.ptr, buffer.length, &he, &errno) == ERANGE)
768                         buffer.length = buffer.length * 2;
769                     else
770                         break;
771                 }
772             }(name);
773         }
774         else
775         {
776             return getHost!q{
777                 auto he = gethostbyname(param.tempCString());
778             }(name);
779         }
780     }
781 
782     /**
783      * Resolve IPv4 address number.
784      *
785      * Params:
786      *   addr = The IPv4 address to resolve, in host byte order.
787      * Returns:
788      *   false if unable to resolve.
789      */
790     bool getHostByAddr(uint addr) @trusted
791     {
792         return getHost!q{
793             auto x = htonl(param);
794             auto he = gethostbyaddr(&x, 4, cast(int) AddressFamily.INET);
795         }(addr);
796     }
797 
798     /**
799      * Same as previous, but addr is an IPv4 address string in the
800      * dotted-decimal form $(I a.b.c.d).
801      * Returns: false if unable to resolve.
802      */
803     bool getHostByAddr(in char[] addr) @trusted
804     {
805         return getHost!q{
806             auto x = inet_addr(param.tempCString());
807             enforce(x != INADDR_NONE,
808                 new SocketParameterException("Invalid IPv4 address"));
809             auto he = gethostbyaddr(&x, 4, cast(int) AddressFamily.INET);
810         }(addr);
811     }
812 }
813 
814 ///
815 @safe unittest
816 {
817     InternetHost ih = new InternetHost;
818 
819     ih.getHostByAddr(0x7F_00_00_01);
820     assert(ih.addrList[0] == 0x7F_00_00_01);
821     ih.getHostByAddr("127.0.0.1");
822     assert(ih.addrList[0] == 0x7F_00_00_01);
823 
824     if (!ih.getHostByName("www.digitalmars.com"))
825         return;             // don't fail if not connected to internet
826 
827     assert(ih.addrList.length);
828     InternetAddress ia = new InternetAddress(ih.addrList[0], InternetAddress.PORT_ANY);
829     assert(ih.name == "www.digitalmars.com" || ih.name == "digitalmars.com",
830             ih.name);
831 
832     assert(ih.getHostByAddr(ih.addrList[0]));
833     string getHostNameFromInt = ih.name.dup;
834 
835     assert(ih.getHostByAddr(ia.toAddrString()));
836     string getHostNameFromStr = ih.name.dup;
837 
838     assert(getHostNameFromInt == getHostNameFromStr);
839 }
840 
841 
842 /// Holds information about a socket _address retrieved by $(D getAddressInfo).
843 struct AddressInfo
844 {
845     AddressFamily family;   /// Address _family
846     SocketType type;        /// Socket _type
847     ProtocolType protocol;  /// Protocol
848     Address address;        /// Socket _address
849     string canonicalName;   /// Canonical name, when $(D AddressInfoFlags.CANONNAME) is used.
850 }
851 
852 /**
853  * A subset of flags supported on all platforms with getaddrinfo.
854  * Specifies option flags for $(D getAddressInfo).
855  */
856 enum AddressInfoFlags: int
857 {
858     /// The resulting addresses will be used in a call to $(D Socket.bind).
859     PASSIVE = AI_PASSIVE,
860 
861     /// The canonical name is returned in $(D canonicalName) member in the first $(D AddressInfo).
862     CANONNAME = AI_CANONNAME,
863 
864     /**
865      * The $(D node) parameter passed to $(D getAddressInfo) must be a numeric string.
866      * This will suppress any potentially lengthy network host address lookups.
867      */
868     NUMERICHOST = AI_NUMERICHOST,
869 }
870 
871 
872 /**
873  * On POSIX, getaddrinfo uses its own error codes, and thus has its own
874  * formatting function.
875  */
876 private string formatGaiError(int err) @trusted
877 {
878     version (Windows)
879     {
880         return sysErrorString(err);
881     }
882     else
883     {
884         synchronized
885             return to!string(gai_strerror(err));
886     }
887 }
888 
889 /**
890  * Provides _protocol-independent translation from host names to socket
891  * addresses. If advanced functionality is not required, consider using
892  * $(D getAddress) for compatibility with older systems.
893  *
894  * Returns: Array with one $(D AddressInfo) per socket address.
895  *
896  * Throws: $(D SocketOSException) on failure, or $(D SocketFeatureException)
897  * if this functionality is not available on the current system.
898  *
899  * Params:
900  *  node     = string containing host name or numeric address
901  *  options  = optional additional parameters, identified by type:
902  *             $(UL $(LI $(D string) - service name or port number)
903  *                  $(LI $(D AddressInfoFlags) - option flags)
904  *                  $(LI $(D AddressFamily) - address family to filter by)
905  *                  $(LI $(D SocketType) - socket type to filter by)
906  *                  $(LI $(D ProtocolType) - protocol to filter by))
907  *
908  * Example:
909  * ---
910  * // Roundtrip DNS resolution
911  * auto results = getAddressInfo("www.digitalmars.com");
912  * assert(results[0].address.toHostNameString() ==
913  *     "digitalmars.com");
914  *
915  * // Canonical name
916  * results = getAddressInfo("www.digitalmars.com",
917  *     AddressInfoFlags.CANONNAME);
918  * assert(results[0].canonicalName == "digitalmars.com");
919  *
920  * // IPv6 resolution
921  * results = getAddressInfo("ipv6.google.com");
922  * assert(results[0].family == AddressFamily.INET6);
923  *
924  * // Multihomed resolution
925  * results = getAddressInfo("google.com");
926  * assert(results.length > 1);
927  *
928  * // Parsing IPv4
929  * results = getAddressInfo("127.0.0.1",
930  *     AddressInfoFlags.NUMERICHOST);
931  * assert(results.length && results[0].family ==
932  *     AddressFamily.INET);
933  *
934  * // Parsing IPv6
935  * results = getAddressInfo("::1",
936  *     AddressInfoFlags.NUMERICHOST);
937  * assert(results.length && results[0].family ==
938  *     AddressFamily.INET6);
939  * ---
940  */
941 AddressInfo[] getAddressInfo(T...)(in char[] node, T options)
942 {
943     const(char)[] service = null;
944     addrinfo hints;
945     hints.ai_family = AF_UNSPEC;
946 
947     foreach (option; options)
948     {
949         static if (is(typeof(option) : const(char)[]))
950             service = option;
951         else
952         static if (is(typeof(option) == AddressInfoFlags))
953             hints.ai_flags |= option;
954         else
955         static if (is(typeof(option) == AddressFamily))
956             hints.ai_family = option;
957         else
958         static if (is(typeof(option) == SocketType))
959             hints.ai_socktype = option;
960         else
961         static if (is(typeof(option) == ProtocolType))
962             hints.ai_protocol = option;
963         else
964             static assert(0, "Unknown getAddressInfo option type: " ~ typeof(option).stringof);
965     }
966 
967     return () @trusted { return getAddressInfoImpl(node, service, &hints); }();
968 }
969 
970 @system unittest
971 {
972     struct Oops
973     {
974         const(char[]) breakSafety()
975         {
976             *cast(int*) 0xcafebabe = 0xdeadbeef;
977             return null;
978         }
979         alias breakSafety this;
980     }
981     assert(!__traits(compiles, () {
982         getAddressInfo("", Oops.init);
983     }), "getAddressInfo breaks @safe");
984 }
985 
986 private AddressInfo[] getAddressInfoImpl(in char[] node, in char[] service, addrinfo* hints) @system
987 {
988         import std.array : appender;
989 
990     if (getaddrinfoPointer && freeaddrinfoPointer)
991     {
992         addrinfo* ai_res;
993 
994         int ret = getaddrinfoPointer(
995             node.tempCString(),
996             service.tempCString(),
997             hints, &ai_res);
998         enforce(ret == 0, new SocketOSException("getaddrinfo error", ret, &formatGaiError));
999         scope(exit) freeaddrinfoPointer(ai_res);
1000 
1001         auto result = appender!(AddressInfo[])();
1002 
1003         // Use const to force UnknownAddressReference to copy the sockaddr.
1004         for (const(addrinfo)* ai = ai_res; ai; ai = ai.ai_next)
1005             result ~= AddressInfo(
1006                 cast(AddressFamily) ai.ai_family,
1007                 cast(SocketType   ) ai.ai_socktype,
1008                 cast(ProtocolType ) ai.ai_protocol,
1009                 new UnknownAddressReference(ai.ai_addr, cast(socklen_t) ai.ai_addrlen),
1010                 ai.ai_canonname ? to!string(ai.ai_canonname) : null);
1011 
1012         assert(result.data.length > 0);
1013         return result.data;
1014     }
1015 
1016     throw new SocketFeatureException("Address info lookup is not available " ~
1017         "on this system.");
1018 }
1019 
1020 
1021 @safe unittest
1022 {
1023     softUnittest({
1024         if (getaddrinfoPointer)
1025         {
1026             // Roundtrip DNS resolution
1027             auto results = getAddressInfo("www.digitalmars.com");
1028             assert(results[0].address.toHostNameString() == "digitalmars.com");
1029 
1030             // Canonical name
1031             results = getAddressInfo("www.digitalmars.com",
1032                 AddressInfoFlags.CANONNAME);
1033             assert(results[0].canonicalName == "digitalmars.com");
1034 
1035             // IPv6 resolution
1036             //results = getAddressInfo("ipv6.google.com");
1037             //assert(results[0].family == AddressFamily.INET6);
1038 
1039             // Multihomed resolution
1040             //results = getAddressInfo("google.com");
1041             //assert(results.length > 1);
1042 
1043             // Parsing IPv4
1044             results = getAddressInfo("127.0.0.1", AddressInfoFlags.NUMERICHOST);
1045             assert(results.length && results[0].family == AddressFamily.INET);
1046 
1047             // Parsing IPv6
1048             results = getAddressInfo("::1", AddressInfoFlags.NUMERICHOST);
1049             assert(results.length && results[0].family == AddressFamily.INET6);
1050         }
1051     });
1052 
1053     if (getaddrinfoPointer)
1054     {
1055         auto results = getAddressInfo(null, "1234", AddressInfoFlags.PASSIVE,
1056                                       SocketType.STREAM, ProtocolType.TCP, AddressFamily.INET);
1057         assert(results.length == 1 && results[0].address.toString() == "0.0.0.0:1234");
1058     }
1059 }
1060 
1061 
1062 private ushort serviceToPort(in char[] service)
1063 {
1064     if (service == "")
1065         return InternetAddress.PORT_ANY;
1066     else
1067     if (isNumeric(service))
1068         return to!ushort(service);
1069     else
1070     {
1071         auto s = new Service();
1072         s.getServiceByName(service);
1073         return s.port;
1074     }
1075 }
1076 
1077 /**
1078  * Provides _protocol-independent translation from host names to socket
1079  * addresses. Uses $(D getAddressInfo) if the current system supports it,
1080  * and $(D InternetHost) otherwise.
1081  *
1082  * Returns: Array with one $(D Address) instance per socket address.
1083  *
1084  * Throws: $(D SocketOSException) on failure.
1085  *
1086  * Example:
1087  * ---
1088  * writeln("Resolving www.digitalmars.com:");
1089  * try
1090  * {
1091  *     auto addresses = getAddress("www.digitalmars.com");
1092  *     foreach (address; addresses)
1093  *         writefln("  IP: %s", address.toAddrString());
1094  * }
1095  * catch (SocketException e)
1096  *     writefln("  Lookup failed: %s", e.msg);
1097  * ---
1098  */
1099 Address[] getAddress(in char[] hostname, in char[] service = null)
1100 {
1101     if (getaddrinfoPointer && freeaddrinfoPointer)
1102     {
1103         // use getAddressInfo
1104         auto infos = getAddressInfo(hostname, service);
1105         Address[] results;
1106         results.length = infos.length;
1107         foreach (i, ref result; results)
1108             result = infos[i].address;
1109         return results;
1110     }
1111     else
1112         return getAddress(hostname, serviceToPort(service));
1113 }
1114 
1115 /// ditto
1116 Address[] getAddress(in char[] hostname, ushort port)
1117 {
1118     if (getaddrinfoPointer && freeaddrinfoPointer)
1119         return getAddress(hostname, to!string(port));
1120     else
1121     {
1122         // use getHostByName
1123         auto ih = new InternetHost;
1124         if (!ih.getHostByName(hostname))
1125             throw new AddressException(
1126                         text("Unable to resolve host '", hostname, "'"));
1127 
1128         Address[] results;
1129         foreach (uint addr; ih.addrList)
1130             results ~= new InternetAddress(addr, port);
1131         return results;
1132     }
1133 }
1134 
1135 
1136 @safe unittest
1137 {
1138     softUnittest({
1139         auto addresses = getAddress("63.105.9.61");
1140         assert(addresses.length && addresses[0].toAddrString() == "63.105.9.61");
1141 
1142         if (getaddrinfoPointer)
1143         {
1144             // test via gethostbyname
1145             auto getaddrinfoPointerBackup = getaddrinfoPointer;
1146             cast() getaddrinfoPointer = null;
1147             scope(exit) cast() getaddrinfoPointer = getaddrinfoPointerBackup;
1148 
1149             addresses = getAddress("63.105.9.61");
1150             assert(addresses.length && addresses[0].toAddrString() == "63.105.9.61");
1151         }
1152     });
1153 }
1154 
1155 
1156 /**
1157  * Provides _protocol-independent parsing of network addresses. Does not
1158  * attempt name resolution. Uses $(D getAddressInfo) with
1159  * $(D AddressInfoFlags.NUMERICHOST) if the current system supports it, and
1160  * $(D InternetAddress) otherwise.
1161  *
1162  * Returns: An $(D Address) instance representing specified address.
1163  *
1164  * Throws: $(D SocketException) on failure.
1165  *
1166  * Example:
1167  * ---
1168  * writeln("Enter IP address:");
1169  * string ip = readln().chomp();
1170  * try
1171  * {
1172  *     Address address = parseAddress(ip);
1173  *     writefln("Looking up reverse of %s:",
1174  *         address.toAddrString());
1175  *     try
1176  *     {
1177  *         string reverse = address.toHostNameString();
1178  *         if (reverse)
1179  *             writefln("  Reverse name: %s", reverse);
1180  *         else
1181  *             writeln("  Reverse hostname not found.");
1182  *     }
1183  *     catch (SocketException e)
1184  *         writefln("  Lookup error: %s", e.msg);
1185  * }
1186  * catch (SocketException e)
1187  * {
1188  *     writefln("  %s is not a valid IP address: %s",
1189  *         ip, e.msg);
1190  * }
1191  * ---
1192  */
1193 Address parseAddress(in char[] hostaddr, in char[] service = null)
1194 {
1195     if (getaddrinfoPointer && freeaddrinfoPointer)
1196         return getAddressInfo(hostaddr, service, AddressInfoFlags.NUMERICHOST)[0].address;
1197     else
1198         return parseAddress(hostaddr, serviceToPort(service));
1199 }
1200 
1201 /// ditto
1202 Address parseAddress(in char[] hostaddr, ushort port)
1203 {
1204     if (getaddrinfoPointer && freeaddrinfoPointer)
1205         return parseAddress(hostaddr, to!string(port));
1206     else
1207     {
1208         auto in4_addr = InternetAddress.parse(hostaddr);
1209         enforce(in4_addr != InternetAddress.ADDR_NONE,
1210             new SocketParameterException("Invalid IP address"));
1211         return new InternetAddress(in4_addr, port);
1212     }
1213 }
1214 
1215 
1216 @safe unittest
1217 {
1218     softUnittest({
1219         auto address = parseAddress("63.105.9.61");
1220         assert(address.toAddrString() == "63.105.9.61");
1221 
1222         if (getaddrinfoPointer)
1223         {
1224             // test via inet_addr
1225             auto getaddrinfoPointerBackup = getaddrinfoPointer;
1226             cast() getaddrinfoPointer = null;
1227             scope(exit) cast() getaddrinfoPointer = getaddrinfoPointerBackup;
1228 
1229             address = parseAddress("63.105.9.61");
1230             assert(address.toAddrString() == "63.105.9.61");
1231         }
1232 
1233         assert(collectException!SocketException(parseAddress("Invalid IP address")));
1234     });
1235 }
1236 
1237 
1238 /**
1239  * Class for exceptions thrown from an $(D Address).
1240  */
1241 class AddressException: SocketOSException
1242 {
1243     mixin socketOSExceptionCtors;
1244 }
1245 
1246 
1247 /**
1248  * $(D Address) is an abstract class for representing a socket addresses.
1249  *
1250  * Example:
1251  * ---
1252  * writeln("About www.google.com port 80:");
1253  * try
1254  * {
1255  *     Address[] addresses = getAddress("www.google.com", 80);
1256  *     writefln("  %d addresses found.", addresses.length);
1257  *     foreach (int i, Address a; addresses)
1258  *     {
1259  *         writefln("  Address %d:", i+1);
1260  *         writefln("    IP address: %s", a.toAddrString());
1261  *         writefln("    Hostname: %s", a.toHostNameString());
1262  *         writefln("    Port: %s", a.toPortString());
1263  *         writefln("    Service name: %s",
1264  *             a.toServiceNameString());
1265  *     }
1266  * }
1267  * catch (SocketException e)
1268  *     writefln("  Lookup error: %s", e.msg);
1269  * ---
1270  */
1271 abstract class Address
1272 {
1273     /// Returns pointer to underlying $(D sockaddr) structure.
1274     abstract @property sockaddr* name() pure nothrow @nogc;
1275     abstract @property const(sockaddr)* name() const pure nothrow @nogc; /// ditto
1276 
1277     /// Returns actual size of underlying $(D sockaddr) structure.
1278     abstract @property socklen_t nameLen() const pure nothrow @nogc;
1279 
1280     // Socket.remoteAddress, Socket.localAddress, and Socket.receiveFrom
1281     // use setNameLen to set the actual size of the address as returned by
1282     // getsockname, getpeername, and recvfrom, respectively.
1283     // The following implementation is sufficient for fixed-length addresses,
1284     // and ensures that the length is not changed.
1285     // Must be overridden for variable-length addresses.
1286     protected void setNameLen(socklen_t len)
1287     {
1288         if (len != this.nameLen)
1289             throw new AddressException(
1290                 format("%s expects address of length %d, not %d", typeid(this),
1291                     this.nameLen, len), 0);
1292     }
1293 
1294     /// Family of this address.
1295     @property AddressFamily addressFamily() const pure nothrow @nogc
1296     {
1297         return cast(AddressFamily) name.sa_family;
1298     }
1299 
1300     // Common code for toAddrString and toHostNameString
1301     private string toHostString(bool numeric) @trusted const
1302     {
1303         // getnameinfo() is the recommended way to perform a reverse (name)
1304         // lookup on both Posix and Windows. However, it is only available
1305         // on Windows XP and above, and not included with the WinSock import
1306         // libraries shipped with DMD. Thus, we check for getnameinfo at
1307         // runtime in the shared module constructor, and use it if it's
1308         // available in the base class method. Classes for specific network
1309         // families (e.g. InternetHost) override this method and use a
1310         // deprecated, albeit commonly-available method when getnameinfo()
1311         // is not available.
1312         // http://technet.microsoft.com/en-us/library/aa450403.aspx
1313         if (getnameinfoPointer)
1314         {
1315             auto buf = new char[NI_MAXHOST];
1316             auto ret = getnameinfoPointer(
1317                         name, nameLen,
1318                         buf.ptr, cast(uint) buf.length,
1319                         null, 0,
1320                         numeric ? NI_NUMERICHOST : NI_NAMEREQD);
1321 
1322             if (!numeric)
1323             {
1324                 if (ret == EAI_NONAME)
1325                     return null;
1326                 version (Windows)
1327                     if (ret == WSANO_DATA)
1328                         return null;
1329             }
1330 
1331             enforce(ret == 0, new AddressException("Could not get " ~
1332                         (numeric ? "host address" : "host name")));
1333             return assumeUnique(buf[0 .. strlen(buf.ptr)]);
1334         }
1335 
1336         throw new SocketFeatureException((numeric ? "Host address" : "Host name") ~
1337             " lookup for this address family is not available on this system.");
1338     }
1339 
1340     // Common code for toPortString and toServiceNameString
1341     private string toServiceString(bool numeric) @trusted const
1342     {
1343         // See toHostNameString() for details about getnameinfo().
1344         if (getnameinfoPointer)
1345         {
1346             auto buf = new char[NI_MAXSERV];
1347             enforce(getnameinfoPointer(
1348                         name, nameLen,
1349                         null, 0,
1350                         buf.ptr, cast(uint) buf.length,
1351                         numeric ? NI_NUMERICSERV : NI_NAMEREQD
1352                     ) == 0, new AddressException("Could not get " ~
1353                         (numeric ? "port number" : "service name")));
1354             return assumeUnique(buf[0 .. strlen(buf.ptr)]);
1355         }
1356 
1357         throw new SocketFeatureException((numeric ? "Port number" : "Service name") ~
1358             " lookup for this address family is not available on this system.");
1359     }
1360 
1361     /**
1362      * Attempts to retrieve the host address as a human-readable string.
1363      *
1364      * Throws: $(D AddressException) on failure, or $(D SocketFeatureException)
1365      * if address retrieval for this address family is not available on the
1366      * current system.
1367      */
1368     string toAddrString() const
1369     {
1370         return toHostString(true);
1371     }
1372 
1373     /**
1374      * Attempts to retrieve the host name as a fully qualified domain name.
1375      *
1376      * Returns: The FQDN corresponding to this $(D Address), or $(D null) if
1377      * the host name did not resolve.
1378      *
1379      * Throws: $(D AddressException) on error, or $(D SocketFeatureException)
1380      * if host name lookup for this address family is not available on the
1381      * current system.
1382      */
1383     string toHostNameString() const
1384     {
1385         return toHostString(false);
1386     }
1387 
1388     /**
1389      * Attempts to retrieve the numeric port number as a string.
1390      *
1391      * Throws: $(D AddressException) on failure, or $(D SocketFeatureException)
1392      * if port number retrieval for this address family is not available on the
1393      * current system.
1394      */
1395     string toPortString() const
1396     {
1397         return toServiceString(true);
1398     }
1399 
1400     /**
1401      * Attempts to retrieve the service name as a string.
1402      *
1403      * Throws: $(D AddressException) on failure, or $(D SocketFeatureException)
1404      * if service name lookup for this address family is not available on the
1405      * current system.
1406      */
1407     string toServiceNameString() const
1408     {
1409         return toServiceString(false);
1410     }
1411 
1412     /// Human readable string representing this address.
1413     override string toString() const
1414     {
1415         try
1416         {
1417             string host = toAddrString();
1418             string port = toPortString();
1419             if (host.indexOf(':') >= 0)
1420                 return "[" ~ host ~ "]:" ~ port;
1421             else
1422                 return host ~ ":" ~ port;
1423         }
1424         catch (SocketException)
1425             return "Unknown";
1426     }
1427 }
1428 
1429 /**
1430  * $(D UnknownAddress) encapsulates an unknown socket address.
1431  */
1432 class UnknownAddress: Address
1433 {
1434 protected:
1435     sockaddr sa;
1436 
1437 
1438 public:
1439     override @property sockaddr* name()
1440     {
1441         return &sa;
1442     }
1443 
1444     override @property const(sockaddr)* name() const
1445     {
1446         return &sa;
1447     }
1448 
1449 
1450     override @property socklen_t nameLen() const
1451     {
1452         return cast(socklen_t) sa.sizeof;
1453     }
1454 
1455 }
1456 
1457 
1458 /**
1459  * $(D UnknownAddressReference) encapsulates a reference to an arbitrary
1460  * socket address.
1461  */
1462 class UnknownAddressReference: Address
1463 {
1464 protected:
1465     sockaddr* sa;
1466     socklen_t len;
1467 
1468 public:
1469     /// Constructs an $(D Address) with a reference to the specified $(D sockaddr).
1470     this(sockaddr* sa, socklen_t len) pure nothrow @nogc
1471     {
1472         this.sa  = sa;
1473         this.len = len;
1474     }
1475 
1476     /// Constructs an $(D Address) with a copy of the specified $(D sockaddr).
1477     this(const(sockaddr)* sa, socklen_t len) @system pure nothrow
1478     {
1479         this.sa = cast(sockaddr*) (cast(ubyte*) sa)[0 .. len].dup.ptr;
1480         this.len = len;
1481     }
1482 
1483     override @property sockaddr* name()
1484     {
1485         return sa;
1486     }
1487 
1488     override @property const(sockaddr)* name() const
1489     {
1490         return sa;
1491     }
1492 
1493 
1494     override @property socklen_t nameLen() const
1495     {
1496         return cast(socklen_t) len;
1497     }
1498 }
1499 
1500 
1501 /**
1502  * $(D InternetAddress) encapsulates an IPv4 (Internet Protocol version 4)
1503  * socket address.
1504  *
1505  * Consider using $(D getAddress), $(D parseAddress) and $(D Address) methods
1506  * instead of using this class directly.
1507  */
1508 class InternetAddress: Address
1509 {
1510 protected:
1511     sockaddr_in sin;
1512 
1513 
1514     this() pure nothrow @nogc
1515     {
1516     }
1517 
1518 
1519 public:
1520     override @property sockaddr* name()
1521     {
1522         return cast(sockaddr*)&sin;
1523     }
1524 
1525     override @property const(sockaddr)* name() const
1526     {
1527         return cast(const(sockaddr)*)&sin;
1528     }
1529 
1530 
1531     override @property socklen_t nameLen() const
1532     {
1533         return cast(socklen_t) sin.sizeof;
1534     }
1535 
1536 
1537     enum uint ADDR_ANY = INADDR_ANY;         /// Any IPv4 host address.
1538     enum uint ADDR_NONE = INADDR_NONE;       /// An invalid IPv4 host address.
1539     enum ushort PORT_ANY = 0;                /// Any IPv4 port number.
1540 
1541     /// Returns the IPv4 _port number (in host byte order).
1542     @property ushort port() const pure nothrow @nogc
1543     {
1544         return ntohs(sin.sin_port);
1545     }
1546 
1547     /// Returns the IPv4 address number (in host byte order).
1548     @property uint addr() const pure nothrow @nogc
1549     {
1550         return ntohl(sin.sin_addr.s_addr);
1551     }
1552 
1553     /**
1554      * Construct a new $(D InternetAddress).
1555      * Params:
1556      *   addr = an IPv4 address string in the dotted-decimal form a.b.c.d,
1557      *          or a host name which will be resolved using an $(D InternetHost)
1558      *          object.
1559      *   port = port number, may be $(D PORT_ANY).
1560      */
1561     this(in char[] addr, ushort port)
1562     {
1563         uint uiaddr = parse(addr);
1564         if (ADDR_NONE == uiaddr)
1565         {
1566             InternetHost ih = new InternetHost;
1567             if (!ih.getHostByName(addr))
1568                 //throw new AddressException("Invalid internet address");
1569                 throw new AddressException(
1570                           text("Unable to resolve host '", addr, "'"));
1571             uiaddr = ih.addrList[0];
1572         }
1573         sin.sin_family = AddressFamily.INET;
1574         sin.sin_addr.s_addr = htonl(uiaddr);
1575         sin.sin_port = htons(port);
1576     }
1577 
1578     /**
1579      * Construct a new $(D InternetAddress).
1580      * Params:
1581      *   addr = (optional) an IPv4 address in host byte order, may be $(D ADDR_ANY).
1582      *   port = port number, may be $(D PORT_ANY).
1583      */
1584     this(uint addr, ushort port) pure nothrow @nogc
1585     {
1586         sin.sin_family = AddressFamily.INET;
1587         sin.sin_addr.s_addr = htonl(addr);
1588         sin.sin_port = htons(port);
1589     }
1590 
1591     /// ditto
1592     this(ushort port) pure nothrow @nogc
1593     {
1594         sin.sin_family = AddressFamily.INET;
1595         sin.sin_addr.s_addr = ADDR_ANY;
1596         sin.sin_port = htons(port);
1597     }
1598 
1599     /**
1600      * Construct a new $(D InternetAddress).
1601      * Params:
1602      *   addr = A sockaddr_in as obtained from lower-level API calls such as getifaddrs.
1603      */
1604     this(sockaddr_in addr) pure nothrow @nogc
1605     {
1606         assert(addr.sin_family == AddressFamily.INET);
1607         sin = addr;
1608     }
1609 
1610     /// Human readable string representing the IPv4 address in dotted-decimal form.
1611     override string toAddrString() @trusted const
1612     {
1613         return to!string(inet_ntoa(sin.sin_addr));
1614     }
1615 
1616     /// Human readable string representing the IPv4 port.
1617     override string toPortString() const
1618     {
1619         return std.conv.to!string(port);
1620     }
1621 
1622     /**
1623      * Attempts to retrieve the host name as a fully qualified domain name.
1624      *
1625      * Returns: The FQDN corresponding to this $(D InternetAddress), or
1626      * $(D null) if the host name did not resolve.
1627      *
1628      * Throws: $(D AddressException) on error.
1629      */
1630     override string toHostNameString() const
1631     {
1632         // getnameinfo() is the recommended way to perform a reverse (name)
1633         // lookup on both Posix and Windows. However, it is only available
1634         // on Windows XP and above, and not included with the WinSock import
1635         // libraries shipped with DMD. Thus, we check for getnameinfo at
1636         // runtime in the shared module constructor, and fall back to the
1637         // deprecated getHostByAddr() if it could not be found. See also:
1638         // http://technet.microsoft.com/en-us/library/aa450403.aspx
1639 
1640         if (getnameinfoPointer)
1641             return super.toHostNameString();
1642         else
1643         {
1644             auto host = new InternetHost();
1645             if (!host.getHostByAddr(ntohl(sin.sin_addr.s_addr)))
1646                 return null;
1647             return host.name;
1648         }
1649     }
1650 
1651     /**
1652      * Compares with another InternetAddress of same type for equality
1653      * Returns: true if the InternetAddresses share the same address and
1654      * port number.
1655      */
1656     override bool opEquals(Object o) const
1657     {
1658         auto other = cast(InternetAddress) o;
1659         return other && this.sin.sin_addr.s_addr == other.sin.sin_addr.s_addr &&
1660             this.sin.sin_port == other.sin.sin_port;
1661     }
1662 
1663     ///
1664     @system unittest
1665     {
1666         auto addr1 = new InternetAddress("127.0.0.1", 80);
1667         auto addr2 = new InternetAddress("127.0.0.2", 80);
1668 
1669         assert(addr1 == addr1);
1670         assert(addr1 != addr2);
1671     }
1672 
1673     /**
1674      * Parse an IPv4 address string in the dotted-decimal form $(I a.b.c.d)
1675      * and return the number.
1676      * Returns: If the string is not a legitimate IPv4 address,
1677      * $(D ADDR_NONE) is returned.
1678      */
1679     static uint parse(in char[] addr) @trusted nothrow
1680     {
1681         return ntohl(inet_addr(addr.tempCString()));
1682     }
1683 
1684     /**
1685      * Convert an IPv4 address number in host byte order to a human readable
1686      * string representing the IPv4 address in dotted-decimal form.
1687      */
1688     static string addrToString(uint addr) @trusted nothrow
1689     {
1690         in_addr sin_addr;
1691         sin_addr.s_addr = htonl(addr);
1692         return to!string(inet_ntoa(sin_addr));
1693     }
1694 }
1695 
1696 
1697 @safe unittest
1698 {
1699     softUnittest({
1700         const InternetAddress ia = new InternetAddress("63.105.9.61", 80);
1701         assert(ia.toString() == "63.105.9.61:80");
1702     });
1703 
1704     softUnittest({
1705         // test construction from a sockaddr_in
1706         sockaddr_in sin;
1707 
1708         sin.sin_addr.s_addr = htonl(0x7F_00_00_01);  // 127.0.0.1
1709         sin.sin_family = AddressFamily.INET;
1710         sin.sin_port = htons(80);
1711 
1712         const InternetAddress ia = new InternetAddress(sin);
1713         assert(ia.toString() == "127.0.0.1:80");
1714     });
1715 
1716     softUnittest({
1717         // test reverse lookup
1718         auto ih = new InternetHost;
1719         if (ih.getHostByName("digitalmars.com"))
1720         {
1721             const ia = new InternetAddress(ih.addrList[0], 80);
1722             assert(ia.toHostNameString() == "digitalmars.com");
1723 
1724             if (getnameinfoPointer)
1725             {
1726                 // test reverse lookup, via gethostbyaddr
1727                 auto getnameinfoPointerBackup = getnameinfoPointer;
1728                 cast() getnameinfoPointer = null;
1729                 scope(exit) cast() getnameinfoPointer = getnameinfoPointerBackup;
1730 
1731                 assert(ia.toHostNameString() == "digitalmars.com");
1732             }
1733         }
1734     });
1735 
1736     version (SlowTests)
1737     softUnittest({
1738         // test failing reverse lookup
1739         const InternetAddress ia = new InternetAddress("127.114.111.120", 80);
1740         assert(ia.toHostNameString() is null);
1741 
1742         if (getnameinfoPointer)
1743         {
1744             // test failing reverse lookup, via gethostbyaddr
1745             auto getnameinfoPointerBackup = getnameinfoPointer;
1746             getnameinfoPointer = null;
1747             scope(exit) getnameinfoPointer = getnameinfoPointerBackup;
1748 
1749             assert(ia.toHostNameString() is null);
1750         }
1751     });
1752 }
1753 
1754 
1755 /**
1756  * $(D Internet6Address) encapsulates an IPv6 (Internet Protocol version 6)
1757  * socket address.
1758  *
1759  * Consider using $(D getAddress), $(D parseAddress) and $(D Address) methods
1760  * instead of using this class directly.
1761  */
1762 class Internet6Address: Address
1763 {
1764 protected:
1765     sockaddr_in6 sin6;
1766 
1767 
1768     this() pure nothrow @nogc
1769     {
1770     }
1771 
1772 
1773 public:
1774     override @property sockaddr* name()
1775     {
1776         return cast(sockaddr*)&sin6;
1777     }
1778 
1779     override @property const(sockaddr)* name() const
1780     {
1781         return cast(const(sockaddr)*)&sin6;
1782     }
1783 
1784 
1785     override @property socklen_t nameLen() const
1786     {
1787         return cast(socklen_t) sin6.sizeof;
1788     }
1789 
1790 
1791     /// Any IPv6 host address.
1792     static @property ref const(ubyte)[16] ADDR_ANY() pure nothrow @nogc
1793     {
1794         const(ubyte)[16]* addr;
1795         static if (is(typeof(IN6ADDR_ANY)))
1796         {
1797             addr = &IN6ADDR_ANY.s6_addr;
1798             return *addr;
1799         }
1800         else static if (is(typeof(in6addr_any)))
1801         {
1802             addr = &in6addr_any.s6_addr;
1803             return *addr;
1804         }
1805         else
1806             static assert(0);
1807     }
1808 
1809     /// Any IPv6 port number.
1810     enum ushort PORT_ANY = 0;
1811 
1812     /// Returns the IPv6 port number.
1813     @property ushort port() const pure nothrow @nogc
1814     {
1815         return ntohs(sin6.sin6_port);
1816     }
1817 
1818     /// Returns the IPv6 address.
1819     @property ubyte[16] addr() const pure nothrow @nogc
1820     {
1821         return sin6.sin6_addr.s6_addr;
1822     }
1823 
1824     /**
1825      * Construct a new $(D Internet6Address).
1826      * Params:
1827      *   addr    = an IPv6 host address string in the form described in RFC 2373,
1828      *             or a host name which will be resolved using $(D getAddressInfo).
1829      *   service = (optional) service name.
1830      */
1831     this(in char[] addr, in char[] service = null) @trusted
1832     {
1833         auto results = getAddressInfo(addr, service, AddressFamily.INET6);
1834         assert(results.length && results[0].family == AddressFamily.INET6);
1835         sin6 = *cast(sockaddr_in6*) results[0].address.name;
1836     }
1837 
1838     /**
1839      * Construct a new $(D Internet6Address).
1840      * Params:
1841      *   addr = an IPv6 host address string in the form described in RFC 2373,
1842      *          or a host name which will be resolved using $(D getAddressInfo).
1843      *   port = port number, may be $(D PORT_ANY).
1844      */
1845     this(in char[] addr, ushort port)
1846     {
1847         if (port == PORT_ANY)
1848             this(addr);
1849         else
1850             this(addr, to!string(port));
1851     }
1852 
1853     /**
1854      * Construct a new $(D Internet6Address).
1855      * Params:
1856      *   addr = (optional) an IPv6 host address in host byte order, or
1857      *          $(D ADDR_ANY).
1858      *   port = port number, may be $(D PORT_ANY).
1859      */
1860     this(ubyte[16] addr, ushort port) pure nothrow @nogc
1861     {
1862         sin6.sin6_family = AddressFamily.INET6;
1863         sin6.sin6_addr.s6_addr = addr;
1864         sin6.sin6_port = htons(port);
1865     }
1866 
1867     /// ditto
1868     this(ushort port) pure nothrow @nogc
1869     {
1870         sin6.sin6_family = AddressFamily.INET6;
1871         sin6.sin6_addr.s6_addr = ADDR_ANY;
1872         sin6.sin6_port = htons(port);
1873     }
1874 
1875      /**
1876      * Construct a new $(D Internet6Address).
1877      * Params:
1878      *   addr = A sockaddr_in6 as obtained from lower-level API calls such as getifaddrs.
1879      */
1880     this(sockaddr_in6 addr) pure nothrow @nogc
1881     {
1882         assert(addr.sin6_family == AddressFamily.INET6);
1883         sin6 = addr;
1884     }
1885 
1886    /**
1887      * Parse an IPv6 host address string as described in RFC 2373, and return the
1888      * address.
1889      * Throws: $(D SocketException) on error.
1890      */
1891     static ubyte[16] parse(in char[] addr) @trusted
1892     {
1893         // Although we could use inet_pton here, it's only available on Windows
1894         // versions starting with Vista, so use getAddressInfo with NUMERICHOST
1895         // instead.
1896         auto results = getAddressInfo(addr, AddressInfoFlags.NUMERICHOST);
1897         if (results.length && results[0].family == AddressFamily.INET6)
1898             return (cast(sockaddr_in6*) results[0].address.name).sin6_addr.s6_addr;
1899         throw new AddressException("Not an IPv6 address", 0);
1900     }
1901 }
1902 
1903 
1904 @safe unittest
1905 {
1906     softUnittest({
1907         const Internet6Address ia = new Internet6Address("::1", 80);
1908         assert(ia.toString() == "[::1]:80");
1909     });
1910 
1911     softUnittest({
1912         // test construction from a sockaddr_in6
1913         sockaddr_in6 sin;
1914 
1915         sin.sin6_addr.s6_addr = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];  // [::1]
1916         sin.sin6_family = AddressFamily.INET6;
1917         sin.sin6_port = htons(80);
1918 
1919         const Internet6Address ia = new Internet6Address(sin);
1920         assert(ia.toString() == "[::1]:80");
1921     });
1922 }
1923 
1924 
1925 version (StdDdoc)
1926 {
1927     static if (!is(sockaddr_un))
1928     {
1929         // This exists only to allow the constructor taking
1930         // a sockaddr_un to be compilable for documentation
1931         // on platforms that don't supply a sockaddr_un.
1932         struct sockaddr_un
1933         {
1934         }
1935     }
1936 
1937     /**
1938      * $(D UnixAddress) encapsulates an address for a Unix domain socket
1939      * ($(D AF_UNIX)), i.e. a socket bound to a path name in the file system.
1940      * Available only on supported systems.
1941      *
1942      * Linux also supports an abstract address namespace, in which addresses
1943      * are independent of the file system. A socket address is abstract
1944      * iff `path` starts with a _null byte (`'\0'`). Null bytes in other
1945      * positions of an abstract address are allowed and have no special
1946      * meaning.
1947      *
1948      * Example:
1949      * ---
1950      * auto addr = new UnixAddress("/var/run/dbus/system_bus_socket");
1951      * auto abstractAddr = new UnixAddress("\0/tmp/dbus-OtHLWmCLPR");
1952      * ---
1953      *
1954      * See_Also: $(HTTP http://man7.org/linux/man-pages/man7/unix.7.html, UNIX(7))
1955      */
1956     class UnixAddress: Address
1957     {
1958         private this() pure nothrow @nogc {}
1959 
1960         /// Construct a new $(D UnixAddress) from the specified path.
1961         this(in char[] path) { }
1962 
1963         /**
1964          * Construct a new $(D UnixAddress).
1965          * Params:
1966          *   addr = A sockaddr_un as obtained from lower-level API calls.
1967          */
1968         this(sockaddr_un addr) pure nothrow @nogc { }
1969 
1970         /// Get the underlying _path.
1971         @property string path() const { return null; }
1972 
1973         /// ditto
1974         override string toString() const { return null; }
1975 
1976         override @property sockaddr* name() { return null; }
1977         override @property const(sockaddr)* name() const { return null; }
1978         override @property socklen_t nameLen() const { return 0; }
1979     }
1980 }
1981 else
1982 static if (is(sockaddr_un))
1983 {
1984     class UnixAddress: Address
1985     {
1986     protected:
1987         socklen_t _nameLen;
1988 
1989         struct
1990         {
1991         align (1):
1992             sockaddr_un sun;
1993             char unused = '\0'; // placeholder for a terminating '\0'
1994         }
1995 
1996         this() pure nothrow @nogc
1997         {
1998             sun.sun_family = AddressFamily.UNIX;
1999             sun.sun_path = '?';
2000             _nameLen = sun.sizeof;
2001         }
2002 
2003         override void setNameLen(socklen_t len) @trusted
2004         {
2005             if (len > sun.sizeof)
2006                 throw new SocketParameterException("Not enough socket address storage");
2007             _nameLen = len;
2008         }
2009 
2010     public:
2011         override @property sockaddr* name()
2012         {
2013             return cast(sockaddr*)&sun;
2014         }
2015 
2016         override @property const(sockaddr)* name() const
2017         {
2018             return cast(const(sockaddr)*)&sun;
2019         }
2020 
2021         override @property socklen_t nameLen() @trusted const
2022         {
2023             return _nameLen;
2024         }
2025 
2026         this(in char[] path) @trusted pure
2027         {
2028             enforce(path.length <= sun.sun_path.sizeof, new SocketParameterException("Path too long"));
2029             sun.sun_family = AddressFamily.UNIX;
2030             sun.sun_path.ptr[0 .. path.length] = (cast(byte[]) path)[];
2031             _nameLen = cast(socklen_t)
2032                 {
2033                     auto len = sockaddr_un.init.sun_path.offsetof + path.length;
2034                     // Pathname socket address must be terminated with '\0'
2035                     // which must be included in the address length.
2036                     if (sun.sun_path.ptr[0])
2037                     {
2038                         sun.sun_path.ptr[path.length] = 0;
2039                         ++len;
2040                     }
2041                     return len;
2042                 }();
2043         }
2044 
2045         this(sockaddr_un addr) pure nothrow @nogc
2046         {
2047             assert(addr.sun_family == AddressFamily.UNIX);
2048             sun = addr;
2049         }
2050 
2051         @property string path() @trusted const pure
2052         {
2053             auto len = _nameLen - sockaddr_un.init.sun_path.offsetof;
2054             // For pathname socket address we need to strip off the terminating '\0'
2055             if (sun.sun_path.ptr[0])
2056                 --len;
2057             return (cast(const(char)*) sun.sun_path.ptr)[0 .. len].idup;
2058         }
2059 
2060         override string toString() const pure
2061         {
2062             return path;
2063         }
2064     }
2065 
2066     @safe unittest
2067     {
2068         import core.stdc.stdio : remove;
2069         import std.file : deleteme;
2070 
2071         immutable ubyte[] data = [1, 2, 3, 4];
2072         Socket[2] pair;
2073 
2074         auto names = [ deleteme ~ "-unix-socket" ];
2075         version (linux)
2076             names ~= "\0" ~ deleteme ~ "-abstract\0unix\0socket";
2077         foreach (name; names)
2078         {
2079             auto address = new UnixAddress(name);
2080 
2081             auto listener = new Socket(AddressFamily.UNIX, SocketType.STREAM);
2082             scope(exit) listener.close();
2083             listener.bind(address);
2084             scope(exit) () @trusted { if (name[0]) remove(name.tempCString()); } ();
2085             assert(listener.localAddress.toString == name);
2086 
2087             listener.listen(1);
2088 
2089             pair[0] = new Socket(AddressFamily.UNIX, SocketType.STREAM);
2090             scope(exit) listener.close();
2091 
2092             pair[0].connect(address);
2093             scope(exit) pair[0].close();
2094 
2095             pair[1] = listener.accept();
2096             scope(exit) pair[1].close();
2097 
2098             pair[0].send(data);
2099 
2100             auto buf = new ubyte[data.length];
2101             pair[1].receive(buf);
2102             assert(buf == data);
2103         }
2104     }
2105 }
2106 
2107 
2108 /**
2109  * Class for exceptions thrown by $(D Socket.accept).
2110  */
2111 class SocketAcceptException: SocketOSException
2112 {
2113     mixin socketOSExceptionCtors;
2114 }
2115 
2116 /// How a socket is shutdown:
2117 enum SocketShutdown: int
2118 {
2119     RECEIVE =  SD_RECEIVE,      /// socket receives are disallowed
2120     SEND =     SD_SEND,         /// socket sends are disallowed
2121     BOTH =     SD_BOTH,         /// both RECEIVE and SEND
2122 }
2123 
2124 
2125 /// Flags may be OR'ed together:
2126 enum SocketFlags: int
2127 {
2128     NONE =       0,                 /// no flags specified
2129 
2130     OOB =        MSG_OOB,           /// out-of-band stream data
2131     PEEK =       MSG_PEEK,          /// peek at incoming data without removing it from the queue, only for receiving
2132     DONTROUTE =  MSG_DONTROUTE,     /// data should not be subject to routing; this flag may be ignored. Only for sending
2133 }
2134 
2135 
2136 private mixin template FieldProxy(string target, string field)
2137 {
2138     mixin(`
2139         @property typeof(`~target~`) `~field~`() const pure nothrow @nogc
2140         {
2141             return `~target~`;
2142         }
2143 
2144         /// ditto
2145         @property typeof(`~target~`) `~field~`(typeof(`~target~`) value) pure nothrow @nogc
2146         {
2147             return `~target~` = value;
2148         }
2149     `);
2150 }
2151 
2152 
2153 /// Duration timeout value.
2154 struct TimeVal
2155 {
2156     _ctimeval ctimeval;
2157     alias tv_sec_t = typeof(ctimeval.tv_sec);
2158     alias tv_usec_t = typeof(ctimeval.tv_usec);
2159 
2160     version (StdDdoc) // no DDoc for string mixins, can't forward individual fields
2161     {
2162         tv_sec_t seconds;           /// Number of _seconds.
2163         tv_usec_t microseconds;     /// Number of additional _microseconds.
2164     }
2165     else
2166     {
2167         // D interface
2168         mixin FieldProxy!(`ctimeval.tv_sec`, `seconds`);
2169         mixin FieldProxy!(`ctimeval.tv_usec`, `microseconds`);
2170     }
2171 }
2172 
2173 
2174 /**
2175  * A collection of sockets for use with $(D Socket.select).
2176  *
2177  * $(D SocketSet) wraps the platform $(D fd_set) type. However, unlike
2178  * $(D fd_set), $(D SocketSet) is not statically limited to $(D FD_SETSIZE)
2179  * or any other limit, and grows as needed.
2180  */
2181 class SocketSet
2182 {
2183 private:
2184     version (Windows)
2185     {
2186         // On Windows, fd_set is an array of socket handles,
2187         // following a word containing the fd_set instance size.
2188         // We use one dynamic array for everything, and use its first
2189         // element(s) for the count.
2190 
2191         alias fd_set_count_type = typeof(fd_set.init.fd_count);
2192         alias fd_set_type = typeof(fd_set.init.fd_array[0]);
2193         static assert(fd_set_type.sizeof == socket_t.sizeof);
2194 
2195         // Number of fd_set_type elements at the start of our array that are
2196         // used for the socket count and alignment
2197 
2198         enum FD_SET_OFFSET = fd_set.fd_array.offsetof / fd_set_type.sizeof;
2199         static assert(FD_SET_OFFSET);
2200         static assert(fd_set.fd_count.offsetof % fd_set_type.sizeof == 0);
2201 
2202         fd_set_type[] set;
2203 
2204         void resize(size_t size) pure nothrow
2205         {
2206             set.length = FD_SET_OFFSET + size;
2207         }
2208 
2209         ref inout(fd_set_count_type) count() @trusted @property inout pure nothrow @nogc
2210         {
2211             assert(set.length);
2212             return *cast(inout(fd_set_count_type)*)set.ptr;
2213         }
2214 
2215         size_t capacity() @property const pure nothrow @nogc
2216         {
2217             return set.length - FD_SET_OFFSET;
2218         }
2219 
2220         inout(socket_t)[] fds() @trusted inout @property pure nothrow @nogc
2221         {
2222             return cast(inout(socket_t)[])set[FD_SET_OFFSET .. FD_SET_OFFSET+count];
2223         }
2224     }
2225     else
2226     version (Posix)
2227     {
2228         // On Posix, fd_set is a bit array. We assume that the fd_set
2229         // type (declared in core.sys.posix.sys.select) is a structure
2230         // containing a single field, a static array.
2231 
2232         static assert(fd_set.tupleof.length == 1);
2233 
2234         // This is the type used in the fd_set array.
2235         // Using the type of the correct size is important for big-endian
2236         // architectures.
2237 
2238         alias fd_set_type = typeof(fd_set.init.tupleof[0][0]);
2239 
2240         // Number of file descriptors represented by one fd_set_type
2241 
2242         enum FD_NFDBITS = 8 * fd_set_type.sizeof;
2243 
2244         static fd_set_type mask(uint n) pure nothrow @nogc
2245         {
2246             return (cast(fd_set_type) 1) << (n % FD_NFDBITS);
2247         }
2248 
2249         // Array size to fit that many sockets
2250 
2251         static size_t lengthFor(size_t size) pure nothrow @nogc
2252         {
2253             return (size + (FD_NFDBITS-1)) / FD_NFDBITS;
2254         }
2255 
2256         fd_set_type[] set;
2257 
2258         void resize(size_t size) pure nothrow
2259         {
2260             set.length = lengthFor(size);
2261         }
2262 
2263         // Make sure we can fit that many sockets
2264 
2265         void setMinCapacity(size_t size) pure nothrow
2266         {
2267             auto length = lengthFor(size);
2268             if (set.length < length)
2269                 set.length = length;
2270         }
2271 
2272         size_t capacity() @property const pure nothrow @nogc
2273         {
2274             return set.length * FD_NFDBITS;
2275         }
2276 
2277         int maxfd;
2278     }
2279     else
2280         static assert(false, "Unknown platform");
2281 
2282 public:
2283 
2284     /**
2285      * Create a SocketSet with a specific initial capacity (defaults to
2286      * $(D FD_SETSIZE), the system's default capacity).
2287      */
2288     this(size_t size = FD_SETSIZE) pure nothrow
2289     {
2290         resize(size);
2291         reset();
2292     }
2293 
2294     /// Reset the $(D SocketSet) so that there are 0 $(D Socket)s in the collection.
2295     void reset() pure nothrow @nogc
2296     {
2297         version (Windows)
2298             count = 0;
2299         else
2300         {
2301             set[] = 0;
2302             maxfd = -1;
2303         }
2304     }
2305 
2306 
2307     void add(socket_t s) @trusted pure nothrow
2308     {
2309         version (Windows)
2310         {
2311             if (count == capacity)
2312             {
2313                 set.length *= 2;
2314                 set.length = set.capacity;
2315             }
2316             ++count;
2317             fds[$-1] = s;
2318         }
2319         else
2320         {
2321             auto index = s / FD_NFDBITS;
2322             auto length = set.length;
2323             if (index >= length)
2324             {
2325                 while (index >= length)
2326                     length *= 2;
2327                 set.length = length;
2328                 set.length = set.capacity;
2329             }
2330             set[index] |= mask(s);
2331             if (maxfd < s)
2332                 maxfd = s;
2333         }
2334     }
2335 
2336     /**
2337      * Add a $(D Socket) to the collection.
2338      * The socket must not already be in the collection.
2339      */
2340     void add(Socket s) pure nothrow
2341     {
2342         add(s.sock);
2343     }
2344 
2345     void remove(socket_t s) pure nothrow
2346     {
2347         version (Windows)
2348         {
2349             import std.algorithm.searching : countUntil;
2350             auto fds = fds;
2351             auto p = fds.countUntil(s);
2352             if (p >= 0)
2353                 fds[p] = fds[--count];
2354         }
2355         else
2356         {
2357             auto index = s / FD_NFDBITS;
2358             if (index >= set.length)
2359                 return;
2360             set[index] &= ~mask(s);
2361             // note: adjusting maxfd would require scanning the set, not worth it
2362         }
2363     }
2364 
2365 
2366     /**
2367      * Remove this $(D Socket) from the collection.
2368      * Does nothing if the socket is not in the collection already.
2369      */
2370     void remove(Socket s) pure nothrow
2371     {
2372         remove(s.sock);
2373     }
2374 
2375     int isSet(socket_t s) const pure nothrow @nogc
2376     {
2377         version (Windows)
2378         {
2379             import std.algorithm.searching : canFind;
2380             return fds.canFind(s) ? 1 : 0;
2381         }
2382         else
2383         {
2384             if (s > maxfd)
2385                 return 0;
2386             auto index = s / FD_NFDBITS;
2387             return (set[index] & mask(s)) ? 1 : 0;
2388         }
2389     }
2390 
2391 
2392     /// Return nonzero if this $(D Socket) is in the collection.
2393     int isSet(Socket s) const pure nothrow @nogc
2394     {
2395         return isSet(s.sock);
2396     }
2397 
2398 
2399     /**
2400      * Returns:
2401      * The current capacity of this $(D SocketSet). The exact
2402      * meaning of the return value varies from platform to platform.
2403      *
2404      * Note:
2405      * Since D 2.065, this value does not indicate a
2406      * restriction, and $(D SocketSet) will grow its capacity as
2407      * needed automatically.
2408      */
2409     @property uint max() const pure nothrow @nogc
2410     {
2411         return cast(uint) capacity;
2412     }
2413 
2414 
2415     fd_set* toFd_set() @trusted pure nothrow @nogc
2416     {
2417         return cast(fd_set*) set.ptr;
2418     }
2419 
2420 
2421     int selectn() const pure nothrow @nogc
2422     {
2423         version (Windows)
2424         {
2425             return count;
2426         }
2427         else version (Posix)
2428         {
2429             return maxfd + 1;
2430         }
2431     }
2432 }
2433 
2434 @safe unittest
2435 {
2436     auto fds = cast(socket_t[])
2437         [cast(socket_t) 1, 2, 0, 1024, 17, 42, 1234, 77, 77+32, 77+64];
2438     auto set = new SocketSet();
2439     foreach (fd; fds) assert(!set.isSet(fd));
2440     foreach (fd; fds) set.add(fd);
2441     foreach (fd; fds) assert(set.isSet(fd));
2442 
2443     // Make sure SocketSet reimplements fd_set correctly
2444     auto fdset = set.toFd_set();
2445     foreach (fd; fds[0]..cast(socket_t)(fds[$-1]+1))
2446         assert(cast(bool) set.isSet(fd) == cast(bool)(() @trusted => FD_ISSET(fd, fdset))());
2447 
2448     foreach (fd; fds)
2449     {
2450         assert(set.isSet(fd));
2451         set.remove(fd);
2452         assert(!set.isSet(fd));
2453     }
2454 }
2455 
2456 @safe unittest
2457 {
2458     softUnittest({
2459         enum PAIRS = 768;
2460         version (Posix)
2461         () @trusted
2462         {
2463             enum LIMIT = 2048;
2464             static assert(LIMIT > PAIRS*2);
2465             import core.sys.posix.sys.resource;
2466             rlimit fileLimit;
2467             getrlimit(RLIMIT_NOFILE, &fileLimit);
2468             assert(fileLimit.rlim_max > LIMIT, "Open file hard limit too low");
2469             fileLimit.rlim_cur = LIMIT;
2470             setrlimit(RLIMIT_NOFILE, &fileLimit);
2471         } ();
2472 
2473         Socket[2][PAIRS] pairs;
2474         foreach (ref pair; pairs)
2475             pair = socketPair();
2476         scope(exit)
2477         {
2478             foreach (pair; pairs)
2479             {
2480                 pair[0].close();
2481                 pair[1].close();
2482             }
2483         }
2484 
2485         import std.random;
2486         auto rng = Xorshift(42);
2487         pairs[].randomShuffle(rng);
2488 
2489         auto readSet = new SocketSet();
2490         auto writeSet = new SocketSet();
2491         auto errorSet = new SocketSet();
2492 
2493         foreach (testPair; pairs)
2494         {
2495             void fillSets()
2496             {
2497                 readSet.reset();
2498                 writeSet.reset();
2499                 errorSet.reset();
2500                 foreach (ref pair; pairs)
2501                     foreach (s; pair[])
2502                     {
2503                         readSet.add(s);
2504                         writeSet.add(s);
2505                         errorSet.add(s);
2506                     }
2507             }
2508 
2509             fillSets();
2510             auto n = Socket.select(readSet, writeSet, errorSet);
2511             assert(n == PAIRS*2); // All in writeSet
2512             assert(writeSet.isSet(testPair[0]));
2513             assert(writeSet.isSet(testPair[1]));
2514             assert(!readSet.isSet(testPair[0]));
2515             assert(!readSet.isSet(testPair[1]));
2516             assert(!errorSet.isSet(testPair[0]));
2517             assert(!errorSet.isSet(testPair[1]));
2518 
2519             ubyte[1] b;
2520             testPair[0].send(b[]);
2521             fillSets();
2522             n = Socket.select(readSet, null, null);
2523             assert(n == 1); // testPair[1]
2524             assert(readSet.isSet(testPair[1]));
2525             assert(!readSet.isSet(testPair[0]));
2526             testPair[1].receive(b[]);
2527         }
2528     });
2529 }
2530 
2531 @safe unittest // Issue 14012, 14013
2532 {
2533     auto set = new SocketSet(1);
2534     assert(set.max >= 0);
2535 
2536     enum LIMIT = 4096;
2537     foreach (n; 0 .. LIMIT)
2538         set.add(cast(socket_t) n);
2539     assert(set.max >= LIMIT);
2540 }
2541 
2542 /// The level at which a socket option is defined:
2543 enum SocketOptionLevel: int
2544 {
2545     SOCKET =  SOL_SOCKET,               /// Socket level
2546     IP =      ProtocolType.IP,          /// Internet Protocol version 4 level
2547     ICMP =    ProtocolType.ICMP,        /// Internet Control Message Protocol level
2548     IGMP =    ProtocolType.IGMP,        /// Internet Group Management Protocol level
2549     GGP =     ProtocolType.GGP,         /// Gateway to Gateway Protocol level
2550     TCP =     ProtocolType.TCP,         /// Transmission Control Protocol level
2551     PUP =     ProtocolType.PUP,         /// PARC Universal Packet Protocol level
2552     UDP =     ProtocolType.UDP,         /// User Datagram Protocol level
2553     IDP =     ProtocolType.IDP,         /// Xerox NS protocol level
2554     RAW =     ProtocolType.RAW,         /// Raw IP packet level
2555     IPV6 =    ProtocolType.IPV6,        /// Internet Protocol version 6 level
2556 }
2557 
2558 /// _Linger information for use with SocketOption.LINGER.
2559 struct Linger
2560 {
2561     _clinger clinger;
2562 
2563     version (StdDdoc) // no DDoc for string mixins, can't forward individual fields
2564     {
2565         private alias l_onoff_t = typeof(_clinger.init.l_onoff );
2566         private alias l_linger_t = typeof(_clinger.init.l_linger);
2567         l_onoff_t  on;   /// Nonzero for _on.
2568         l_linger_t time; /// Linger _time.
2569     }
2570     else
2571     {
2572         // D interface
2573         mixin FieldProxy!(`clinger.l_onoff`, `on`);
2574         mixin FieldProxy!(`clinger.l_linger`, `time`);
2575     }
2576 }
2577 
2578 /// Specifies a socket option:
2579 enum SocketOption: int
2580 {
2581     DEBUG =                SO_DEBUG,            /// Record debugging information
2582     BROADCAST =            SO_BROADCAST,        /// Allow transmission of broadcast messages
2583     REUSEADDR =            SO_REUSEADDR,        /// Allow local reuse of address
2584     LINGER =               SO_LINGER,           /// Linger on close if unsent data is present
2585     OOBINLINE =            SO_OOBINLINE,        /// Receive out-of-band data in band
2586     SNDBUF =               SO_SNDBUF,           /// Send buffer size
2587     RCVBUF =               SO_RCVBUF,           /// Receive buffer size
2588     DONTROUTE =            SO_DONTROUTE,        /// Do not route
2589     SNDTIMEO =             SO_SNDTIMEO,         /// Send timeout
2590     RCVTIMEO =             SO_RCVTIMEO,         /// Receive timeout
2591     ERROR =                SO_ERROR,            /// Retrieve and clear error status
2592     KEEPALIVE =            SO_KEEPALIVE,        /// Enable keep-alive packets
2593     ACCEPTCONN =           SO_ACCEPTCONN,       /// Listen
2594     RCVLOWAT =             SO_RCVLOWAT,         /// Minimum number of input bytes to process
2595     SNDLOWAT =             SO_SNDLOWAT,         /// Minimum number of output bytes to process
2596     TYPE =                 SO_TYPE,             /// Socket type
2597 
2598     // SocketOptionLevel.TCP:
2599     TCP_NODELAY =          .TCP_NODELAY,        /// Disable the Nagle algorithm for send coalescing
2600 
2601     // SocketOptionLevel.IPV6:
2602     IPV6_UNICAST_HOPS =    .IPV6_UNICAST_HOPS,          /// IP unicast hop limit
2603     IPV6_MULTICAST_IF =    .IPV6_MULTICAST_IF,          /// IP multicast interface
2604     IPV6_MULTICAST_LOOP =  .IPV6_MULTICAST_LOOP,        /// IP multicast loopback
2605     IPV6_MULTICAST_HOPS =  .IPV6_MULTICAST_HOPS,        /// IP multicast hops
2606     IPV6_JOIN_GROUP =      .IPV6_JOIN_GROUP,            /// Add an IP group membership
2607     IPV6_LEAVE_GROUP =     .IPV6_LEAVE_GROUP,           /// Drop an IP group membership
2608     IPV6_V6ONLY =          .IPV6_V6ONLY,                /// Treat wildcard bind as AF_INET6-only
2609 }
2610 
2611 
2612 /**
2613  * $(D Socket) is a class that creates a network communication endpoint using
2614  * the Berkeley sockets interface.
2615  */
2616 class Socket
2617 {
2618 private:
2619     socket_t sock;
2620     AddressFamily _family;
2621 
2622     version (Windows)
2623         bool _blocking = false;         /// Property to get or set whether the socket is blocking or nonblocking.
2624 
2625     // The WinSock timeouts seem to be effectively skewed by a constant
2626     // offset of about half a second (value in milliseconds). This has
2627     // been confirmed on updated (as of Jun 2011) Windows XP, Windows 7
2628     // and Windows Server 2008 R2 boxes. The unittest below tests this
2629     // behavior.
2630     enum WINSOCK_TIMEOUT_SKEW = 500;
2631 
2632     @safe unittest
2633     {
2634         version (SlowTests)
2635         softUnittest({
2636             import std.datetime;
2637             import std.typecons;
2638 
2639             enum msecs = 1000;
2640             auto pair = socketPair();
2641             auto sock = pair[0];
2642             sock.setOption(SocketOptionLevel.SOCKET,
2643                 SocketOption.RCVTIMEO, dur!"msecs"(msecs));
2644 
2645             auto sw = StopWatch(Yes.autoStart);
2646             ubyte[1] buf;
2647             sock.receive(buf);
2648             sw.stop();
2649 
2650             Duration readBack = void;
2651             sock.getOption(SocketOptionLevel.SOCKET, SocketOption.RCVTIMEO, readBack);
2652 
2653             assert(readBack.total!"msecs" == msecs);
2654             assert(sw.peek().msecs > msecs-100 && sw.peek().msecs < msecs+100);
2655         });
2656     }
2657 
2658     void setSock(socket_t handle)
2659     {
2660         assert(handle != socket_t.init);
2661         sock = handle;
2662 
2663         // Set the option to disable SIGPIPE on send() if the platform
2664         // has it (e.g. on OS X).
2665         static if (is(typeof(SO_NOSIGPIPE)))
2666         {
2667             setOption(SocketOptionLevel.SOCKET, cast(SocketOption) SO_NOSIGPIPE, true);
2668         }
2669     }
2670 
2671 
2672     // For use with accepting().
2673     protected this() pure nothrow @nogc
2674     {
2675     }
2676 
2677 
2678 public:
2679 
2680     /**
2681      * Create a blocking socket. If a single protocol type exists to support
2682      * this socket type within the address family, the $(D ProtocolType) may be
2683      * omitted.
2684      */
2685     this(AddressFamily af, SocketType type, ProtocolType protocol) @trusted
2686     {
2687         _family = af;
2688         auto handle = cast(socket_t) socket(af, type, protocol);
2689         if (handle == socket_t.init)
2690             throw new SocketOSException("Unable to create socket");
2691         setSock(handle);
2692     }
2693 
2694     /// ditto
2695     this(AddressFamily af, SocketType type)
2696     {
2697         /* A single protocol exists to support this socket type within the
2698          * protocol family, so the ProtocolType is assumed.
2699          */
2700         this(af, type, cast(ProtocolType) 0);         // Pseudo protocol number.
2701     }
2702 
2703 
2704     /// ditto
2705     this(AddressFamily af, SocketType type, in char[] protocolName) @trusted
2706     {
2707         protoent* proto;
2708         proto = getprotobyname(protocolName.tempCString());
2709         if (!proto)
2710             throw new SocketOSException("Unable to find the protocol");
2711         this(af, type, cast(ProtocolType) proto.p_proto);
2712     }
2713 
2714 
2715     /**
2716      * Create a blocking socket using the parameters from the specified
2717      * $(D AddressInfo) structure.
2718      */
2719     this(in AddressInfo info)
2720     {
2721         this(info.family, info.type, info.protocol);
2722     }
2723 
2724     /// Use an existing socket handle.
2725     this(socket_t sock, AddressFamily af) pure nothrow @nogc
2726     {
2727         assert(sock != socket_t.init);
2728         this.sock = sock;
2729         this._family = af;
2730     }
2731 
2732 
2733     ~this() nothrow @nogc
2734     {
2735         close();
2736     }
2737 
2738 
2739     /// Get underlying socket handle.
2740     @property socket_t handle() const pure nothrow @nogc
2741     {
2742         return sock;
2743     }
2744 
2745     /**
2746      * Get/set socket's blocking flag.
2747      *
2748      * When a socket is blocking, calls to receive(), accept(), and send()
2749      * will block and wait for data/action.
2750      * A non-blocking socket will immediately return instead of blocking.
2751      */
2752     @property bool blocking() @trusted const nothrow @nogc
2753     {
2754         version (Windows)
2755         {
2756             return _blocking;
2757         }
2758         else version (Posix)
2759         {
2760             return !(fcntl(handle, F_GETFL, 0) & O_NONBLOCK);
2761         }
2762     }
2763 
2764     /// ditto
2765     @property void blocking(bool byes) @trusted
2766     {
2767         version (Windows)
2768         {
2769             uint num = !byes;
2770             if (_SOCKET_ERROR == ioctlsocket(sock, FIONBIO, &num))
2771                 goto err;
2772             _blocking = byes;
2773         }
2774         else version (Posix)
2775         {
2776             int x = fcntl(sock, F_GETFL, 0);
2777             if (-1 == x)
2778                 goto err;
2779             if (byes)
2780                 x &= ~O_NONBLOCK;
2781             else
2782                 x |= O_NONBLOCK;
2783             if (-1 == fcntl(sock, F_SETFL, x))
2784                 goto err;
2785         }
2786         return;         // Success.
2787 
2788  err:
2789         throw new SocketOSException("Unable to set socket blocking");
2790     }
2791 
2792 
2793     /// Get the socket's address family.
2794     @property AddressFamily addressFamily()
2795     {
2796         return _family;
2797     }
2798 
2799     /// Property that indicates if this is a valid, alive socket.
2800     @property bool isAlive() @trusted const
2801     {
2802         int type;
2803         socklen_t typesize = cast(socklen_t) type.sizeof;
2804         return !getsockopt(sock, SOL_SOCKET, SO_TYPE, cast(char*)&type, &typesize);
2805     }
2806 
2807     /// Associate a local address with this socket.
2808     void bind(Address addr) @trusted
2809     {
2810         if (_SOCKET_ERROR == .bind(sock, addr.name, addr.nameLen))
2811             throw new SocketOSException("Unable to bind socket");
2812     }
2813 
2814     /**
2815      * Establish a connection. If the socket is blocking, connect waits for
2816      * the connection to be made. If the socket is nonblocking, connect
2817      * returns immediately and the connection attempt is still in progress.
2818      */
2819     void connect(Address to) @trusted
2820     {
2821         if (_SOCKET_ERROR == .connect(sock, to.name, to.nameLen))
2822         {
2823             int err;
2824             err = _lasterr();
2825 
2826             if (!blocking)
2827             {
2828                 version (Windows)
2829                 {
2830                     if (WSAEWOULDBLOCK == err)
2831                         return;
2832                 }
2833                 else version (Posix)
2834                 {
2835                     if (EINPROGRESS == err)
2836                         return;
2837                 }
2838                 else
2839                 {
2840                     static assert(0);
2841                 }
2842             }
2843             throw new SocketOSException("Unable to connect socket", err);
2844         }
2845     }
2846 
2847     /**
2848      * Listen for an incoming connection. $(D bind) must be called before you
2849      * can $(D listen). The $(D backlog) is a request of how many pending
2850      * incoming connections are queued until $(D accept)ed.
2851      */
2852     void listen(int backlog) @trusted
2853     {
2854         if (_SOCKET_ERROR == .listen(sock, backlog))
2855             throw new SocketOSException("Unable to listen on socket");
2856     }
2857 
2858     /**
2859      * Called by $(D accept) when a new $(D Socket) must be created for a new
2860      * connection. To use a derived class, override this method and return an
2861      * instance of your class. The returned $(D Socket)'s handle must not be
2862      * set; $(D Socket) has a protected constructor $(D this()) to use in this
2863      * situation.
2864      *
2865      * Override to use a derived class.
2866      * The returned socket's handle must not be set.
2867      */
2868     protected Socket accepting() pure nothrow
2869     {
2870         return new Socket;
2871     }
2872 
2873     /**
2874      * Accept an incoming connection. If the socket is blocking, $(D accept)
2875      * waits for a connection request. Throws $(D SocketAcceptException) if
2876      * unable to _accept. See $(D accepting) for use with derived classes.
2877      */
2878     Socket accept() @trusted
2879     {
2880         auto newsock = cast(socket_t).accept(sock, null, null);
2881         if (socket_t.init == newsock)
2882             throw new SocketAcceptException("Unable to accept socket connection");
2883 
2884         Socket newSocket;
2885         try
2886         {
2887             newSocket = accepting();
2888             assert(newSocket.sock == socket_t.init);
2889 
2890             newSocket.setSock(newsock);
2891             version (Windows)
2892                 newSocket._blocking = _blocking;                 //inherits blocking mode
2893             newSocket._family = _family;             //same family
2894         }
2895         catch (Throwable o)
2896         {
2897             _close(newsock);
2898             throw o;
2899         }
2900 
2901         return newSocket;
2902     }
2903 
2904     /// Disables sends and/or receives.
2905     void shutdown(SocketShutdown how) @trusted nothrow @nogc
2906     {
2907         .shutdown(sock, cast(int) how);
2908     }
2909 
2910 
2911     private static void _close(socket_t sock) @system nothrow @nogc
2912     {
2913         version (Windows)
2914         {
2915             .closesocket(sock);
2916         }
2917         else version (Posix)
2918         {
2919             .close(sock);
2920         }
2921     }
2922 
2923 
2924     /**
2925      * Immediately drop any connections and release socket resources.
2926      * Calling $(D shutdown) before $(D close) is recommended for
2927      * connection-oriented sockets. The $(D Socket) object is no longer
2928      * usable after $(D close).
2929      * Calling shutdown() before this is recommended
2930      * for connection-oriented sockets.
2931      */
2932     void close() @trusted nothrow @nogc
2933     {
2934         _close(sock);
2935         sock = socket_t.init;
2936     }
2937 
2938 
2939     /**
2940      * Returns: the local machine's host name
2941      */
2942     static @property string hostName() @trusted     // getter
2943     {
2944         char[256] result;         // Host names are limited to 255 chars.
2945         if (_SOCKET_ERROR == .gethostname(result.ptr, result.length))
2946             throw new SocketOSException("Unable to obtain host name");
2947         return to!string(result.ptr);
2948     }
2949 
2950     /// Remote endpoint $(D Address).
2951     @property Address remoteAddress() @trusted
2952     {
2953         Address addr = createAddress();
2954         socklen_t nameLen = addr.nameLen;
2955         if (_SOCKET_ERROR == .getpeername(sock, addr.name, &nameLen))
2956             throw new SocketOSException("Unable to obtain remote socket address");
2957         addr.setNameLen(nameLen);
2958         assert(addr.addressFamily == _family);
2959         return addr;
2960     }
2961 
2962     /// Local endpoint $(D Address).
2963     @property Address localAddress() @trusted
2964     {
2965         Address addr = createAddress();
2966         socklen_t nameLen = addr.nameLen;
2967         if (_SOCKET_ERROR == .getsockname(sock, addr.name, &nameLen))
2968             throw new SocketOSException("Unable to obtain local socket address");
2969         addr.setNameLen(nameLen);
2970         assert(addr.addressFamily == _family);
2971         return addr;
2972     }
2973 
2974     /**
2975      * Send or receive error code. See $(D wouldHaveBlocked),
2976      * $(D lastSocketError) and $(D Socket.getErrorText) for obtaining more
2977      * information about the error.
2978      */
2979     enum int ERROR = _SOCKET_ERROR;
2980 
2981     private static int capToInt(size_t size) nothrow @nogc
2982     {
2983         // Windows uses int instead of size_t for length arguments.
2984         // Luckily, the send/recv functions make no guarantee that
2985         // all the data is sent, so we use that to send at most
2986         // int.max bytes.
2987         return size > size_t(int.max) ? int.max : cast(int) size;
2988     }
2989 
2990     /**
2991      * Send data on the connection. If the socket is blocking and there is no
2992      * buffer space left, $(D send) waits.
2993      * Returns: The number of bytes actually sent, or $(D Socket.ERROR) on
2994      * failure.
2995      */
2996     ptrdiff_t send(const(void)[] buf, SocketFlags flags) @trusted
2997     {
2998         static if (is(typeof(MSG_NOSIGNAL)))
2999         {
3000             flags = cast(SocketFlags)(flags | MSG_NOSIGNAL);
3001         }
3002         version (Windows)
3003             auto sent = .send(sock, buf.ptr, capToInt(buf.length), cast(int) flags);
3004         else
3005             auto sent = .send(sock, buf.ptr, buf.length, cast(int) flags);
3006         return sent;
3007     }
3008 
3009     /// ditto
3010     ptrdiff_t send(const(void)[] buf)
3011     {
3012         return send(buf, SocketFlags.NONE);
3013     }
3014 
3015     /**
3016      * Send data to a specific destination Address. If the destination address is
3017      * not specified, a connection must have been made and that address is used.
3018      * If the socket is blocking and there is no buffer space left, $(D sendTo) waits.
3019      * Returns: The number of bytes actually sent, or $(D Socket.ERROR) on
3020      * failure.
3021      */
3022     ptrdiff_t sendTo(const(void)[] buf, SocketFlags flags, Address to) @trusted
3023     {
3024         static if (is(typeof(MSG_NOSIGNAL)))
3025         {
3026             flags = cast(SocketFlags)(flags | MSG_NOSIGNAL);
3027         }
3028         version (Windows)
3029             return .sendto(
3030                        sock, buf.ptr, capToInt(buf.length),
3031                        cast(int) flags, to.name, to.nameLen
3032                        );
3033         else
3034             return .sendto(sock, buf.ptr, buf.length, cast(int) flags, to.name, to.nameLen);
3035     }
3036 
3037     /// ditto
3038     ptrdiff_t sendTo(const(void)[] buf, Address to)
3039     {
3040         return sendTo(buf, SocketFlags.NONE, to);
3041     }
3042 
3043 
3044     //assumes you connect()ed
3045     /// ditto
3046     ptrdiff_t sendTo(const(void)[] buf, SocketFlags flags) @trusted
3047     {
3048         static if (is(typeof(MSG_NOSIGNAL)))
3049         {
3050             flags = cast(SocketFlags)(flags | MSG_NOSIGNAL);
3051         }
3052         version (Windows)
3053             return .sendto(sock, buf.ptr, capToInt(buf.length), cast(int) flags, null, 0);
3054         else
3055             return .sendto(sock, buf.ptr, buf.length, cast(int) flags, null, 0);
3056     }
3057 
3058 
3059     //assumes you connect()ed
3060     /// ditto
3061     ptrdiff_t sendTo(const(void)[] buf)
3062     {
3063         return sendTo(buf, SocketFlags.NONE);
3064     }
3065 
3066 
3067     /**
3068      * Receive data on the connection. If the socket is blocking, $(D receive)
3069      * waits until there is data to be received.
3070      * Returns: The number of bytes actually received, $(D 0) if the remote side
3071      * has closed the connection, or $(D Socket.ERROR) on failure.
3072      */
3073     ptrdiff_t receive(void[] buf, SocketFlags flags) @trusted
3074     {
3075         version (Windows)         // Does not use size_t
3076         {
3077             return buf.length
3078                    ? .recv(sock, buf.ptr, capToInt(buf.length), cast(int) flags)
3079                    : 0;
3080         }
3081         else
3082         {
3083             return buf.length
3084                    ? .recv(sock, buf.ptr, buf.length, cast(int) flags)
3085                    : 0;
3086         }
3087     }
3088 
3089     /// ditto
3090     ptrdiff_t receive(void[] buf)
3091     {
3092         return receive(buf, SocketFlags.NONE);
3093     }
3094 
3095     /**
3096      * Receive data and get the remote endpoint $(D Address).
3097      * If the socket is blocking, $(D receiveFrom) waits until there is data to
3098      * be received.
3099      * Returns: The number of bytes actually received, $(D 0) if the remote side
3100      * has closed the connection, or $(D Socket.ERROR) on failure.
3101      */
3102     ptrdiff_t receiveFrom(void[] buf, SocketFlags flags, ref Address from) @trusted
3103     {
3104         if (!buf.length)         //return 0 and don't think the connection closed
3105             return 0;
3106         if (from is null || from.addressFamily != _family)
3107             from = createAddress();
3108         socklen_t nameLen = from.nameLen;
3109         version (Windows)
3110         {
3111             auto read = .recvfrom(sock, buf.ptr, capToInt(buf.length), cast(int) flags, from.name, &nameLen);
3112             from.setNameLen(nameLen);
3113             assert(from.addressFamily == _family);
3114             // if (!read) //connection closed
3115             return read;
3116         }
3117         else
3118         {
3119             auto read = .recvfrom(sock, buf.ptr, buf.length, cast(int) flags, from.name, &nameLen);
3120             from.setNameLen(nameLen);
3121             assert(from.addressFamily == _family);
3122             // if (!read) //connection closed
3123             return read;
3124         }
3125     }
3126 
3127 
3128     /// ditto
3129     ptrdiff_t receiveFrom(void[] buf, ref Address from)
3130     {
3131         return receiveFrom(buf, SocketFlags.NONE, from);
3132     }
3133 
3134 
3135     //assumes you connect()ed
3136     /// ditto
3137     ptrdiff_t receiveFrom(void[] buf, SocketFlags flags) @trusted
3138     {
3139         if (!buf.length)         //return 0 and don't think the connection closed
3140             return 0;
3141         version (Windows)
3142         {
3143             auto read = .recvfrom(sock, buf.ptr, capToInt(buf.length), cast(int) flags, null, null);
3144             // if (!read) //connection closed
3145             return read;
3146         }
3147         else
3148         {
3149             auto read = .recvfrom(sock, buf.ptr, buf.length, cast(int) flags, null, null);
3150             // if (!read) //connection closed
3151             return read;
3152         }
3153     }
3154 
3155 
3156     //assumes you connect()ed
3157     /// ditto
3158     ptrdiff_t receiveFrom(void[] buf)
3159     {
3160         return receiveFrom(buf, SocketFlags.NONE);
3161     }
3162 
3163 
3164     /**
3165      * Get a socket option.
3166      * Returns: The number of bytes written to $(D result).
3167      * The length, in bytes, of the actual result - very different from getsockopt()
3168      */
3169     int getOption(SocketOptionLevel level, SocketOption option, void[] result) @trusted
3170     {
3171         socklen_t len = cast(socklen_t) result.length;
3172         if (_SOCKET_ERROR == .getsockopt(sock, cast(int) level, cast(int) option, result.ptr, &len))
3173             throw new SocketOSException("Unable to get socket option");
3174         return len;
3175     }
3176 
3177 
3178     /// Common case of getting integer and boolean options.
3179     int getOption(SocketOptionLevel level, SocketOption option, out int32_t result) @trusted
3180     {
3181         return getOption(level, option, (&result)[0 .. 1]);
3182     }
3183 
3184 
3185     /// Get the linger option.
3186     int getOption(SocketOptionLevel level, SocketOption option, out Linger result) @trusted
3187     {
3188         //return getOption(cast(SocketOptionLevel) SocketOptionLevel.SOCKET, SocketOption.LINGER, (&result)[0 .. 1]);
3189         return getOption(level, option, (&result.clinger)[0 .. 1]);
3190     }
3191 
3192     /// Get a timeout (duration) option.
3193     void getOption(SocketOptionLevel level, SocketOption option, out Duration result) @trusted
3194     {
3195         enforce(option == SocketOption.SNDTIMEO || option == SocketOption.RCVTIMEO,
3196                 new SocketParameterException("Not a valid timeout option: " ~ to!string(option)));
3197         // WinSock returns the timeout values as a milliseconds DWORD,
3198         // while Linux and BSD return a timeval struct.
3199         version (Windows)
3200         {
3201             int msecs;
3202             getOption(level, option, (&msecs)[0 .. 1]);
3203             if (option == SocketOption.RCVTIMEO)
3204                 msecs += WINSOCK_TIMEOUT_SKEW;
3205             result = dur!"msecs"(msecs);
3206         }
3207         else version (Posix)
3208         {
3209             TimeVal tv;
3210             getOption(level, option, (&tv.ctimeval)[0 .. 1]);
3211             result = dur!"seconds"(tv.seconds) + dur!"usecs"(tv.microseconds);
3212         }
3213         else static assert(false);
3214     }
3215 
3216     /// Set a socket option.
3217     void setOption(SocketOptionLevel level, SocketOption option, void[] value) @trusted
3218     {
3219         if (_SOCKET_ERROR == .setsockopt(sock, cast(int) level,
3220                                         cast(int) option, value.ptr, cast(uint) value.length))
3221             throw new SocketOSException("Unable to set socket option");
3222     }
3223 
3224 
3225     /// Common case for setting integer and boolean options.
3226     void setOption(SocketOptionLevel level, SocketOption option, int32_t value) @trusted
3227     {
3228         setOption(level, option, (&value)[0 .. 1]);
3229     }
3230 
3231 
3232     /// Set the linger option.
3233     void setOption(SocketOptionLevel level, SocketOption option, Linger value) @trusted
3234     {
3235         //setOption(cast(SocketOptionLevel) SocketOptionLevel.SOCKET, SocketOption.LINGER, (&value)[0 .. 1]);
3236         setOption(level, option, (&value.clinger)[0 .. 1]);
3237     }
3238 
3239     /**
3240      * Sets a timeout (duration) option, i.e. $(D SocketOption.SNDTIMEO) or
3241      * $(D RCVTIMEO). Zero indicates no timeout.
3242      *
3243      * In a typical application, you might also want to consider using
3244      * a non-blocking socket instead of setting a timeout on a blocking one.
3245      *
3246      * Note: While the receive timeout setting is generally quite accurate
3247      * on *nix systems even for smaller durations, there are two issues to
3248      * be aware of on Windows: First, although undocumented, the effective
3249      * timeout duration seems to be the one set on the socket plus half
3250      * a second. $(D setOption()) tries to compensate for that, but still,
3251      * timeouts under 500ms are not possible on Windows. Second, be aware
3252      * that the actual amount of time spent until a blocking call returns
3253      * randomly varies on the order of 10ms.
3254      *
3255      * Params:
3256      *   level  = The level at which a socket option is defined.
3257      *   option = Either $(D SocketOption.SNDTIMEO) or $(D SocketOption.RCVTIMEO).
3258      *   value  = The timeout duration to set. Must not be negative.
3259      *
3260      * Throws: $(D SocketException) if setting the options fails.
3261      *
3262      * Example:
3263      * ---
3264      * import std.datetime;
3265      * import std.typecons;
3266      * auto pair = socketPair();
3267      * scope(exit) foreach (s; pair) s.close();
3268      *
3269      * // Set a receive timeout, and then wait at one end of
3270      * // the socket pair, knowing that no data will arrive.
3271      * pair[0].setOption(SocketOptionLevel.SOCKET,
3272      *     SocketOption.RCVTIMEO, dur!"seconds"(1));
3273      *
3274      * auto sw = StopWatch(Yes.autoStart);
3275      * ubyte[1] buffer;
3276      * pair[0].receive(buffer);
3277      * writefln("Waited %s ms until the socket timed out.",
3278      *     sw.peek.msecs);
3279      * ---
3280      */
3281     void setOption(SocketOptionLevel level, SocketOption option, Duration value) @trusted
3282     {
3283         enforce(option == SocketOption.SNDTIMEO || option == SocketOption.RCVTIMEO,
3284                 new SocketParameterException("Not a valid timeout option: " ~ to!string(option)));
3285 
3286         enforce(value >= dur!"hnsecs"(0), new SocketParameterException(
3287                     "Timeout duration must not be negative."));
3288 
3289         version (Windows)
3290         {
3291             import std.algorithm.comparison : max;
3292 
3293             auto msecs = to!int(value.total!"msecs");
3294             if (msecs != 0 && option == SocketOption.RCVTIMEO)
3295                 msecs = max(1, msecs - WINSOCK_TIMEOUT_SKEW);
3296             setOption(level, option, msecs);
3297         }
3298         else version (Posix)
3299         {
3300             _ctimeval tv;
3301             value.split!("seconds", "usecs")(tv.tv_sec, tv.tv_usec);
3302             setOption(level, option, (&tv)[0 .. 1]);
3303         }
3304         else static assert(false);
3305     }
3306 
3307     /**
3308      * Get a text description of this socket's error status, and clear the
3309      * socket's error status.
3310      */
3311     string getErrorText()
3312     {
3313         int32_t error;
3314         getOption(SocketOptionLevel.SOCKET, SocketOption.ERROR, error);
3315         return formatSocketError(error);
3316     }
3317 
3318     /**
3319      * Enables TCP keep-alive with the specified parameters.
3320      *
3321      * Params:
3322      *   time     = Number of seconds with no activity until the first
3323      *              keep-alive packet is sent.
3324      *   interval = Number of seconds between when successive keep-alive
3325      *              packets are sent if no acknowledgement is received.
3326      *
3327      * Throws: $(D SocketOSException) if setting the options fails, or
3328      * $(D SocketFeatureException) if setting keep-alive parameters is
3329      * unsupported on the current platform.
3330      */
3331     void setKeepAlive(int time, int interval) @trusted
3332     {
3333         version (Windows)
3334         {
3335             tcp_keepalive options;
3336             options.onoff = 1;
3337             options.keepalivetime = time * 1000;
3338             options.keepaliveinterval = interval * 1000;
3339             uint cbBytesReturned;
3340             enforce(WSAIoctl(sock, SIO_KEEPALIVE_VALS,
3341                              &options, options.sizeof,
3342                              null, 0,
3343                              &cbBytesReturned, null, null) == 0,
3344                     new SocketOSException("Error setting keep-alive"));
3345         }
3346         else
3347         static if (is(typeof(TCP_KEEPIDLE)) && is(typeof(TCP_KEEPINTVL)))
3348         {
3349             setOption(SocketOptionLevel.TCP, cast(SocketOption) TCP_KEEPIDLE, time);
3350             setOption(SocketOptionLevel.TCP, cast(SocketOption) TCP_KEEPINTVL, interval);
3351             setOption(SocketOptionLevel.SOCKET, SocketOption.KEEPALIVE, true);
3352         }
3353         else
3354             throw new SocketFeatureException("Setting keep-alive options " ~
3355                 "is not supported on this platform");
3356     }
3357 
3358     /**
3359      * Wait for a socket to change status. A wait timeout of $(REF Duration, core, time) or
3360      * $(D TimeVal), may be specified; if a timeout is not specified or the
3361      * $(D TimeVal) is $(D null), the maximum timeout is used. The $(D TimeVal)
3362      * timeout has an unspecified value when $(D select) returns.
3363      * Returns: The number of sockets with status changes, $(D 0) on timeout,
3364      * or $(D -1) on interruption. If the return value is greater than $(D 0),
3365      * the $(D SocketSets) are updated to only contain the sockets having status
3366      * changes. For a connecting socket, a write status change means the
3367      * connection is established and it's able to send. For a listening socket,
3368      * a read status change means there is an incoming connection request and
3369      * it's able to accept.
3370      *
3371      * `SocketSet`'s updated to include only those sockets which an event occured.
3372      * For a `connect()`ing socket, writeability means connected.
3373      * For a `listen()`ing socket, readability means listening
3374      * `Winsock`; possibly internally limited to 64 sockets per set.
3375      *
3376      * Returns:
3377      * the number of events, 0 on timeout, or -1 on interruption
3378      */
3379     static int select(SocketSet checkRead, SocketSet checkWrite, SocketSet checkError, Duration timeout) @trusted
3380     {
3381         auto vals = timeout.split!("seconds", "usecs")();
3382         TimeVal tv;
3383         tv.seconds      = cast(tv.tv_sec_t ) vals.seconds;
3384         tv.microseconds = cast(tv.tv_usec_t) vals.usecs;
3385         return select(checkRead, checkWrite, checkError, &tv);
3386     }
3387 
3388     /// ditto
3389     //maximum timeout
3390     static int select(SocketSet checkRead, SocketSet checkWrite, SocketSet checkError)
3391     {
3392         return select(checkRead, checkWrite, checkError, null);
3393     }
3394 
3395     /// Ditto
3396     static int select(SocketSet checkRead, SocketSet checkWrite, SocketSet checkError, TimeVal* timeout) @trusted
3397     in
3398     {
3399         //make sure none of the SocketSet's are the same object
3400         if (checkRead)
3401         {
3402             assert(checkRead !is checkWrite);
3403             assert(checkRead !is checkError);
3404         }
3405         if (checkWrite)
3406         {
3407             assert(checkWrite !is checkError);
3408         }
3409     }
3410     body
3411     {
3412         fd_set* fr, fw, fe;
3413         int n = 0;
3414 
3415         version (Windows)
3416         {
3417             // Windows has a problem with empty fd_set`s that aren't null.
3418             fr = checkRead  && checkRead.count  ? checkRead.toFd_set()  : null;
3419             fw = checkWrite && checkWrite.count ? checkWrite.toFd_set() : null;
3420             fe = checkError && checkError.count ? checkError.toFd_set() : null;
3421         }
3422         else
3423         {
3424             if (checkRead)
3425             {
3426                 fr = checkRead.toFd_set();
3427                 n = checkRead.selectn();
3428             }
3429             else
3430             {
3431                 fr = null;
3432             }
3433 
3434             if (checkWrite)
3435             {
3436                 fw = checkWrite.toFd_set();
3437                 int _n;
3438                 _n = checkWrite.selectn();
3439                 if (_n > n)
3440                     n = _n;
3441             }
3442             else
3443             {
3444                 fw = null;
3445             }
3446 
3447             if (checkError)
3448             {
3449                 fe = checkError.toFd_set();
3450                 int _n;
3451                 _n = checkError.selectn();
3452                 if (_n > n)
3453                     n = _n;
3454             }
3455             else
3456             {
3457                 fe = null;
3458             }
3459 
3460             // Make sure the sets' capacity matches, to avoid select reading
3461             // out of bounds just because one set was bigger than another
3462             if (checkRead ) checkRead .setMinCapacity(n);
3463             if (checkWrite) checkWrite.setMinCapacity(n);
3464             if (checkError) checkError.setMinCapacity(n);
3465         }
3466 
3467         int result = .select(n, fr, fw, fe, &timeout.ctimeval);
3468 
3469         version (Windows)
3470         {
3471             if (_SOCKET_ERROR == result && WSAGetLastError() == WSAEINTR)
3472                 return -1;
3473         }
3474         else version (Posix)
3475         {
3476             if (_SOCKET_ERROR == result && errno == EINTR)
3477                 return -1;
3478         }
3479         else
3480         {
3481             static assert(0);
3482         }
3483 
3484         if (_SOCKET_ERROR == result)
3485             throw new SocketOSException("Socket select error");
3486 
3487         return result;
3488     }
3489 
3490 
3491     /**
3492      * Can be overridden to support other addresses.
3493      * Returns: a new `Address` object for the current address family.
3494      */
3495     protected Address createAddress() pure nothrow
3496     {
3497         Address result;
3498         switch (_family)
3499         {
3500         static if (is(sockaddr_un))
3501         {
3502             case AddressFamily.UNIX:
3503                 result = new UnixAddress;
3504                 break;
3505         }
3506 
3507         case AddressFamily.INET:
3508             result = new InternetAddress;
3509             break;
3510 
3511         case AddressFamily.INET6:
3512             result = new Internet6Address;
3513             break;
3514 
3515         default:
3516             result = new UnknownAddress;
3517         }
3518         return result;
3519     }
3520 
3521 }
3522 
3523 
3524 /// $(D TcpSocket) is a shortcut class for a TCP Socket.
3525 class TcpSocket: Socket
3526 {
3527     /// Constructs a blocking TCP Socket.
3528     this(AddressFamily family)
3529     {
3530         super(family, SocketType.STREAM, ProtocolType.TCP);
3531     }
3532 
3533     /// Constructs a blocking IPv4 TCP Socket.
3534     this()
3535     {
3536         this(AddressFamily.INET);
3537     }
3538 
3539 
3540     //shortcut
3541     /// Constructs a blocking TCP Socket and connects to an $(D Address).
3542     this(Address connectTo)
3543     {
3544         this(connectTo.addressFamily);
3545         connect(connectTo);
3546     }
3547 }
3548 
3549 
3550 /// $(D UdpSocket) is a shortcut class for a UDP Socket.
3551 class UdpSocket: Socket
3552 {
3553     /// Constructs a blocking UDP Socket.
3554     this(AddressFamily family)
3555     {
3556         super(family, SocketType.DGRAM, ProtocolType.UDP);
3557     }
3558 
3559 
3560     /// Constructs a blocking IPv4 UDP Socket.
3561     this()
3562     {
3563         this(AddressFamily.INET);
3564     }
3565 }
3566 
3567 // Issue 16514
3568 @safe unittest
3569 {
3570     class TestSocket : Socket
3571     {
3572         override
3573         {
3574             const pure nothrow @nogc @property @safe socket_t handle() { assert(0); }
3575             const nothrow @nogc @property @trusted bool blocking() { assert(0); }
3576             @property @trusted void blocking(bool byes) { assert(0); }
3577             @property @safe AddressFamily addressFamily() { assert(0); }
3578             const @property @trusted bool isAlive() { assert(0); }
3579             @trusted void bind(Address addr) { assert(0); }
3580             @trusted void connect(Address to) { assert(0); }
3581             @trusted void listen(int backlog) { assert(0); }
3582             protected pure nothrow @safe Socket accepting() { assert(0); }
3583             @trusted Socket accept() { assert(0); }
3584             nothrow @nogc @trusted void shutdown(SocketShutdown how) { assert(0); }
3585             nothrow @nogc @trusted void close() { assert(0); }
3586             @property @trusted Address remoteAddress() { assert(0); }
3587             @property @trusted Address localAddress() { assert(0); }
3588             @trusted ptrdiff_t send(const(void)[] buf, SocketFlags flags) { assert(0); }
3589             @safe ptrdiff_t send(const(void)[] buf) { assert(0); }
3590             @trusted ptrdiff_t sendTo(const(void)[] buf, SocketFlags flags, Address to) { assert(0); }
3591             @safe ptrdiff_t sendTo(const(void)[] buf, Address to) { assert(0); }
3592             @trusted ptrdiff_t sendTo(const(void)[] buf, SocketFlags flags) { assert(0); }
3593             @safe ptrdiff_t sendTo(const(void)[] buf) { assert(0); }
3594             @trusted ptrdiff_t receive(void[] buf, SocketFlags flags) { assert(0); }
3595             @safe ptrdiff_t receive(void[] buf) { assert(0); }
3596             @trusted ptrdiff_t receiveFrom(void[] buf, SocketFlags flags, ref Address from) { assert(0); }
3597             @safe ptrdiff_t receiveFrom(void[] buf, ref Address from) { assert(0); }
3598             @trusted ptrdiff_t receiveFrom(void[] buf, SocketFlags flags) { assert(0); }
3599             @safe ptrdiff_t receiveFrom(void[] buf) { assert(0); }
3600             @trusted int getOption(SocketOptionLevel level, SocketOption option, void[] result) { assert(0); }
3601             @trusted int getOption(SocketOptionLevel level, SocketOption option, out int32_t result) { assert(0); }
3602             @trusted int getOption(SocketOptionLevel level, SocketOption option, out Linger result) { assert(0); }
3603             @trusted void getOption(SocketOptionLevel level, SocketOption option, out Duration result) { assert(0); }
3604             @trusted void setOption(SocketOptionLevel level, SocketOption option, void[] value) { assert(0); }
3605             @trusted void setOption(SocketOptionLevel level, SocketOption option, int32_t value) { assert(0); }
3606             @trusted void setOption(SocketOptionLevel level, SocketOption option, Linger value) { assert(0); }
3607             @trusted void setOption(SocketOptionLevel level, SocketOption option, Duration value) { assert(0); }
3608             @safe string getErrorText() { assert(0); }
3609             @trusted void setKeepAlive(int time, int interval) { assert(0); }
3610             protected pure nothrow @safe Address createAddress() { assert(0); }
3611         }
3612     }
3613 }
3614 
3615 /**
3616  * Creates a pair of connected sockets.
3617  *
3618  * The two sockets are indistinguishable.
3619  *
3620  * Throws: $(D SocketException) if creation of the sockets fails.
3621  */
3622 Socket[2] socketPair() @trusted
3623 {
3624     version (Posix)
3625     {
3626         int[2] socks;
3627         if (socketpair(AF_UNIX, SOCK_STREAM, 0, socks) == -1)
3628             throw new SocketOSException("Unable to create socket pair");
3629 
3630         Socket toSocket(size_t id)
3631         {
3632             auto s = new Socket;
3633             s.setSock(cast(socket_t) socks[id]);
3634             s._family = AddressFamily.UNIX;
3635             return s;
3636         }
3637 
3638         return [toSocket(0), toSocket(1)];
3639     }
3640     else version (Windows)
3641     {
3642         // We do not have socketpair() on Windows, just manually create a
3643         // pair of sockets connected over some localhost port.
3644         Socket[2] result;
3645 
3646         auto listener = new TcpSocket();
3647         listener.setOption(SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, true);
3648         listener.bind(new InternetAddress(INADDR_LOOPBACK, InternetAddress.PORT_ANY));
3649         auto addr = listener.localAddress;
3650         listener.listen(1);
3651 
3652         result[0] = new TcpSocket(addr);
3653         result[1] = listener.accept();
3654 
3655         listener.close();
3656         return result;
3657     }
3658     else
3659         static assert(false);
3660 }
3661 
3662 ///
3663 @safe unittest
3664 {
3665     immutable ubyte[] data = [1, 2, 3, 4];
3666     auto pair = socketPair();
3667     scope(exit) foreach (s; pair) s.close();
3668 
3669     pair[0].send(data);
3670 
3671     auto buf = new ubyte[data.length];
3672     pair[1].receive(buf);
3673     assert(buf == data);
3674 }
3675