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 [listener.d](https://github.com/dlang/undeaD/blob/master/dmdsamples/listener.d) and [htmlget.d](https://github.com/dlang/undeaD/blob/master/dmdsamples/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. InternetAddress) 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     version (Posix)
1867     {
1868         /// Human readable string representing the IPv6 address in RFC 2373 form.
1869         override string toAddrString() @trusted const
1870         {
1871             char[INET6_ADDRSTRLEN] buf;
1872             string addrString = to!string(
1873                 .inet_ntop(AddressFamily.INET6, &sin6.sin6_addr, buf.ptr, INET6_ADDRSTRLEN)
1874             );
1875             return addrString;
1876         }
1877     }
1878 
1879    /**
1880      * Parse an IPv6 host address string as described in RFC 2373, and return the
1881      * address.
1882      * Throws: `SocketException` on error.
1883      */
1884     static ubyte[16] parse(scope const(char)[] addr) @trusted
1885     {
1886         // Although we could use inet_pton here, it's only available on Windows
1887         // versions starting with Vista, so use getAddressInfo with NUMERICHOST
1888         // instead.
1889         auto results = getAddressInfo(addr, AddressInfoFlags.NUMERICHOST);
1890         if (results.length && results[0].family == AddressFamily.INET6)
1891             return (cast(sockaddr_in6*) results[0].address.name).sin6_addr.s6_addr;
1892         throw new AddressException("Not an IPv6 address", 0);
1893     }
1894 }
1895 
1896 
1897 @safe unittest
1898 {
1899     softUnittest({
1900         const Internet6Address ia = new Internet6Address("::1", 80);
1901         assert(ia.toString() == "[::1]:80");
1902     });
1903 
1904     softUnittest({
1905         // test construction from a sockaddr_in6
1906         sockaddr_in6 sin;
1907 
1908         sin.sin6_addr.s6_addr = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1];  // [::1]
1909         sin.sin6_family = AddressFamily.INET6;
1910         sin.sin6_port = htons(80);
1911 
1912         const Internet6Address ia = new Internet6Address(sin);
1913         assert(ia.toString() == "[::1]:80");
1914     });
1915 }
1916 
1917 
1918 version (StdDdoc)
1919 {
1920     static if (!is(sockaddr_un))
1921     {
1922         // This exists only to allow the constructor taking
1923         // a sockaddr_un to be compilable for documentation
1924         // on platforms that don't supply a sockaddr_un.
1925         struct sockaddr_un
1926         {
1927         }
1928     }
1929 
1930     /**
1931      * Encapsulates an address for a Unix domain socket (`AF_UNIX`),
1932      * i.e. a socket bound to a path name in the file system.
1933      * Available only on supported systems.
1934      *
1935      * Linux also supports an abstract address namespace, in which addresses
1936      * are independent of the file system. A socket address is abstract
1937      * iff `path` starts with a _null byte (`'\0'`). Null bytes in other
1938      * positions of an abstract address are allowed and have no special
1939      * meaning.
1940      *
1941      * Example:
1942      * ---
1943      * auto addr = new UnixAddress("/var/run/dbus/system_bus_socket");
1944      * auto abstractAddr = new UnixAddress("\0/tmp/dbus-OtHLWmCLPR");
1945      * ---
1946      *
1947      * See_Also: $(HTTP man7.org/linux/man-pages/man7/unix.7.html, UNIX(7))
1948      */
1949     class UnixAddress: Address
1950     {
1951         private this() pure nothrow @nogc {}
1952 
1953         /// Construct a new `UnixAddress` from the specified path.
1954         this(scope const(char)[] path) { }
1955 
1956         /**
1957          * Construct a new `UnixAddress`.
1958          * Params:
1959          *   addr = A sockaddr_un as obtained from lower-level API calls.
1960          */
1961         this(sockaddr_un addr) pure nothrow @nogc { }
1962 
1963         /// Get the underlying _path.
1964         @property string path() const { return null; }
1965 
1966         /// ditto
1967         override string toString() const { return null; }
1968 
1969         override @property sockaddr* name() { return null; }
1970         override @property const(sockaddr)* name() const { return null; }
1971         override @property socklen_t nameLen() const { return 0; }
1972     }
1973 }
1974 else
1975 static if (is(sockaddr_un))
1976 {
1977     class UnixAddress: Address
1978     {
1979     protected:
1980         socklen_t _nameLen;
1981 
1982         struct
1983         {
1984         align (1):
1985             sockaddr_un sun;
1986             char unused = '\0'; // placeholder for a terminating '\0'
1987         }
1988 
1989         this() pure nothrow @nogc
1990         {
1991             sun.sun_family = AddressFamily.UNIX;
1992             sun.sun_path = '?';
1993             _nameLen = sun.sizeof;
1994         }
1995 
1996         override void setNameLen(socklen_t len) @trusted
1997         {
1998             if (len > sun.sizeof)
1999                 throw new SocketParameterException("Not enough socket address storage");
2000             _nameLen = len;
2001         }
2002 
2003     public:
2004         override @property sockaddr* name() return
2005         {
2006             return cast(sockaddr*)&sun;
2007         }
2008 
2009         override @property const(sockaddr)* name() const return
2010         {
2011             return cast(const(sockaddr)*)&sun;
2012         }
2013 
2014         override @property socklen_t nameLen() @trusted const
2015         {
2016             return _nameLen;
2017         }
2018 
2019         this(scope const(char)[] path) @trusted pure
2020         {
2021             enforce(path.length <= sun.sun_path.sizeof, new SocketParameterException("Path too long"));
2022             sun.sun_family = AddressFamily.UNIX;
2023             sun.sun_path.ptr[0 .. path.length] = (cast(byte[]) path)[];
2024             _nameLen = cast(socklen_t)
2025                 {
2026                     auto len = sockaddr_un.init.sun_path.offsetof + path.length;
2027                     // Pathname socket address must be terminated with '\0'
2028                     // which must be included in the address length.
2029                     if (sun.sun_path.ptr[0])
2030                     {
2031                         sun.sun_path.ptr[path.length] = 0;
2032                         ++len;
2033                     }
2034                     return len;
2035                 }();
2036         }
2037 
2038         this(sockaddr_un addr) pure nothrow @nogc
2039         {
2040             assert(addr.sun_family == AddressFamily.UNIX);
2041             sun = addr;
2042         }
2043 
2044         @property string path() @trusted const pure
2045         {
2046             auto len = _nameLen - sockaddr_un.init.sun_path.offsetof;
2047             if (len == 0)
2048                 return null; // An empty path may be returned from getpeername
2049             // For pathname socket address we need to strip off the terminating '\0'
2050             if (sun.sun_path.ptr[0])
2051                 --len;
2052             return (cast(const(char)*) sun.sun_path.ptr)[0 .. len].idup;
2053         }
2054 
2055         override string toString() const pure
2056         {
2057             return path;
2058         }
2059     }
2060 
2061     @safe unittest
2062     {
2063         import core.stdc.stdio : remove;
2064 
2065         version (iOSDerived)
2066         {
2067             // Slightly different version of `std.file.deleteme` to reduce the path
2068             // length on iOS derived platforms. Due to the sandbox, the length
2069             // of paths can quickly become too long.
2070             static string deleteme()
2071             {
2072                 import std.conv : text;
2073                 import std.process : thisProcessID;
2074                 import std.file : tempDir;
2075 
2076                 return text(tempDir, thisProcessID);
2077             }
2078         }
2079 
2080         else
2081             import std.file : deleteme;
2082 
2083         immutable ubyte[] data = [1, 2, 3, 4];
2084         Socket[2] pair;
2085 
2086         const basePath = deleteme;
2087         auto names = [ basePath ~ "-socket" ];
2088         version (linux)
2089             names ~= "\0" ~ basePath ~ "-abstract\0unix\0socket";
2090 
2091         foreach (name; names)
2092         {
2093             auto address = new UnixAddress(name);
2094 
2095             auto listener = new Socket(AddressFamily.UNIX, SocketType.STREAM);
2096             scope(exit) listener.close();
2097             listener.bind(address);
2098             scope(exit) () @trusted { if (name[0]) remove(name.tempCString()); } ();
2099             assert(listener.localAddress.toString == name);
2100 
2101             listener.listen(1);
2102 
2103             pair[0] = new Socket(AddressFamily.UNIX, SocketType.STREAM);
2104             scope(exit) listener.close();
2105 
2106             pair[0].connect(address);
2107             scope(exit) pair[0].close();
2108 
2109             pair[1] = listener.accept();
2110             scope(exit) pair[1].close();
2111 
2112             pair[0].send(data);
2113 
2114             auto buf = new ubyte[data.length];
2115             pair[1].receive(buf);
2116             assert(buf == data);
2117 
2118             // getpeername is free to return an empty name for a unix
2119             // domain socket pair or unbound socket. Let's confirm it
2120             // returns successfully and doesn't throw anything.
2121             // See https://issues.dlang.org/show_bug.cgi?id=20544
2122             assertNotThrown(pair[1].remoteAddress().toString());
2123         }
2124     }
2125 }
2126 
2127 
2128 /**
2129  * Exception thrown by `Socket.accept`.
2130  */
2131 class SocketAcceptException: SocketOSException
2132 {
2133     mixin socketOSExceptionCtors;
2134 }
2135 
2136 /// How a socket is shutdown:
2137 enum SocketShutdown: int
2138 {
2139     RECEIVE =  SD_RECEIVE,      /// socket receives are disallowed
2140     SEND =     SD_SEND,         /// socket sends are disallowed
2141     BOTH =     SD_BOTH,         /// both RECEIVE and SEND
2142 }
2143 
2144 
2145 /// Socket flags that may be OR'ed together:
2146 enum SocketFlags: int
2147 {
2148     NONE =       0,                 /// no flags specified
2149 
2150     OOB =        MSG_OOB,           /// out-of-band stream data
2151     PEEK =       MSG_PEEK,          /// peek at incoming data without removing it from the queue, only for receiving
2152     DONTROUTE =  MSG_DONTROUTE,     /// data should not be subject to routing; this flag may be ignored. Only for sending
2153 }
2154 
2155 
2156 /// Duration timeout value.
2157 struct TimeVal
2158 {
2159     _ctimeval ctimeval;
2160     alias tv_sec_t = typeof(ctimeval.tv_sec);
2161     alias tv_usec_t = typeof(ctimeval.tv_usec);
2162 
2163     /// Number of _seconds.
2164     pure nothrow @nogc @property
2165     ref inout(tv_sec_t) seconds() inout return
2166     {
2167         return ctimeval.tv_sec;
2168     }
2169 
2170     /// Number of additional _microseconds.
2171     pure nothrow @nogc @property
2172     ref inout(tv_usec_t) microseconds() inout return
2173     {
2174         return ctimeval.tv_usec;
2175     }
2176 }
2177 
2178 
2179 /**
2180  * A collection of sockets for use with `Socket.select`.
2181  *
2182  * `SocketSet` wraps the platform `fd_set` type. However, unlike
2183  * `fd_set`, `SocketSet` is not statically limited to `FD_SETSIZE`
2184  * or any other limit, and grows as needed.
2185  */
2186 class SocketSet
2187 {
2188 private:
2189     version (Windows)
2190     {
2191         // On Windows, fd_set is an array of socket handles,
2192         // following a word containing the fd_set instance size.
2193         // We use one dynamic array for everything, and use its first
2194         // element(s) for the count.
2195 
2196         alias fd_set_count_type = typeof(fd_set.init.fd_count);
2197         alias fd_set_type = typeof(fd_set.init.fd_array[0]);
2198         static assert(fd_set_type.sizeof == socket_t.sizeof);
2199 
2200         // Number of fd_set_type elements at the start of our array that are
2201         // used for the socket count and alignment
2202 
2203         enum FD_SET_OFFSET = fd_set.fd_array.offsetof / fd_set_type.sizeof;
2204         static assert(FD_SET_OFFSET);
2205         static assert(fd_set.fd_count.offsetof % fd_set_type.sizeof == 0);
2206 
2207         fd_set_type[] set;
2208 
2209         void resize(size_t size) pure nothrow
2210         {
2211             set.length = FD_SET_OFFSET + size;
2212         }
2213 
2214         ref inout(fd_set_count_type) count() @trusted @property inout pure nothrow @nogc
2215         {
2216             assert(set.length);
2217             return *cast(inout(fd_set_count_type)*)set.ptr;
2218         }
2219 
2220         size_t capacity() @property const pure nothrow @nogc
2221         {
2222             return set.length - FD_SET_OFFSET;
2223         }
2224 
2225         inout(socket_t)[] fds() @trusted inout @property pure nothrow @nogc
2226         {
2227             return cast(inout(socket_t)[])set[FD_SET_OFFSET .. FD_SET_OFFSET+count];
2228         }
2229     }
2230     else
2231     version (Posix)
2232     {
2233         // On Posix, fd_set is a bit array. We assume that the fd_set
2234         // type (declared in core.sys.posix.sys.select) is a structure
2235         // containing a single field, a static array.
2236 
2237         static assert(fd_set.tupleof.length == 1);
2238 
2239         // This is the type used in the fd_set array.
2240         // Using the type of the correct size is important for big-endian
2241         // architectures.
2242 
2243         alias fd_set_type = typeof(fd_set.init.tupleof[0][0]);
2244 
2245         // Number of file descriptors represented by one fd_set_type
2246 
2247         enum FD_NFDBITS = 8 * fd_set_type.sizeof;
2248 
2249         static fd_set_type mask(uint n) pure nothrow @nogc
2250         {
2251             return (cast(fd_set_type) 1) << (n % FD_NFDBITS);
2252         }
2253 
2254         // Array size to fit that many sockets
2255 
2256         static size_t lengthFor(size_t size) pure nothrow @nogc
2257         {
2258             return (size + (FD_NFDBITS-1)) / FD_NFDBITS;
2259         }
2260 
2261         fd_set_type[] set;
2262 
2263         void resize(size_t size) pure nothrow
2264         {
2265             set.length = lengthFor(size);
2266         }
2267 
2268         // Make sure we can fit that many sockets
2269 
2270         void setMinCapacity(size_t size) pure nothrow
2271         {
2272             auto length = lengthFor(size);
2273             if (set.length < length)
2274                 set.length = length;
2275         }
2276 
2277         size_t capacity() @property const pure nothrow @nogc
2278         {
2279             return set.length * FD_NFDBITS;
2280         }
2281 
2282         int maxfd;
2283     }
2284     else
2285         static assert(false, "Unknown platform");
2286 
2287 public:
2288 
2289     /**
2290      * Create a SocketSet with a specific initial capacity (defaults to
2291      * `FD_SETSIZE`, the system's default capacity).
2292      */
2293     this(size_t size = FD_SETSIZE) pure nothrow
2294     {
2295         resize(size);
2296         reset();
2297     }
2298 
2299     /// Reset the `SocketSet` so that there are 0 `Socket`s in the collection.
2300     void reset() pure nothrow @nogc
2301     {
2302         version (Windows)
2303             count = 0;
2304         else
2305         {
2306             set[] = 0;
2307             maxfd = -1;
2308         }
2309     }
2310 
2311 
2312     void add(socket_t s) @trusted pure nothrow
2313     {
2314         version (Windows)
2315         {
2316             if (count == capacity)
2317             {
2318                 set.length *= 2;
2319                 set.length = set.capacity;
2320             }
2321             ++count;
2322             fds[$-1] = s;
2323         }
2324         else
2325         {
2326             auto index = s / FD_NFDBITS;
2327             auto length = set.length;
2328             if (index >= length)
2329             {
2330                 while (index >= length)
2331                     length *= 2;
2332                 set.length = length;
2333                 set.length = set.capacity;
2334             }
2335             set[index] |= mask(s);
2336             if (maxfd < s)
2337                 maxfd = s;
2338         }
2339     }
2340 
2341     /**
2342      * Add a `Socket` to the collection.
2343      * The socket must not already be in the collection.
2344      */
2345     void add(Socket s) pure nothrow
2346     {
2347         add(s.sock);
2348     }
2349 
2350     void remove(socket_t s) pure nothrow
2351     {
2352         version (Windows)
2353         {
2354             import std.algorithm.searching : countUntil;
2355             auto fds = fds;
2356             auto p = fds.countUntil(s);
2357             if (p >= 0)
2358                 fds[p] = fds[--count];
2359         }
2360         else
2361         {
2362             auto index = s / FD_NFDBITS;
2363             if (index >= set.length)
2364                 return;
2365             set[index] &= ~mask(s);
2366             // note: adjusting maxfd would require scanning the set, not worth it
2367         }
2368     }
2369 
2370 
2371     /**
2372      * Remove this `Socket` from the collection.
2373      * Does nothing if the socket is not in the collection already.
2374      */
2375     void remove(Socket s) pure nothrow
2376     {
2377         remove(s.sock);
2378     }
2379 
2380     int isSet(socket_t s) const pure nothrow @nogc
2381     {
2382         version (Windows)
2383         {
2384             import std.algorithm.searching : canFind;
2385             return fds.canFind(s) ? 1 : 0;
2386         }
2387         else
2388         {
2389             if (s > maxfd)
2390                 return 0;
2391             auto index = s / FD_NFDBITS;
2392             return (set[index] & mask(s)) ? 1 : 0;
2393         }
2394     }
2395 
2396 
2397     /// Return nonzero if this `Socket` is in the collection.
2398     int isSet(Socket s) const pure nothrow @nogc
2399     {
2400         return isSet(s.sock);
2401     }
2402 
2403 
2404     /**
2405      * Returns:
2406      * The current capacity of this `SocketSet`. The exact
2407      * meaning of the return value varies from platform to platform.
2408      *
2409      * Note:
2410      * Since D 2.065, this value does not indicate a
2411      * restriction, and `SocketSet` will grow its capacity as
2412      * needed automatically.
2413      */
2414     @property uint max() const pure nothrow @nogc
2415     {
2416         return cast(uint) capacity;
2417     }
2418 
2419 
2420     fd_set* toFd_set() @trusted pure nothrow @nogc
2421     {
2422         return cast(fd_set*) set.ptr;
2423     }
2424 
2425 
2426     int selectn() const pure nothrow @nogc
2427     {
2428         version (Windows)
2429         {
2430             return count;
2431         }
2432         else version (Posix)
2433         {
2434             return maxfd + 1;
2435         }
2436     }
2437 }
2438 
2439 @safe unittest
2440 {
2441     auto fds = cast(socket_t[])
2442         [cast(socket_t) 1, 2, 0, 1024, 17, 42, 1234, 77, 77+32, 77+64];
2443     auto set = new SocketSet();
2444     foreach (fd; fds) assert(!set.isSet(fd));
2445     foreach (fd; fds) set.add(fd);
2446     foreach (fd; fds) assert(set.isSet(fd));
2447 
2448     // Make sure SocketSet reimplements fd_set correctly
2449     auto fdset = set.toFd_set();
2450     foreach (fd; fds[0]..cast(socket_t)(fds[$-1]+1))
2451         assert(cast(bool) set.isSet(fd) == cast(bool)(() @trusted => FD_ISSET(fd, fdset))());
2452 
2453     foreach (fd; fds)
2454     {
2455         assert(set.isSet(fd));
2456         set.remove(fd);
2457         assert(!set.isSet(fd));
2458     }
2459 }
2460 
2461 @safe unittest
2462 {
2463     version (iOSDerived)
2464     {
2465         enum PAIRS = 256;
2466         enum LIMIT = 1024;
2467     }
2468     else
2469     {
2470         enum PAIRS = 768;
2471         enum LIMIT = 2048;
2472     }
2473 
2474     softUnittest({
2475         version (Posix)
2476         () @trusted
2477         {
2478             static assert(LIMIT > PAIRS*2);
2479             import core.sys.posix.sys.resource;
2480             rlimit fileLimit;
2481             getrlimit(RLIMIT_NOFILE, &fileLimit);
2482             assert(fileLimit.rlim_max > LIMIT, "Open file hard limit too low");
2483             fileLimit.rlim_cur = LIMIT;
2484             setrlimit(RLIMIT_NOFILE, &fileLimit);
2485         } ();
2486 
2487         Socket[2][PAIRS] pairs;
2488         foreach (ref pair; pairs)
2489             pair = socketPair();
2490         scope(exit)
2491         {
2492             foreach (pair; pairs)
2493             {
2494                 pair[0].close();
2495                 pair[1].close();
2496             }
2497         }
2498 
2499         import std.random;
2500         auto rng = Xorshift(42);
2501         pairs[].randomShuffle(rng);
2502 
2503         auto readSet = new SocketSet();
2504         auto writeSet = new SocketSet();
2505         auto errorSet = new SocketSet();
2506 
2507         foreach (testPair; pairs)
2508         {
2509             void fillSets()
2510             {
2511                 readSet.reset();
2512                 writeSet.reset();
2513                 errorSet.reset();
2514                 foreach (ref pair; pairs)
2515                     foreach (s; pair[])
2516                     {
2517                         readSet.add(s);
2518                         writeSet.add(s);
2519                         errorSet.add(s);
2520                     }
2521             }
2522 
2523             fillSets();
2524             auto n = Socket.select(readSet, writeSet, errorSet);
2525             assert(n == PAIRS*2); // All in writeSet
2526             assert(writeSet.isSet(testPair[0]));
2527             assert(writeSet.isSet(testPair[1]));
2528             assert(!readSet.isSet(testPair[0]));
2529             assert(!readSet.isSet(testPair[1]));
2530             assert(!errorSet.isSet(testPair[0]));
2531             assert(!errorSet.isSet(testPair[1]));
2532 
2533             ubyte[1] b;
2534             // Socket.send can't be marked with `scope`
2535             // -> @safe DIP1000 code can't use it - see https://github.com/dlang/phobos/pull/6204
2536             () @trusted {
2537                 testPair[0].send(b[]);
2538             }();
2539             fillSets();
2540             n = Socket.select(readSet, null, null);
2541             assert(n == 1); // testPair[1]
2542             assert(readSet.isSet(testPair[1]));
2543             assert(!readSet.isSet(testPair[0]));
2544             // Socket.receive can't be marked with `scope`
2545             // -> @safe DIP1000 code can't use it - see https://github.com/dlang/phobos/pull/6204
2546             () @trusted {
2547                 testPair[1].receive(b[]);
2548             }();
2549         }
2550     });
2551 }
2552 
2553 // https://issues.dlang.org/show_bug.cgi?id=14012
2554 // https://issues.dlang.org/show_bug.cgi?id=14013
2555 @safe unittest
2556 {
2557     auto set = new SocketSet(1);
2558     assert(set.max >= 0);
2559 
2560     enum LIMIT = 4096;
2561     foreach (n; 0 .. LIMIT)
2562         set.add(cast(socket_t) n);
2563     assert(set.max >= LIMIT);
2564 }
2565 
2566 /// The level at which a socket option is defined:
2567 enum SocketOptionLevel: int
2568 {
2569     SOCKET =  SOL_SOCKET,               /// Socket level
2570     IP =      ProtocolType.IP,          /// Internet Protocol version 4 level
2571     ICMP =    ProtocolType.ICMP,        /// Internet Control Message Protocol level
2572     IGMP =    ProtocolType.IGMP,        /// Internet Group Management Protocol level
2573     GGP =     ProtocolType.GGP,         /// Gateway to Gateway Protocol level
2574     TCP =     ProtocolType.TCP,         /// Transmission Control Protocol level
2575     PUP =     ProtocolType.PUP,         /// PARC Universal Packet Protocol level
2576     UDP =     ProtocolType.UDP,         /// User Datagram Protocol level
2577     IDP =     ProtocolType.IDP,         /// Xerox NS protocol level
2578     RAW =     ProtocolType.RAW,         /// Raw IP packet level
2579     IPV6 =    ProtocolType.IPV6,        /// Internet Protocol version 6 level
2580 }
2581 
2582 /// _Linger information for use with SocketOption.LINGER.
2583 struct Linger
2584 {
2585     _clinger clinger;
2586 
2587     private alias l_onoff_t = typeof(_clinger.init.l_onoff );
2588     private alias l_linger_t = typeof(_clinger.init.l_linger);
2589 
2590     /// Nonzero for _on.
2591     pure nothrow @nogc @property
2592     ref inout(l_onoff_t) on() inout return
2593     {
2594         return clinger.l_onoff;
2595     }
2596 
2597     /// Linger _time.
2598     pure nothrow @nogc @property
2599     ref inout(l_linger_t) time() inout return
2600     {
2601         return clinger.l_linger;
2602     }
2603 }
2604 
2605 /// Specifies a socket option:
2606 enum SocketOption: int
2607 {
2608     DEBUG =                SO_DEBUG,            /// Record debugging information
2609     BROADCAST =            SO_BROADCAST,        /// Allow transmission of broadcast messages
2610     REUSEADDR =            SO_REUSEADDR,        /// Allow local reuse of address
2611     /**
2612      * Allow local reuse of port
2613      *
2614      * On Windows, this is equivalent to `SocketOption.REUSEADDR`.
2615      * There is in fact no option named `REUSEPORT`.
2616      * However, `SocketOption.REUSEADDR` matches the behavior of
2617      * `SocketOption.REUSEPORT` on other platforms. Further details on this
2618      * topic can be found here:
2619      * $(LINK https://learn.microsoft.com/en-us/windows/win32/winsock/using-so-reuseaddr-and-so-exclusiveaddruse)
2620      *
2621      * On Linux, this ensures fair distribution of incoming connections accross threads.
2622      *
2623      * See_Also:
2624      *   https://lwn.net/Articles/542629/
2625      */
2626     REUSEPORT =            SO_REUSEPORT,
2627     LINGER =               SO_LINGER,           /// Linger on close if unsent data is present
2628     OOBINLINE =            SO_OOBINLINE,        /// Receive out-of-band data in band
2629     SNDBUF =               SO_SNDBUF,           /// Send buffer size
2630     RCVBUF =               SO_RCVBUF,           /// Receive buffer size
2631     DONTROUTE =            SO_DONTROUTE,        /// Do not route
2632     SNDTIMEO =             SO_SNDTIMEO,         /// Send timeout
2633     RCVTIMEO =             SO_RCVTIMEO,         /// Receive timeout
2634     ERROR =                SO_ERROR,            /// Retrieve and clear error status
2635     KEEPALIVE =            SO_KEEPALIVE,        /// Enable keep-alive packets
2636     ACCEPTCONN =           SO_ACCEPTCONN,       /// Listen
2637     RCVLOWAT =             SO_RCVLOWAT,         /// Minimum number of input bytes to process
2638     SNDLOWAT =             SO_SNDLOWAT,         /// Minimum number of output bytes to process
2639     TYPE =                 SO_TYPE,             /// Socket type
2640 
2641     // SocketOptionLevel.TCP:
2642     TCP_NODELAY =          .TCP_NODELAY,        /// Disable the Nagle algorithm for send coalescing
2643 
2644     // SocketOptionLevel.IPV6:
2645     IPV6_UNICAST_HOPS =    .IPV6_UNICAST_HOPS,          /// IP unicast hop limit
2646     IPV6_MULTICAST_IF =    .IPV6_MULTICAST_IF,          /// IP multicast interface
2647     IPV6_MULTICAST_LOOP =  .IPV6_MULTICAST_LOOP,        /// IP multicast loopback
2648     IPV6_MULTICAST_HOPS =  .IPV6_MULTICAST_HOPS,        /// IP multicast hops
2649     IPV6_JOIN_GROUP =      .IPV6_JOIN_GROUP,            /// Add an IP group membership
2650     IPV6_LEAVE_GROUP =     .IPV6_LEAVE_GROUP,           /// Drop an IP group membership
2651     IPV6_V6ONLY =          .IPV6_V6ONLY,                /// Treat wildcard bind as AF_INET6-only
2652 }
2653 
2654 
2655 /**
2656  * Class that creates a network communication endpoint using
2657  * the Berkeley sockets interface.
2658  */
2659 class Socket
2660 {
2661 private:
2662     socket_t sock;
2663     AddressFamily _family;
2664 
2665     version (Windows)
2666         bool _blocking = true;         /// Property to get or set whether the socket is blocking or nonblocking.
2667 
2668     // The WinSock timeouts seem to be effectively skewed by a constant
2669     // offset of about half a second (value in milliseconds). This has
2670     // been confirmed on updated (as of Jun 2011) Windows XP, Windows 7
2671     // and Windows Server 2008 R2 boxes. The unittest below tests this
2672     // behavior.
2673     enum WINSOCK_TIMEOUT_SKEW = 500;
2674 
2675     @safe unittest
2676     {
2677         if (runSlowTests)
2678         softUnittest({
2679             import std.datetime.stopwatch : StopWatch;
2680             import std.typecons : Yes;
2681 
2682             enum msecs = 1000;
2683             auto pair = socketPair();
2684             auto testSock = pair[0];
2685             testSock.setOption(SocketOptionLevel.SOCKET,
2686                 SocketOption.RCVTIMEO, dur!"msecs"(msecs));
2687 
2688             auto sw = StopWatch(Yes.autoStart);
2689             ubyte[1] buf;
2690             testSock.receive(buf);
2691             sw.stop();
2692 
2693             Duration readBack = void;
2694             testSock.getOption(SocketOptionLevel.SOCKET, SocketOption.RCVTIMEO, readBack);
2695 
2696             assert(readBack.total!"msecs" == msecs);
2697             assert(sw.peek().total!"msecs" > msecs - 100 && sw.peek().total!"msecs" < msecs + 100);
2698         });
2699     }
2700 
2701     void setSock(socket_t handle)
2702     {
2703         assert(handle != socket_t.init);
2704         sock = handle;
2705 
2706         // Set the option to disable SIGPIPE on send() if the platform
2707         // has it (e.g. on OS X).
2708         static if (is(typeof(SO_NOSIGPIPE)))
2709         {
2710             setOption(SocketOptionLevel.SOCKET, cast(SocketOption) SO_NOSIGPIPE, true);
2711         }
2712     }
2713 
2714 
2715     // For use with accepting().
2716     protected this() pure nothrow @nogc
2717     {
2718     }
2719 
2720 
2721 public:
2722 
2723     /**
2724      * Create a blocking socket. If a single protocol type exists to support
2725      * this socket type within the address family, the `ProtocolType` may be
2726      * omitted.
2727      */
2728     this(AddressFamily af, SocketType type, ProtocolType protocol) @trusted
2729     {
2730         _family = af;
2731         auto handle = cast(socket_t) socket(af, type, protocol);
2732         if (handle == socket_t.init)
2733             throw new SocketOSException("Unable to create socket");
2734         setSock(handle);
2735     }
2736 
2737     /// ditto
2738     this(AddressFamily af, SocketType type)
2739     {
2740         /* A single protocol exists to support this socket type within the
2741          * protocol family, so the ProtocolType is assumed.
2742          */
2743         this(af, type, cast(ProtocolType) 0);         // Pseudo protocol number.
2744     }
2745 
2746 
2747     /// ditto
2748     this(AddressFamily af, SocketType type, scope const(char)[] protocolName) @trusted
2749     {
2750         protoent* proto;
2751         proto = getprotobyname(protocolName.tempCString());
2752         if (!proto)
2753             throw new SocketOSException("Unable to find the protocol");
2754         this(af, type, cast(ProtocolType) proto.p_proto);
2755     }
2756 
2757 
2758     /**
2759      * Create a blocking socket using the parameters from the specified
2760      * `AddressInfo` structure.
2761      */
2762     this(const scope AddressInfo info)
2763     {
2764         this(info.family, info.type, info.protocol);
2765     }
2766 
2767     /// Use an existing socket handle.
2768     this(socket_t sock, AddressFamily af) pure nothrow @nogc
2769     {
2770         assert(sock != socket_t.init);
2771         this.sock = sock;
2772         this._family = af;
2773     }
2774 
2775 
2776     ~this() nothrow @nogc
2777     {
2778         close();
2779     }
2780 
2781 
2782     /// Get underlying socket handle.
2783     @property socket_t handle() const pure nothrow @nogc
2784     {
2785         return sock;
2786     }
2787 
2788     /**
2789      * Releases the underlying socket handle from the Socket object. Once it
2790      * is released, you cannot use the Socket object's methods anymore. This
2791      * also means the Socket destructor will no longer close the socket - it
2792      * becomes your responsibility.
2793      *
2794      * To get the handle without releasing it, use the `handle` property.
2795      */
2796     @property socket_t release() pure nothrow @nogc
2797     {
2798         auto h = sock;
2799         this.sock = socket_t.init;
2800         return h;
2801     }
2802 
2803     /**
2804      * Get/set socket's blocking flag.
2805      *
2806      * When a socket is blocking, calls to receive(), accept(), and send()
2807      * will block and wait for data/action.
2808      * A non-blocking socket will immediately return instead of blocking.
2809      */
2810     @property bool blocking() @trusted const nothrow @nogc
2811     {
2812         version (Windows)
2813         {
2814             return _blocking;
2815         }
2816         else version (Posix)
2817         {
2818             return !(fcntl(handle, F_GETFL, 0) & O_NONBLOCK);
2819         }
2820     }
2821 
2822     /// ditto
2823     @property void blocking(bool byes) @trusted
2824     {
2825         version (Windows)
2826         {
2827             uint num = !byes;
2828             if (_SOCKET_ERROR == ioctlsocket(sock, FIONBIO, &num))
2829                 goto err;
2830             _blocking = byes;
2831         }
2832         else version (Posix)
2833         {
2834             int x = fcntl(sock, F_GETFL, 0);
2835             if (-1 == x)
2836                 goto err;
2837             if (byes)
2838                 x &= ~O_NONBLOCK;
2839             else
2840                 x |= O_NONBLOCK;
2841             if (-1 == fcntl(sock, F_SETFL, x))
2842                 goto err;
2843         }
2844         return;         // Success.
2845 
2846  err:
2847         throw new SocketOSException("Unable to set socket blocking");
2848     }
2849 
2850 
2851     /// Get the socket's address family.
2852     @property AddressFamily addressFamily()
2853     {
2854         return _family;
2855     }
2856 
2857     /// Property that indicates if this is a valid, alive socket.
2858     @property bool isAlive() @trusted const
2859     {
2860         int type;
2861         socklen_t typesize = cast(socklen_t) type.sizeof;
2862         return !getsockopt(sock, SOL_SOCKET, SO_TYPE, cast(char*)&type, &typesize);
2863     }
2864 
2865     /**
2866      * Associate a local address with this socket.
2867      *
2868      * Params:
2869      *     addr = The $(LREF Address) to associate this socket with.
2870      *
2871      * Throws: $(LREF SocketOSException) when unable to bind the socket.
2872      */
2873     void bind(Address addr) @trusted
2874     {
2875         if (_SOCKET_ERROR == .bind(sock, addr.name, addr.nameLen))
2876             throw new SocketOSException("Unable to bind socket");
2877     }
2878 
2879     /**
2880      * Establish a connection. If the socket is blocking, connect waits for
2881      * the connection to be made. If the socket is nonblocking, connect
2882      * returns immediately and the connection attempt is still in progress.
2883      */
2884     void connect(Address to) @trusted
2885     {
2886         if (_SOCKET_ERROR == .connect(sock, to.name, to.nameLen))
2887         {
2888             int err;
2889             err = _lasterr();
2890 
2891             if (!blocking)
2892             {
2893                 version (Windows)
2894                 {
2895                     if (WSAEWOULDBLOCK == err)
2896                         return;
2897                 }
2898                 else version (Posix)
2899                 {
2900                     if (EINPROGRESS == err)
2901                         return;
2902                 }
2903                 else
2904                 {
2905                     static assert(0);
2906                 }
2907             }
2908             throw new SocketOSException("Unable to connect socket", err);
2909         }
2910     }
2911 
2912     /**
2913      * Listen for an incoming connection. `bind` must be called before you
2914      * can `listen`. The `backlog` is a request of how many pending
2915      * incoming connections are queued until `accept`ed.
2916      */
2917     void listen(int backlog) @trusted
2918     {
2919         if (_SOCKET_ERROR == .listen(sock, backlog))
2920             throw new SocketOSException("Unable to listen on socket");
2921     }
2922 
2923     /**
2924      * Called by `accept` when a new `Socket` must be created for a new
2925      * connection. To use a derived class, override this method and return an
2926      * instance of your class. The returned `Socket`'s handle must not be
2927      * set; `Socket` has a protected constructor `this()` to use in this
2928      * situation.
2929      *
2930      * Override to use a derived class.
2931      * The returned socket's handle must not be set.
2932      */
2933     protected Socket accepting() pure nothrow
2934     {
2935         return new Socket;
2936     }
2937 
2938     /**
2939      * Accept an incoming connection. If the socket is blocking, `accept`
2940      * waits for a connection request. Throws `SocketAcceptException` if
2941      * unable to _accept. See `accepting` for use with derived classes.
2942      */
2943     Socket accept() @trusted
2944     {
2945         auto newsock = cast(socket_t).accept(sock, null, null);
2946         if (socket_t.init == newsock)
2947             throw new SocketAcceptException("Unable to accept socket connection");
2948 
2949         Socket newSocket;
2950         try
2951         {
2952             newSocket = accepting();
2953             assert(newSocket.sock == socket_t.init);
2954 
2955             newSocket.setSock(newsock);
2956             version (Windows)
2957                 newSocket._blocking = _blocking;                 //inherits blocking mode
2958             newSocket._family = _family;             //same family
2959         }
2960         catch (Throwable o)
2961         {
2962             _close(newsock);
2963             throw o;
2964         }
2965 
2966         return newSocket;
2967     }
2968 
2969     /// Disables sends and/or receives.
2970     void shutdown(SocketShutdown how) @trusted nothrow @nogc
2971     {
2972         .shutdown(sock, cast(int) how);
2973     }
2974 
2975 
2976     private static void _close(socket_t sock) @system nothrow @nogc
2977     {
2978         version (Windows)
2979         {
2980             .closesocket(sock);
2981         }
2982         else version (Posix)
2983         {
2984             .close(sock);
2985         }
2986     }
2987 
2988 
2989     /**
2990      * Immediately drop any connections and release socket resources.
2991      * The `Socket` object is no longer usable after `close`.
2992      * Calling `shutdown` before `close` is recommended
2993      * for connection-oriented sockets.
2994      */
2995     void close() scope @trusted nothrow @nogc
2996     {
2997         _close(sock);
2998         sock = socket_t.init;
2999     }
3000 
3001 
3002     /**
3003      * Returns: The local machine's host name
3004      */
3005     static @property string hostName() @trusted     // getter
3006     {
3007         char[256] result;         // Host names are limited to 255 chars.
3008         if (_SOCKET_ERROR == .gethostname(result.ptr, result.length))
3009             throw new SocketOSException("Unable to obtain host name");
3010         return to!string(result.ptr);
3011     }
3012 
3013     /// Remote endpoint `Address`.
3014     @property Address remoteAddress() @trusted
3015     {
3016         Address addr = createAddress();
3017         socklen_t nameLen = addr.nameLen;
3018         if (_SOCKET_ERROR == .getpeername(sock, addr.name, &nameLen))
3019             throw new SocketOSException("Unable to obtain remote socket address");
3020         addr.setNameLen(nameLen);
3021         assert(addr.addressFamily == _family);
3022         return addr;
3023     }
3024 
3025     /// Local endpoint `Address`.
3026     @property Address localAddress() @trusted
3027     {
3028         Address addr = createAddress();
3029         socklen_t nameLen = addr.nameLen;
3030         if (_SOCKET_ERROR == .getsockname(sock, addr.name, &nameLen))
3031             throw new SocketOSException("Unable to obtain local socket address");
3032         addr.setNameLen(nameLen);
3033         assert(addr.addressFamily == _family);
3034         return addr;
3035     }
3036 
3037     /**
3038      * Send or receive error code. See `wouldHaveBlocked`,
3039      * `lastSocketError` and `Socket.getErrorText` for obtaining more
3040      * information about the error.
3041      */
3042     enum int ERROR = _SOCKET_ERROR;
3043 
3044     private static int capToInt(size_t size) nothrow @nogc
3045     {
3046         // Windows uses int instead of size_t for length arguments.
3047         // Luckily, the send/recv functions make no guarantee that
3048         // all the data is sent, so we use that to send at most
3049         // int.max bytes.
3050         return size > size_t(int.max) ? int.max : cast(int) size;
3051     }
3052 
3053     /**
3054      * Send data on the connection. If the socket is blocking and there is no
3055      * buffer space left, `send` waits.
3056      * Returns: The number of bytes actually sent, or `Socket.ERROR` on
3057      * failure.
3058      */
3059     ptrdiff_t send(scope const(void)[] buf, SocketFlags flags) @trusted
3060     {
3061         static if (is(typeof(MSG_NOSIGNAL)))
3062         {
3063             flags = cast(SocketFlags)(flags | MSG_NOSIGNAL);
3064         }
3065         version (Windows)
3066             auto sent = .send(sock, buf.ptr, capToInt(buf.length), cast(int) flags);
3067         else
3068             auto sent = .send(sock, buf.ptr, buf.length, cast(int) flags);
3069         return sent;
3070     }
3071 
3072     /// ditto
3073     ptrdiff_t send(scope const(void)[] buf)
3074     {
3075         return send(buf, SocketFlags.NONE);
3076     }
3077 
3078     /**
3079      * Send data to a specific destination Address. If the destination address is
3080      * not specified, a connection must have been made and that address is used.
3081      * If the socket is blocking and there is no buffer space left, `sendTo` waits.
3082      * Returns: The number of bytes actually sent, or `Socket.ERROR` on
3083      * failure.
3084      */
3085     ptrdiff_t sendTo(scope const(void)[] buf, SocketFlags flags, Address to) @trusted
3086     {
3087         static if (is(typeof(MSG_NOSIGNAL)))
3088         {
3089             flags = cast(SocketFlags)(flags | MSG_NOSIGNAL);
3090         }
3091         version (Windows)
3092             return .sendto(
3093                        sock, buf.ptr, capToInt(buf.length),
3094                        cast(int) flags, to.name, to.nameLen
3095                        );
3096         else
3097             return .sendto(sock, buf.ptr, buf.length, cast(int) flags, to.name, to.nameLen);
3098     }
3099 
3100     /// ditto
3101     ptrdiff_t sendTo(scope const(void)[] buf, Address to)
3102     {
3103         return sendTo(buf, SocketFlags.NONE, to);
3104     }
3105 
3106 
3107     //assumes you connect()ed
3108     /// ditto
3109     ptrdiff_t sendTo(scope const(void)[] buf, SocketFlags flags) @trusted
3110     {
3111         static if (is(typeof(MSG_NOSIGNAL)))
3112         {
3113             flags = cast(SocketFlags)(flags | MSG_NOSIGNAL);
3114         }
3115         version (Windows)
3116             return .sendto(sock, buf.ptr, capToInt(buf.length), cast(int) flags, null, 0);
3117         else
3118             return .sendto(sock, buf.ptr, buf.length, cast(int) flags, null, 0);
3119     }
3120 
3121 
3122     //assumes you connect()ed
3123     /// ditto
3124     ptrdiff_t sendTo(scope const(void)[] buf)
3125     {
3126         return sendTo(buf, SocketFlags.NONE);
3127     }
3128 
3129 
3130     /**
3131      * Receive data on the connection. If the socket is blocking, `receive`
3132      * waits until there is data to be received.
3133      * Returns: The number of bytes actually received, `0` if the remote side
3134      * has closed the connection, or `Socket.ERROR` on failure.
3135      */
3136     ptrdiff_t receive(scope void[] buf, SocketFlags flags) @trusted
3137     {
3138         version (Windows)         // Does not use size_t
3139         {
3140             return buf.length
3141                    ? .recv(sock, buf.ptr, capToInt(buf.length), cast(int) flags)
3142                    : 0;
3143         }
3144         else
3145         {
3146             return buf.length
3147                    ? .recv(sock, buf.ptr, buf.length, cast(int) flags)
3148                    : 0;
3149         }
3150     }
3151 
3152     /// ditto
3153     ptrdiff_t receive(scope void[] buf)
3154     {
3155         return receive(buf, SocketFlags.NONE);
3156     }
3157 
3158     /**
3159      * Receive data and get the remote endpoint `Address`.
3160      * If the socket is blocking, `receiveFrom` waits until there is data to
3161      * be received.
3162      * Returns: The number of bytes actually received, `0` if the remote side
3163      * has closed the connection, or `Socket.ERROR` on failure.
3164      */
3165     ptrdiff_t receiveFrom(scope void[] buf, SocketFlags flags, ref Address from) @trusted
3166     {
3167         if (!buf.length)         //return 0 and don't think the connection closed
3168             return 0;
3169         if (from is null || from.addressFamily != _family)
3170             from = createAddress();
3171         socklen_t nameLen = from.nameLen;
3172         version (Windows)
3173             auto read = .recvfrom(sock, buf.ptr, capToInt(buf.length), cast(int) flags, from.name, &nameLen);
3174 
3175         else
3176             auto read = .recvfrom(sock, buf.ptr, buf.length, cast(int) flags, from.name, &nameLen);
3177 
3178         if (read >= 0)
3179         {
3180             from.setNameLen(nameLen);
3181             assert(from.addressFamily == _family);
3182         }
3183         return read;
3184     }
3185 
3186 
3187     /// ditto
3188     ptrdiff_t receiveFrom(scope void[] buf, ref Address from)
3189     {
3190         return receiveFrom(buf, SocketFlags.NONE, from);
3191     }
3192 
3193 
3194     //assumes you connect()ed
3195     /// ditto
3196     ptrdiff_t receiveFrom(scope void[] buf, SocketFlags flags) @trusted
3197     {
3198         if (!buf.length)         //return 0 and don't think the connection closed
3199             return 0;
3200         version (Windows)
3201         {
3202             auto read = .recvfrom(sock, buf.ptr, capToInt(buf.length), cast(int) flags, null, null);
3203             // if (!read) //connection closed
3204             return read;
3205         }
3206         else
3207         {
3208             auto read = .recvfrom(sock, buf.ptr, buf.length, cast(int) flags, null, null);
3209             // if (!read) //connection closed
3210             return read;
3211         }
3212     }
3213 
3214 
3215     //assumes you connect()ed
3216     /// ditto
3217     ptrdiff_t receiveFrom(scope void[] buf)
3218     {
3219         return receiveFrom(buf, SocketFlags.NONE);
3220     }
3221 
3222 
3223     /**
3224      * Get a socket option.
3225      * Returns: The number of bytes written to `result`.
3226      * The length, in bytes, of the actual result - very different from getsockopt()
3227      */
3228     int getOption(SocketOptionLevel level, SocketOption option, scope void[] result) @trusted
3229     {
3230         socklen_t len = cast(socklen_t) result.length;
3231         if (_SOCKET_ERROR == .getsockopt(sock, cast(int) level, cast(int) option, result.ptr, &len))
3232             throw new SocketOSException("Unable to get socket option");
3233         return len;
3234     }
3235 
3236 
3237     /// Common case of getting integer and boolean options.
3238     int getOption(SocketOptionLevel level, SocketOption option, out int32_t result) @trusted
3239     {
3240         return getOption(level, option, (&result)[0 .. 1]);
3241     }
3242 
3243 
3244     /// Get the linger option.
3245     int getOption(SocketOptionLevel level, SocketOption option, out Linger result) @trusted
3246     {
3247         //return getOption(cast(SocketOptionLevel) SocketOptionLevel.SOCKET, SocketOption.LINGER, (&result)[0 .. 1]);
3248         return getOption(level, option, (&result.clinger)[0 .. 1]);
3249     }
3250 
3251     /// Get a timeout (duration) option.
3252     void getOption(SocketOptionLevel level, SocketOption option, out Duration result) @trusted
3253     {
3254         enforce(option == SocketOption.SNDTIMEO || option == SocketOption.RCVTIMEO,
3255                 new SocketParameterException("Not a valid timeout option: " ~ to!string(option)));
3256         // WinSock returns the timeout values as a milliseconds DWORD,
3257         // while Linux and BSD return a timeval struct.
3258         version (Windows)
3259         {
3260             int msecs;
3261             getOption(level, option, (&msecs)[0 .. 1]);
3262             if (option == SocketOption.RCVTIMEO)
3263                 msecs += WINSOCK_TIMEOUT_SKEW;
3264             result = dur!"msecs"(msecs);
3265         }
3266         else version (Posix)
3267         {
3268             TimeVal tv;
3269             getOption(level, option, (&tv.ctimeval)[0 .. 1]);
3270             result = dur!"seconds"(tv.seconds) + dur!"usecs"(tv.microseconds);
3271         }
3272         else static assert(false);
3273     }
3274 
3275     /// Set a socket option.
3276     void setOption(SocketOptionLevel level, SocketOption option, scope void[] value) @trusted
3277     {
3278         if (_SOCKET_ERROR == .setsockopt(sock, cast(int) level,
3279                                         cast(int) option, value.ptr, cast(uint) value.length))
3280             throw new SocketOSException("Unable to set socket option");
3281     }
3282 
3283 
3284     /// Common case for setting integer and boolean options.
3285     void setOption(SocketOptionLevel level, SocketOption option, int32_t value) @trusted
3286     {
3287         setOption(level, option, (&value)[0 .. 1]);
3288     }
3289 
3290 
3291     /// Set the linger option.
3292     void setOption(SocketOptionLevel level, SocketOption option, Linger value) @trusted
3293     {
3294         //setOption(cast(SocketOptionLevel) SocketOptionLevel.SOCKET, SocketOption.LINGER, (&value)[0 .. 1]);
3295         setOption(level, option, (&value.clinger)[0 .. 1]);
3296     }
3297 
3298     /**
3299      * Sets a timeout (duration) option, i.e. `SocketOption.SNDTIMEO` or
3300      * `RCVTIMEO`. Zero indicates no timeout.
3301      *
3302      * In a typical application, you might also want to consider using
3303      * a non-blocking socket instead of setting a timeout on a blocking one.
3304      *
3305      * Note: While the receive timeout setting is generally quite accurate
3306      * on *nix systems even for smaller durations, there are two issues to
3307      * be aware of on Windows: First, although undocumented, the effective
3308      * timeout duration seems to be the one set on the socket plus half
3309      * a second. `setOption()` tries to compensate for that, but still,
3310      * timeouts under 500ms are not possible on Windows. Second, be aware
3311      * that the actual amount of time spent until a blocking call returns
3312      * randomly varies on the order of 10ms.
3313      *
3314      * Params:
3315      *   level  = The level at which a socket option is defined.
3316      *   option = Either `SocketOption.SNDTIMEO` or `SocketOption.RCVTIMEO`.
3317      *   value  = The timeout duration to set. Must not be negative.
3318      *
3319      * Throws: `SocketException` if setting the options fails.
3320      *
3321      * Example:
3322      * ---
3323      * import std.datetime;
3324      * import std.typecons;
3325      * auto pair = socketPair();
3326      * scope(exit) foreach (s; pair) s.close();
3327      *
3328      * // Set a receive timeout, and then wait at one end of
3329      * // the socket pair, knowing that no data will arrive.
3330      * pair[0].setOption(SocketOptionLevel.SOCKET,
3331      *     SocketOption.RCVTIMEO, dur!"seconds"(1));
3332      *
3333      * auto sw = StopWatch(Yes.autoStart);
3334      * ubyte[1] buffer;
3335      * pair[0].receive(buffer);
3336      * writefln("Waited %s ms until the socket timed out.",
3337      *     sw.peek.msecs);
3338      * ---
3339      */
3340     void setOption(SocketOptionLevel level, SocketOption option, Duration value) @trusted
3341     {
3342         enforce(option == SocketOption.SNDTIMEO || option == SocketOption.RCVTIMEO,
3343                 new SocketParameterException("Not a valid timeout option: " ~ to!string(option)));
3344 
3345         enforce(value >= dur!"hnsecs"(0), new SocketParameterException(
3346                     "Timeout duration must not be negative."));
3347 
3348         version (Windows)
3349         {
3350             import std.algorithm.comparison : max;
3351 
3352             auto msecs = to!int(value.total!"msecs");
3353             if (msecs != 0 && option == SocketOption.RCVTIMEO)
3354                 msecs = max(1, msecs - WINSOCK_TIMEOUT_SKEW);
3355             setOption(level, option, msecs);
3356         }
3357         else version (Posix)
3358         {
3359             _ctimeval tv;
3360             value.split!("seconds", "usecs")(tv.tv_sec, tv.tv_usec);
3361             setOption(level, option, (&tv)[0 .. 1]);
3362         }
3363         else static assert(false);
3364     }
3365 
3366     /**
3367      * Get a text description of this socket's error status, and clear the
3368      * socket's error status.
3369      */
3370     string getErrorText()
3371     {
3372         int32_t error;
3373         getOption(SocketOptionLevel.SOCKET, SocketOption.ERROR, error);
3374         return formatSocketError(error);
3375     }
3376 
3377     /**
3378      * Enables TCP keep-alive with the specified parameters.
3379      *
3380      * Params:
3381      *   time     = Number of seconds with no activity until the first
3382      *              keep-alive packet is sent.
3383      *   interval = Number of seconds between when successive keep-alive
3384      *              packets are sent if no acknowledgement is received.
3385      *
3386      * Throws: `SocketOSException` if setting the options fails, or
3387      * `SocketFeatureException` if setting keep-alive parameters is
3388      * unsupported on the current platform.
3389      */
3390     void setKeepAlive(int time, int interval) @trusted
3391     {
3392         version (Windows)
3393         {
3394             tcp_keepalive options;
3395             options.onoff = 1;
3396             options.keepalivetime = time * 1000;
3397             options.keepaliveinterval = interval * 1000;
3398             uint cbBytesReturned;
3399             enforce(WSAIoctl(sock, SIO_KEEPALIVE_VALS,
3400                              &options, options.sizeof,
3401                              null, 0,
3402                              &cbBytesReturned, null, null) == 0,
3403                     new SocketOSException("Error setting keep-alive"));
3404         }
3405         else
3406         static if (is(typeof(TCP_KEEPIDLE)) && is(typeof(TCP_KEEPINTVL)))
3407         {
3408             setOption(SocketOptionLevel.TCP, cast(SocketOption) TCP_KEEPIDLE, time);
3409             setOption(SocketOptionLevel.TCP, cast(SocketOption) TCP_KEEPINTVL, interval);
3410             setOption(SocketOptionLevel.SOCKET, SocketOption.KEEPALIVE, true);
3411         }
3412         else
3413             throw new SocketFeatureException("Setting keep-alive options " ~
3414                 "is not supported on this platform");
3415     }
3416 
3417     /**
3418      * Wait for a socket to change status. A wait timeout of $(REF Duration, core, time) or
3419      * `TimeVal`, may be specified; if a timeout is not specified or the
3420      * `TimeVal` is `null`, the maximum timeout is used. The `TimeVal`
3421      * timeout has an unspecified value when `select` returns.
3422      * Returns: The number of sockets with status changes, `0` on timeout,
3423      * or `-1` on interruption. If the return value is greater than `0`,
3424      * the `SocketSets` are updated to only contain the sockets having status
3425      * changes. For a connecting socket, a write status change means the
3426      * connection is established and it's able to send. For a listening socket,
3427      * a read status change means there is an incoming connection request and
3428      * it's able to accept.
3429      *
3430      * `SocketSet`'s updated to include only those sockets which an event occured.
3431      * For a `connect()`ing socket, writeability means connected.
3432      * For a `listen()`ing socket, readability means listening
3433      * `Winsock`; possibly internally limited to 64 sockets per set.
3434      *
3435      * Returns:
3436      * the number of events, 0 on timeout, or -1 on interruption
3437      */
3438     static int select(SocketSet checkRead, SocketSet checkWrite, SocketSet checkError, Duration timeout) @trusted
3439     {
3440         auto vals = timeout.split!("seconds", "usecs")();
3441         TimeVal tv;
3442         tv.seconds      = cast(tv.tv_sec_t ) vals.seconds;
3443         tv.microseconds = cast(tv.tv_usec_t) vals.usecs;
3444         return select(checkRead, checkWrite, checkError, &tv);
3445     }
3446 
3447     /// ditto
3448     //maximum timeout
3449     static int select(SocketSet checkRead, SocketSet checkWrite, SocketSet checkError)
3450     {
3451         return select(checkRead, checkWrite, checkError, null);
3452     }
3453 
3454     /// Ditto
3455     static int select(SocketSet checkRead, SocketSet checkWrite, SocketSet checkError, TimeVal* timeout) @trusted
3456     in
3457     {
3458         //make sure none of the SocketSet's are the same object
3459         if (checkRead)
3460         {
3461             assert(checkRead !is checkWrite);
3462             assert(checkRead !is checkError);
3463         }
3464         if (checkWrite)
3465         {
3466             assert(checkWrite !is checkError);
3467         }
3468     }
3469     do
3470     {
3471         fd_set* fr, fw, fe;
3472         int n = 0;
3473 
3474         version (Windows)
3475         {
3476             // Windows has a problem with empty fd_set`s that aren't null.
3477             fr = checkRead  && checkRead.count  ? checkRead.toFd_set()  : null;
3478             fw = checkWrite && checkWrite.count ? checkWrite.toFd_set() : null;
3479             fe = checkError && checkError.count ? checkError.toFd_set() : null;
3480         }
3481         else
3482         {
3483             if (checkRead)
3484             {
3485                 fr = checkRead.toFd_set();
3486                 n = checkRead.selectn();
3487             }
3488             else
3489             {
3490                 fr = null;
3491             }
3492 
3493             if (checkWrite)
3494             {
3495                 fw = checkWrite.toFd_set();
3496                 int _n;
3497                 _n = checkWrite.selectn();
3498                 if (_n > n)
3499                     n = _n;
3500             }
3501             else
3502             {
3503                 fw = null;
3504             }
3505 
3506             if (checkError)
3507             {
3508                 fe = checkError.toFd_set();
3509                 int _n;
3510                 _n = checkError.selectn();
3511                 if (_n > n)
3512                     n = _n;
3513             }
3514             else
3515             {
3516                 fe = null;
3517             }
3518 
3519             // Make sure the sets' capacity matches, to avoid select reading
3520             // out of bounds just because one set was bigger than another
3521             if (checkRead ) checkRead .setMinCapacity(n);
3522             if (checkWrite) checkWrite.setMinCapacity(n);
3523             if (checkError) checkError.setMinCapacity(n);
3524         }
3525 
3526         int result = .select(n, fr, fw, fe, &timeout.ctimeval);
3527 
3528         version (Windows)
3529         {
3530             if (_SOCKET_ERROR == result && WSAGetLastError() == WSAEINTR)
3531                 return -1;
3532         }
3533         else version (Posix)
3534         {
3535             if (_SOCKET_ERROR == result && errno == EINTR)
3536                 return -1;
3537         }
3538         else
3539         {
3540             static assert(0);
3541         }
3542 
3543         if (_SOCKET_ERROR == result)
3544             throw new SocketOSException("Socket select error");
3545 
3546         return result;
3547     }
3548 
3549 
3550     /**
3551      * Can be overridden to support other addresses.
3552      * Returns: A new `Address` object for the current address family.
3553      */
3554     protected Address createAddress() pure nothrow
3555     {
3556         Address result;
3557         switch (_family)
3558         {
3559         static if (is(sockaddr_un))
3560         {
3561             case AddressFamily.UNIX:
3562                 result = new UnixAddress;
3563                 break;
3564         }
3565 
3566         case AddressFamily.INET:
3567             result = new InternetAddress;
3568             break;
3569 
3570         case AddressFamily.INET6:
3571             result = new Internet6Address;
3572             break;
3573 
3574         default:
3575             result = new UnknownAddress;
3576         }
3577         return result;
3578     }
3579 
3580 }
3581 
3582 
3583 /// Shortcut class for a TCP Socket.
3584 class TcpSocket: Socket
3585 {
3586     /// Constructs a blocking TCP Socket.
3587     this(AddressFamily family)
3588     {
3589         super(family, SocketType.STREAM, ProtocolType.TCP);
3590     }
3591 
3592     /// Constructs a blocking IPv4 TCP Socket.
3593     this()
3594     {
3595         this(AddressFamily.INET);
3596     }
3597 
3598 
3599     //shortcut
3600     /// Constructs a blocking TCP Socket and connects to the given `Address`.
3601     this(Address connectTo)
3602     {
3603         this(connectTo.addressFamily);
3604         connect(connectTo);
3605     }
3606 }
3607 
3608 
3609 /// Shortcut class for a UDP Socket.
3610 class UdpSocket: Socket
3611 {
3612     /// Constructs a blocking UDP Socket.
3613     this(AddressFamily family)
3614     {
3615         super(family, SocketType.DGRAM, ProtocolType.UDP);
3616     }
3617 
3618 
3619     /// Constructs a blocking IPv4 UDP Socket.
3620     this()
3621     {
3622         this(AddressFamily.INET);
3623     }
3624 }
3625 
3626 @safe unittest
3627 {
3628     byte[] buf;
3629     buf.length = 1;
3630     Address addr;
3631     auto s = new UdpSocket;
3632     s.blocking = false;
3633     s.bind(new InternetAddress(InternetAddress.PORT_ANY));
3634     s.receiveFrom(buf, addr);
3635 }
3636 
3637 // https://issues.dlang.org/show_bug.cgi?id=16514
3638 @safe unittest
3639 {
3640     void checkAttributes(string attributes)()
3641     {
3642         mixin(attributes ~ q{ void function() fun = {};});
3643         fun();
3644     }
3645 
3646     class TestSocket : Socket
3647     {
3648         override
3649         {
3650             @property pure nothrow @nogc @safe socket_t handle() const
3651             {
3652                 checkAttributes!q{pure nothrow @nogc @safe}; assert(0);
3653             }
3654             @property nothrow @nogc @trusted bool blocking() const
3655             {
3656                 checkAttributes!q{nothrow @nogc @trusted}; assert(0);
3657             }
3658             @property @trusted void blocking(bool byes)
3659             {
3660                 checkAttributes!q{@trusted};
3661             }
3662             @property @safe AddressFamily addressFamily()
3663             {
3664                 checkAttributes!q{@safe}; assert(0);
3665             }
3666             @property @trusted bool isAlive() const
3667             {
3668                 checkAttributes!q{@trusted}; assert(0);
3669             }
3670             @trusted void bind(Address addr)
3671             {
3672                 checkAttributes!q{@trusted};
3673             }
3674             @trusted void connect(Address to)
3675             {
3676                 checkAttributes!q{@trusted};
3677             }
3678             @trusted void listen(int backlog)
3679             {
3680                 checkAttributes!q{@trusted};
3681             }
3682             protected pure nothrow @safe Socket accepting()
3683             {
3684                 checkAttributes!q{pure nothrow @safe}; assert(0);
3685             }
3686             @trusted Socket accept()
3687             {
3688                 checkAttributes!q{@trusted}; assert(0);
3689             }
3690             nothrow @nogc @trusted void shutdown(SocketShutdown how)
3691             {
3692                 checkAttributes!q{nothrow @nogc @trusted};
3693             }
3694             nothrow @nogc @trusted scope void close()
3695             {
3696                 checkAttributes!q{nothrow @nogc @trusted};
3697             }
3698             @property @trusted Address remoteAddress()
3699             {
3700                 checkAttributes!q{@trusted}; assert(0);
3701             }
3702             @property @trusted Address localAddress()
3703             {
3704                 checkAttributes!q{@trusted}; assert(0);
3705             }
3706             @trusted ptrdiff_t send(scope const(void)[] buf, SocketFlags flags)
3707             {
3708                 checkAttributes!q{@trusted}; assert(0);
3709             }
3710             @safe ptrdiff_t send(scope const(void)[] buf)
3711             {
3712                 checkAttributes!q{@safe}; assert(0);
3713             }
3714             @trusted ptrdiff_t sendTo(scope const(void)[] buf, SocketFlags flags, Address to)
3715             {
3716                 checkAttributes!q{@trusted}; assert(0);
3717             }
3718             @safe ptrdiff_t sendTo(scope const(void)[] buf, Address to)
3719             {
3720                 checkAttributes!q{@safe}; assert(0);
3721             }
3722             @trusted ptrdiff_t sendTo(scope const(void)[] buf, SocketFlags flags)
3723             {
3724                 checkAttributes!q{@trusted}; assert(0);
3725             }
3726             @safe ptrdiff_t sendTo(scope const(void)[] buf)
3727             {
3728                 checkAttributes!q{@safe}; assert(0);
3729             }
3730             @trusted ptrdiff_t receive(scope void[] buf, SocketFlags flags)
3731             {
3732                 checkAttributes!q{@trusted}; assert(0);
3733             }
3734             @safe ptrdiff_t receive(scope void[] buf)
3735             {
3736                 checkAttributes!q{@safe}; assert(0);
3737             }
3738             @trusted ptrdiff_t receiveFrom(scope void[] buf, SocketFlags flags, ref Address from)
3739             {
3740                 checkAttributes!q{@trusted}; assert(0);
3741             }
3742             @safe ptrdiff_t receiveFrom(scope void[] buf, ref Address from)
3743             {
3744                 checkAttributes!q{@safe}; assert(0);
3745             }
3746             @trusted ptrdiff_t receiveFrom(scope void[] buf, SocketFlags flags)
3747             {
3748                 checkAttributes!q{@trusted}; assert(0);
3749             }
3750             @safe ptrdiff_t receiveFrom(scope void[] buf)
3751             {
3752                 checkAttributes!q{@safe}; assert(0);
3753             }
3754             @trusted int getOption(SocketOptionLevel level, SocketOption option, scope void[] result)
3755             {
3756                 checkAttributes!q{@trusted}; assert(0);
3757             }
3758             @trusted int getOption(SocketOptionLevel level, SocketOption option, out int32_t result)
3759             {
3760                 checkAttributes!q{@trusted}; assert(0);
3761             }
3762             @trusted int getOption(SocketOptionLevel level, SocketOption option, out Linger result)
3763             {
3764                 checkAttributes!q{@trusted}; assert(0);
3765             }
3766             @trusted void getOption(SocketOptionLevel level, SocketOption option, out Duration result)
3767             {
3768                 checkAttributes!q{@trusted};
3769             }
3770             @trusted void setOption(SocketOptionLevel level, SocketOption option, scope void[] value)
3771             {
3772                 checkAttributes!q{@trusted};
3773             }
3774             @trusted void setOption(SocketOptionLevel level, SocketOption option, int32_t value)
3775             {
3776                 checkAttributes!q{@trusted};
3777             }
3778             @trusted void setOption(SocketOptionLevel level, SocketOption option, Linger value)
3779             {
3780                 checkAttributes!q{@trusted};
3781             }
3782             @trusted void setOption(SocketOptionLevel level, SocketOption option, Duration value)
3783             {
3784                 checkAttributes!q{@trusted};
3785             }
3786             @safe string getErrorText()
3787             {
3788                 checkAttributes!q{@safe}; assert(0);
3789             }
3790             @trusted void setKeepAlive(int time, int interval)
3791             {
3792                 checkAttributes!q{@trusted};
3793             }
3794             protected pure nothrow @safe Address createAddress()
3795             {
3796                 checkAttributes!q{pure nothrow @safe}; assert(0);
3797             }
3798         }
3799     }
3800 }
3801 
3802 /**
3803  * Creates a pair of connected sockets.
3804  *
3805  * The two sockets are indistinguishable.
3806  *
3807  * Throws: `SocketException` if creation of the sockets fails.
3808  */
3809 Socket[2] socketPair() @trusted
3810 {
3811     version (Posix)
3812     {
3813         int[2] socks;
3814         if (socketpair(AF_UNIX, SOCK_STREAM, 0, socks) == -1)
3815             throw new SocketOSException("Unable to create socket pair");
3816 
3817         Socket toSocket(size_t id)
3818         {
3819             auto s = new Socket;
3820             s.setSock(cast(socket_t) socks[id]);
3821             s._family = AddressFamily.UNIX;
3822             return s;
3823         }
3824 
3825         return [toSocket(0), toSocket(1)];
3826     }
3827     else version (Windows)
3828     {
3829         // We do not have socketpair() on Windows, just manually create a
3830         // pair of sockets connected over some localhost port.
3831         Socket[2] result;
3832 
3833         auto listener = new TcpSocket();
3834         listener.setOption(SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, true);
3835         listener.bind(new InternetAddress(INADDR_LOOPBACK, InternetAddress.PORT_ANY));
3836         auto addr = listener.localAddress;
3837         listener.listen(1);
3838 
3839         result[0] = new TcpSocket(addr);
3840         result[1] = listener.accept();
3841 
3842         listener.close();
3843         return result;
3844     }
3845     else
3846         static assert(false);
3847 }
3848 
3849 ///
3850 @safe unittest
3851 {
3852     immutable ubyte[4] data = [1, 2, 3, 4];
3853     auto pair = socketPair();
3854     scope(exit) foreach (s; pair) s.close();
3855 
3856     pair[0].send(data[]);
3857 
3858     auto buf = new ubyte[data.length];
3859     pair[1].receive(buf);
3860     assert(buf == data);
3861 }