The OpenD Programming Language

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