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