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