The OpenD Programming Language

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