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