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