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