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