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