doc: Describe limitations re Ada, D, and Go on FreeBSD
[official-gcc.git] / libphobos / src / std / socket.d
blob4052479f9ca677978babe11aa2391f35022cf670
1 // Written in the D programming language
3 // NOTE: When working on this module, be sure to run tests with -debug=std_socket
4 // E.g.: dmd -version=StdUnittest -debug=std_socket -unittest -main -run socket
5 // This will enable some tests which are too slow or flaky to run as part of CI.
7 /*
8 Copyright (C) 2004-2011 Christopher E. Miller
10 socket.d 1.4
11 Jan 2011
13 Thanks to Benjamin Herr for his assistance.
16 /**
17 * Socket primitives.
18 * Example: See $(SAMPLESRC listener.d) and $(SAMPLESRC htmlget.d)
19 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
20 * Authors: Christopher E. Miller, $(HTTP klickverbot.at, David Nadlinger),
21 * $(HTTP thecybershadow.net, Vladimir Panteleev)
22 * Source: $(PHOBOSSRC std/socket.d)
25 module std.socket;
27 import core.stdc.stdint, core.stdc.stdlib, core.stdc.string, std.conv, std.string;
29 import core.stdc.config;
30 import core.time : dur, Duration;
31 import std.exception;
33 import std.internal.cstring;
35 version (iOS)
36 version = iOSDerived;
37 else version (TVOS)
38 version = iOSDerived;
39 else version (WatchOS)
40 version = iOSDerived;
42 @safe:
44 version (Windows)
46 pragma (lib, "ws2_32.lib");
47 pragma (lib, "wsock32.lib");
49 import core.sys.windows.winbase, std.windows.syserror;
50 public import core.sys.windows.winsock2;
51 private alias _ctimeval = core.sys.windows.winsock2.timeval;
52 private alias _clinger = core.sys.windows.winsock2.linger;
54 enum socket_t : SOCKET { INVALID_SOCKET }
55 private const int _SOCKET_ERROR = SOCKET_ERROR;
58 private int _lasterr() nothrow @nogc
60 return WSAGetLastError();
63 else version (Posix)
65 version (linux)
67 enum : int
69 TCP_KEEPIDLE = 4,
70 TCP_KEEPINTVL = 5
74 public import core.sys.posix.netinet.in_;
75 import core.sys.posix.arpa.inet;
76 import core.sys.posix.fcntl;
77 import core.sys.posix.netdb;
78 import core.sys.posix.netinet.tcp;
79 import core.sys.posix.sys.select;
80 import core.sys.posix.sys.socket;
81 import core.sys.posix.sys.time;
82 import core.sys.posix.sys.un : sockaddr_un;
83 import core.sys.posix.unistd;
84 private alias _ctimeval = core.sys.posix.sys.time.timeval;
85 private alias _clinger = core.sys.posix.sys.socket.linger;
87 import core.stdc.errno;
89 enum socket_t : int32_t { _init = -1 }
90 private const int _SOCKET_ERROR = -1;
92 private enum : int
94 SD_RECEIVE = SHUT_RD,
95 SD_SEND = SHUT_WR,
96 SD_BOTH = SHUT_RDWR
99 private int _lasterr() nothrow @nogc
101 return errno;
104 else
106 static assert(0, "No socket support for this platform yet.");
109 version (StdUnittest)
111 // Print a message on exception instead of failing the unittest.
112 private void softUnittest(void delegate() @safe test, int line = __LINE__) @trusted
114 debug (std_socket)
115 test();
116 else
118 import std.stdio : writefln;
120 test();
121 catch (Throwable e)
122 writefln("Ignoring std.socket(%d) test failure (likely caused by flaky environment): %s", line, e.msg);
126 // Without debug=std_socket, still compile the slow tests, just don't run them.
127 debug (std_socket)
128 private enum runSlowTests = true;
129 else
130 private enum runSlowTests = false;
133 /// Base exception thrown by `std.socket`.
134 class SocketException: Exception
136 mixin basicExceptionCtors;
139 version (CRuntime_Glibc) version = GNU_STRERROR;
140 version (CRuntime_UClibc) version = GNU_STRERROR;
143 * Needs to be public so that SocketOSException can be thrown outside of
144 * std.socket (since it uses it as a default argument), but it probably doesn't
145 * need to actually show up in the docs, since there's not really any public
146 * need for it outside of being a default argument.
148 string formatSocketError(int err) @trusted
150 version (Posix)
152 char[80] buf;
153 const(char)* cs;
154 version (GNU_STRERROR)
156 cs = strerror_r(err, buf.ptr, buf.length);
158 else
160 auto errs = strerror_r(err, buf.ptr, buf.length);
161 if (errs == 0)
162 cs = buf.ptr;
163 else
164 return "Socket error " ~ to!string(err);
167 auto len = strlen(cs);
169 if (cs[len - 1] == '\n')
170 len--;
171 if (cs[len - 1] == '\r')
172 len--;
173 return cs[0 .. len].idup;
175 else
176 version (Windows)
178 return generateSysErrorMsg(err);
180 else
181 return "Socket error " ~ to!string(err);
184 /// Returns the error message of the most recently encountered network error.
185 @property string lastSocketError()
187 return formatSocketError(_lasterr());
190 /// Socket exception representing network errors reported by the operating system.
191 class SocketOSException: SocketException
193 int errorCode; /// Platform-specific error code.
196 this(string msg,
197 string file = __FILE__,
198 size_t line = __LINE__,
199 Throwable next = null,
200 int err = _lasterr(),
201 string function(int) @trusted errorFormatter = &formatSocketError)
203 errorCode = err;
205 if (msg.length)
206 super(msg ~ ": " ~ errorFormatter(err), file, line, next);
207 else
208 super(errorFormatter(err), file, line, next);
212 this(string msg,
213 Throwable next,
214 string file = __FILE__,
215 size_t line = __LINE__,
216 int err = _lasterr(),
217 string function(int) @trusted errorFormatter = &formatSocketError)
219 this(msg, file, line, next, err, errorFormatter);
223 this(string msg,
224 int err,
225 string function(int) @trusted errorFormatter = &formatSocketError,
226 string file = __FILE__,
227 size_t line = __LINE__,
228 Throwable next = null)
230 this(msg, file, line, next, err, errorFormatter);
234 /// Socket exception representing invalid parameters specified by user code.
235 class SocketParameterException: SocketException
237 mixin basicExceptionCtors;
241 * Socket exception representing attempts to use network capabilities not
242 * available on the current system.
244 class SocketFeatureException: SocketException
246 mixin basicExceptionCtors;
251 * Returns:
252 * `true` if the last socket operation failed because the socket
253 * was in non-blocking mode and the operation would have blocked,
254 * or if the socket is in blocking mode and set a `SNDTIMEO` or `RCVTIMEO`,
255 * and the operation timed out.
257 bool wouldHaveBlocked() nothrow @nogc
259 version (Windows)
260 return _lasterr() == WSAEWOULDBLOCK || _lasterr() == WSAETIMEDOUT;
261 else version (Posix)
262 return _lasterr() == EAGAIN;
263 else
264 static assert(0, "No socket support for this platform yet.");
267 @safe unittest
269 auto sockets = socketPair();
270 auto s = sockets[0];
271 s.setOption(SocketOptionLevel.SOCKET, SocketOption.RCVTIMEO, dur!"msecs"(10));
272 ubyte[] buffer = new ubyte[](16);
273 auto rec = s.receive(buffer);
274 assert(rec == -1 && wouldHaveBlocked());
278 private immutable
280 typeof(&getnameinfo) getnameinfoPointer;
281 typeof(&getaddrinfo) getaddrinfoPointer;
282 typeof(&freeaddrinfo) freeaddrinfoPointer;
285 shared static this() @system
287 version (Windows)
289 WSADATA wd;
291 // Winsock will still load if an older version is present.
292 // The version is just a request.
293 int val;
294 val = WSAStartup(0x2020, &wd);
295 if (val) // Request Winsock 2.2 for IPv6.
296 throw new SocketOSException("Unable to initialize socket library", val);
298 // These functions may not be present on older Windows versions.
299 // See the comment in InternetAddress.toHostNameString() for details.
300 auto ws2Lib = GetModuleHandleA("ws2_32.dll");
301 if (ws2Lib)
303 getnameinfoPointer = cast(typeof(getnameinfoPointer))
304 GetProcAddress(ws2Lib, "getnameinfo");
305 getaddrinfoPointer = cast(typeof(getaddrinfoPointer))
306 GetProcAddress(ws2Lib, "getaddrinfo");
307 freeaddrinfoPointer = cast(typeof(freeaddrinfoPointer))
308 GetProcAddress(ws2Lib, "freeaddrinfo");
311 else version (Posix)
313 getnameinfoPointer = &getnameinfo;
314 getaddrinfoPointer = &getaddrinfo;
315 freeaddrinfoPointer = &freeaddrinfo;
320 shared static ~this() @system nothrow @nogc
322 version (Windows)
324 WSACleanup();
329 * The communication domain used to resolve an address.
331 enum AddressFamily: ushort
333 UNSPEC = AF_UNSPEC, /// Unspecified address family
334 UNIX = AF_UNIX, /// Local communication (Unix socket)
335 INET = AF_INET, /// Internet Protocol version 4
336 IPX = AF_IPX, /// Novell IPX
337 APPLETALK = AF_APPLETALK, /// AppleTalk
338 INET6 = AF_INET6, /// Internet Protocol version 6
343 * Communication semantics
345 enum SocketType: int
347 STREAM = SOCK_STREAM, /// Sequenced, reliable, two-way communication-based byte streams
348 DGRAM = SOCK_DGRAM, /// Connectionless, unreliable datagrams with a fixed maximum length; data may be lost or arrive out of order
349 RAW = SOCK_RAW, /// Raw protocol access
350 RDM = SOCK_RDM, /// Reliably-delivered message datagrams
351 SEQPACKET = SOCK_SEQPACKET, /// Sequenced, reliable, two-way connection-based datagrams with a fixed maximum length
356 * Protocol
358 enum ProtocolType: int
360 IP = IPPROTO_IP, /// Internet Protocol version 4
361 ICMP = IPPROTO_ICMP, /// Internet Control Message Protocol
362 IGMP = IPPROTO_IGMP, /// Internet Group Management Protocol
363 GGP = IPPROTO_GGP, /// Gateway to Gateway Protocol
364 TCP = IPPROTO_TCP, /// Transmission Control Protocol
365 PUP = IPPROTO_PUP, /// PARC Universal Packet Protocol
366 UDP = IPPROTO_UDP, /// User Datagram Protocol
367 IDP = IPPROTO_IDP, /// Xerox NS protocol
368 RAW = IPPROTO_RAW, /// Raw IP packets
369 IPV6 = IPPROTO_IPV6, /// Internet Protocol version 6
374 * Class for retrieving protocol information.
376 * Example:
377 * ---
378 * auto proto = new Protocol;
379 * writeln("About protocol TCP:");
380 * if (proto.getProtocolByType(ProtocolType.TCP))
382 * writefln(" Name: %s", proto.name);
383 * foreach (string s; proto.aliases)
384 * writefln(" Alias: %s", s);
386 * else
387 * writeln(" No information found");
388 * ---
390 class Protocol
392 /// These members are populated when one of the following functions are called successfully:
393 ProtocolType type;
394 string name; /// ditto
395 string[] aliases; /// ditto
398 void populate(protoent* proto) @system pure nothrow
400 type = cast(ProtocolType) proto.p_proto;
401 name = to!string(proto.p_name);
403 int i;
404 for (i = 0;; i++)
406 if (!proto.p_aliases[i])
407 break;
410 if (i)
412 aliases = new string[i];
413 for (i = 0; i != aliases.length; i++)
415 aliases[i] =
416 to!string(proto.p_aliases[i]);
419 else
421 aliases = null;
425 /** Returns: false on failure */
426 bool getProtocolByName(scope const(char)[] name) @trusted nothrow
428 protoent* proto;
429 proto = getprotobyname(name.tempCString());
430 if (!proto)
431 return false;
432 populate(proto);
433 return true;
437 /** Returns: false on failure */
438 // Same as getprotobynumber().
439 bool getProtocolByType(ProtocolType type) @trusted nothrow
441 protoent* proto;
442 proto = getprotobynumber(type);
443 if (!proto)
444 return false;
445 populate(proto);
446 return true;
451 // Skip this test on Android because getprotobyname/number are
452 // unimplemented in bionic.
453 version (CRuntime_Bionic) {} else
454 @safe unittest
456 // import std.stdio : writefln;
457 softUnittest({
458 Protocol proto = new Protocol;
459 assert(proto.getProtocolByType(ProtocolType.TCP));
460 //writeln("About protocol TCP:");
461 //writefln("\tName: %s", proto.name);
462 // foreach (string s; proto.aliases)
463 // {
464 // writefln("\tAlias: %s", s);
465 // }
466 assert(proto.name == "tcp");
467 assert(proto.aliases.length == 1 && proto.aliases[0] == "TCP");
473 * Class for retrieving service information.
475 * Example:
476 * ---
477 * auto serv = new Service;
478 * writeln("About service epmap:");
479 * if (serv.getServiceByName("epmap", "tcp"))
481 * writefln(" Service: %s", serv.name);
482 * writefln(" Port: %d", serv.port);
483 * writefln(" Protocol: %s", serv.protocolName);
484 * foreach (string s; serv.aliases)
485 * writefln(" Alias: %s", s);
487 * else
488 * writefln(" No service for epmap.");
489 * ---
491 class Service
493 /// These members are populated when one of the following functions are called successfully:
494 string name;
495 string[] aliases; /// ditto
496 ushort port; /// ditto
497 string protocolName; /// ditto
500 void populate(servent* serv) @system pure nothrow
502 name = to!string(serv.s_name);
503 port = ntohs(cast(ushort) serv.s_port);
504 protocolName = to!string(serv.s_proto);
506 int i;
507 for (i = 0;; i++)
509 if (!serv.s_aliases[i])
510 break;
513 if (i)
515 aliases = new string[i];
516 for (i = 0; i != aliases.length; i++)
518 aliases[i] =
519 to!string(serv.s_aliases[i]);
522 else
524 aliases = null;
529 * If a protocol name is omitted, any protocol will be matched.
530 * Returns: false on failure.
532 bool getServiceByName(scope const(char)[] name, scope const(char)[] protocolName = null) @trusted nothrow
534 servent* serv;
535 serv = getservbyname(name.tempCString(), protocolName.tempCString());
536 if (!serv)
537 return false;
538 populate(serv);
539 return true;
543 /// ditto
544 bool getServiceByPort(ushort port, scope const(char)[] protocolName = null) @trusted nothrow
546 servent* serv;
547 serv = getservbyport(port, protocolName.tempCString());
548 if (!serv)
549 return false;
550 populate(serv);
551 return true;
556 @safe unittest
558 import std.stdio : writefln;
559 softUnittest({
560 Service serv = new Service;
561 if (serv.getServiceByName("epmap", "tcp"))
563 // writefln("About service epmap:");
564 // writefln("\tService: %s", serv.name);
565 // writefln("\tPort: %d", serv.port);
566 // writefln("\tProtocol: %s", serv.protocolName);
567 // foreach (string s; serv.aliases)
568 // {
569 // writefln("\tAlias: %s", s);
570 // }
571 // For reasons unknown this is loc-srv on Wine and epmap on Windows
572 assert(serv.name == "loc-srv" || serv.name == "epmap", serv.name);
573 assert(serv.port == 135);
574 assert(serv.protocolName == "tcp");
576 else
578 writefln("No service for epmap.");
584 private mixin template socketOSExceptionCtors()
587 this(string msg, string file = __FILE__, size_t line = __LINE__,
588 Throwable next = null, int err = _lasterr())
590 super(msg, file, line, next, err);
594 this(string msg, Throwable next, string file = __FILE__,
595 size_t line = __LINE__, int err = _lasterr())
597 super(msg, next, file, line, err);
601 this(string msg, int err, string file = __FILE__, size_t line = __LINE__,
602 Throwable next = null)
604 super(msg, next, file, line, err);
610 * Class for exceptions thrown from an `InternetHost`.
612 class HostException: SocketOSException
614 mixin socketOSExceptionCtors;
618 * Class for resolving IPv4 addresses.
620 * Consider using `getAddress`, `parseAddress` and `Address` methods
621 * instead of using this class directly.
623 class InternetHost
625 /// These members are populated when one of the following functions are called successfully:
626 string name;
627 string[] aliases; /// ditto
628 uint[] addrList; /// ditto
631 void validHostent(in hostent* he)
633 if (he.h_addrtype != cast(int) AddressFamily.INET || he.h_length != 4)
634 throw new HostException("Address family mismatch");
638 void populate(hostent* he) @system pure nothrow
640 int i;
641 char* p;
643 name = to!string(he.h_name);
645 for (i = 0;; i++)
647 p = he.h_aliases[i];
648 if (!p)
649 break;
652 if (i)
654 aliases = new string[i];
655 for (i = 0; i != aliases.length; i++)
657 aliases[i] =
658 to!string(he.h_aliases[i]);
661 else
663 aliases = null;
666 for (i = 0;; i++)
668 p = he.h_addr_list[i];
669 if (!p)
670 break;
673 if (i)
675 addrList = new uint[i];
676 for (i = 0; i != addrList.length; i++)
678 addrList[i] = ntohl(*(cast(uint*) he.h_addr_list[i]));
681 else
683 addrList = null;
687 private bool getHostNoSync(string opMixin, T)(T param) @system
689 mixin(opMixin);
690 if (!he)
691 return false;
692 validHostent(he);
693 populate(he);
694 return true;
697 version (Windows)
698 alias getHost = getHostNoSync;
699 else
701 // posix systems use global state for return value, so we
702 // must synchronize across all threads
703 private bool getHost(string opMixin, T)(T param) @system
705 synchronized(this.classinfo)
706 return getHostNoSync!(opMixin, T)(param);
711 * Resolve host name.
712 * Returns: false if unable to resolve.
714 bool getHostByName(scope const(char)[] name) @trusted
716 static if (is(typeof(gethostbyname_r)))
718 return getHostNoSync!q{
719 hostent he_v;
720 hostent* he;
721 ubyte[256] buffer_v = void;
722 auto buffer = buffer_v[];
723 auto param_zTmp = param.tempCString();
724 while (true)
726 he = &he_v;
727 int errno;
728 if (gethostbyname_r(param_zTmp, he, buffer.ptr, buffer.length, &he, &errno) == ERANGE)
729 buffer.length = buffer.length * 2;
730 else
731 break;
733 }(name);
735 else
737 return getHost!q{
738 auto he = gethostbyname(param.tempCString());
739 }(name);
744 * Resolve IPv4 address number.
746 * Params:
747 * addr = The IPv4 address to resolve, in host byte order.
748 * Returns:
749 * false if unable to resolve.
751 bool getHostByAddr(uint addr) @trusted
753 return getHost!q{
754 auto x = htonl(param);
755 auto he = gethostbyaddr(&x, 4, cast(int) AddressFamily.INET);
756 }(addr);
760 * Same as previous, but addr is an IPv4 address string in the
761 * dotted-decimal form $(I a.b.c.d).
762 * Returns: false if unable to resolve.
764 bool getHostByAddr(scope const(char)[] addr) @trusted
766 return getHost!q{
767 auto x = inet_addr(param.tempCString());
768 enforce(x != INADDR_NONE,
769 new SocketParameterException("Invalid IPv4 address"));
770 auto he = gethostbyaddr(&x, 4, cast(int) AddressFamily.INET);
771 }(addr);
776 @safe unittest
778 InternetHost ih = new InternetHost;
780 ih.getHostByAddr(0x7F_00_00_01);
781 assert(ih.addrList[0] == 0x7F_00_00_01);
782 ih.getHostByAddr("127.0.0.1");
783 assert(ih.addrList[0] == 0x7F_00_00_01);
785 if (!ih.getHostByName("www.digitalmars.com"))
786 return; // don't fail if not connected to internet
788 assert(ih.addrList.length);
789 InternetAddress ia = new InternetAddress(ih.addrList[0], InternetAddress.PORT_ANY);
790 assert(ih.name == "www.digitalmars.com" || ih.name == "digitalmars.com",
791 ih.name);
793 /* The following assert randomly fails in the test suite.
794 * https://issues.dlang.org/show_bug.cgi?id=22791
795 * So just ignore it when it fails.
797 //assert(ih.getHostByAddr(ih.addrList[0]));
798 if (ih.getHostByAddr(ih.addrList[0]))
800 string getHostNameFromInt = ih.name.dup;
802 // This randomly fails in the compiler test suite
803 //assert(ih.getHostByAddr(ia.toAddrString()));
805 if (ih.getHostByAddr(ia.toAddrString()))
807 string getHostNameFromStr = ih.name.dup;
808 assert(getHostNameFromInt == getHostNameFromStr);
814 /// Holds information about a socket _address retrieved by `getAddressInfo`.
815 struct AddressInfo
817 AddressFamily family; /// Address _family
818 SocketType type; /// Socket _type
819 ProtocolType protocol; /// Protocol
820 Address address; /// Socket _address
821 string canonicalName; /// Canonical name, when `AddressInfoFlags.CANONNAME` is used.
825 * A subset of flags supported on all platforms with getaddrinfo.
826 * Specifies option flags for `getAddressInfo`.
828 enum AddressInfoFlags: int
830 /// The resulting addresses will be used in a call to `Socket.bind`.
831 PASSIVE = AI_PASSIVE,
833 /// The canonical name is returned in `canonicalName` member in the first `AddressInfo`.
834 CANONNAME = AI_CANONNAME,
837 * The `node` parameter passed to `getAddressInfo` must be a numeric string.
838 * This will suppress any potentially lengthy network host address lookups.
840 NUMERICHOST = AI_NUMERICHOST,
845 * On POSIX, getaddrinfo uses its own error codes, and thus has its own
846 * formatting function.
848 private string formatGaiError(int err) @trusted
850 version (Windows)
852 return generateSysErrorMsg(err);
854 else
856 synchronized
857 return to!string(gai_strerror(err));
862 * Provides _protocol-independent translation from host names to socket
863 * addresses. If advanced functionality is not required, consider using
864 * `getAddress` for compatibility with older systems.
866 * Returns: Array with one `AddressInfo` per socket address.
868 * Throws: `SocketOSException` on failure, or `SocketFeatureException`
869 * if this functionality is not available on the current system.
871 * Params:
872 * node = string containing host name or numeric address
873 * options = optional additional parameters, identified by type:
874 * $(UL $(LI `string` - service name or port number)
875 * $(LI `AddressInfoFlags` - option flags)
876 * $(LI `AddressFamily` - address family to filter by)
877 * $(LI `SocketType` - socket type to filter by)
878 * $(LI `ProtocolType` - protocol to filter by))
880 * Example:
881 * ---
882 * // Roundtrip DNS resolution
883 * auto results = getAddressInfo("www.digitalmars.com");
884 * assert(results[0].address.toHostNameString() ==
885 * "digitalmars.com");
887 * // Canonical name
888 * results = getAddressInfo("www.digitalmars.com",
889 * AddressInfoFlags.CANONNAME);
890 * assert(results[0].canonicalName == "digitalmars.com");
892 * // IPv6 resolution
893 * results = getAddressInfo("ipv6.google.com");
894 * assert(results[0].family == AddressFamily.INET6);
896 * // Multihomed resolution
897 * results = getAddressInfo("google.com");
898 * assert(results.length > 1);
900 * // Parsing IPv4
901 * results = getAddressInfo("127.0.0.1",
902 * AddressInfoFlags.NUMERICHOST);
903 * assert(results.length && results[0].family ==
904 * AddressFamily.INET);
906 * // Parsing IPv6
907 * results = getAddressInfo("::1",
908 * AddressInfoFlags.NUMERICHOST);
909 * assert(results.length && results[0].family ==
910 * AddressFamily.INET6);
911 * ---
913 AddressInfo[] getAddressInfo(T...)(scope const(char)[] node, scope T options)
915 const(char)[] service = null;
916 addrinfo hints;
917 hints.ai_family = AF_UNSPEC;
919 foreach (i, option; options)
921 static if (is(typeof(option) : const(char)[]))
922 service = options[i];
923 else
924 static if (is(typeof(option) == AddressInfoFlags))
925 hints.ai_flags |= option;
926 else
927 static if (is(typeof(option) == AddressFamily))
928 hints.ai_family = option;
929 else
930 static if (is(typeof(option) == SocketType))
931 hints.ai_socktype = option;
932 else
933 static if (is(typeof(option) == ProtocolType))
934 hints.ai_protocol = option;
935 else
936 static assert(0, "Unknown getAddressInfo option type: " ~ typeof(option).stringof);
939 return () @trusted { return getAddressInfoImpl(node, service, &hints); }();
942 @system unittest
944 struct Oops
946 const(char[]) breakSafety()
948 *cast(int*) 0xcafebabe = 0xdeadbeef;
949 return null;
951 alias breakSafety this;
953 assert(!__traits(compiles, () {
954 getAddressInfo("", Oops.init);
955 }), "getAddressInfo breaks @safe");
958 private AddressInfo[] getAddressInfoImpl(scope const(char)[] node, scope const(char)[] service, addrinfo* hints) @system
960 import std.array : appender;
962 if (getaddrinfoPointer && freeaddrinfoPointer)
964 addrinfo* ai_res;
966 int ret = getaddrinfoPointer(
967 node.tempCString(),
968 service.tempCString(),
969 hints, &ai_res);
970 enforce(ret == 0, new SocketOSException("getaddrinfo error", ret, &formatGaiError));
971 scope(exit) freeaddrinfoPointer(ai_res);
973 auto result = appender!(AddressInfo[])();
975 // Use const to force UnknownAddressReference to copy the sockaddr.
976 for (const(addrinfo)* ai = ai_res; ai; ai = ai.ai_next)
977 result ~= AddressInfo(
978 cast(AddressFamily) ai.ai_family,
979 cast(SocketType ) ai.ai_socktype,
980 cast(ProtocolType ) ai.ai_protocol,
981 new UnknownAddressReference(ai.ai_addr, cast(socklen_t) ai.ai_addrlen),
982 ai.ai_canonname ? to!string(ai.ai_canonname) : null);
984 assert(result.data.length > 0);
985 return result.data;
988 throw new SocketFeatureException("Address info lookup is not available " ~
989 "on this system.");
993 @safe unittest
995 softUnittest({
996 if (getaddrinfoPointer)
998 // Roundtrip DNS resolution
999 auto results = getAddressInfo("www.digitalmars.com");
1000 assert(results[0].address.toHostNameString() == "digitalmars.com");
1002 // Canonical name
1003 results = getAddressInfo("www.digitalmars.com",
1004 AddressInfoFlags.CANONNAME);
1005 assert(results[0].canonicalName == "digitalmars.com");
1007 // IPv6 resolution
1008 //results = getAddressInfo("ipv6.google.com");
1009 //assert(results[0].family == AddressFamily.INET6);
1011 // Multihomed resolution
1012 //results = getAddressInfo("google.com");
1013 //assert(results.length > 1);
1015 // Parsing IPv4
1016 results = getAddressInfo("127.0.0.1", AddressInfoFlags.NUMERICHOST);
1017 assert(results.length && results[0].family == AddressFamily.INET);
1019 // Parsing IPv6
1020 results = getAddressInfo("::1", AddressInfoFlags.NUMERICHOST);
1021 assert(results.length && results[0].family == AddressFamily.INET6);
1025 if (getaddrinfoPointer)
1027 auto results = getAddressInfo(null, "1234", AddressInfoFlags.PASSIVE,
1028 SocketType.STREAM, ProtocolType.TCP, AddressFamily.INET);
1029 assert(results.length == 1 && results[0].address.toString() == "0.0.0.0:1234");
1034 private ushort serviceToPort(scope const(char)[] service)
1036 if (service == "")
1037 return InternetAddress.PORT_ANY;
1038 else
1039 if (isNumeric(service))
1040 return to!ushort(service);
1041 else
1043 auto s = new Service();
1044 s.getServiceByName(service);
1045 return s.port;
1050 * Provides _protocol-independent translation from host names to socket
1051 * addresses. Uses `getAddressInfo` if the current system supports it,
1052 * and `InternetHost` otherwise.
1054 * Returns: Array with one `Address` instance per socket address.
1056 * Throws: `SocketOSException` on failure.
1058 * Example:
1059 * ---
1060 * writeln("Resolving www.digitalmars.com:");
1061 * try
1063 * auto addresses = getAddress("www.digitalmars.com");
1064 * foreach (address; addresses)
1065 * writefln(" IP: %s", address.toAddrString());
1067 * catch (SocketException e)
1068 * writefln(" Lookup failed: %s", e.msg);
1069 * ---
1071 Address[] getAddress(scope const(char)[] hostname, scope const(char)[] service = null)
1073 if (getaddrinfoPointer && freeaddrinfoPointer)
1075 // use getAddressInfo
1076 auto infos = getAddressInfo(hostname, service);
1077 Address[] results;
1078 results.length = infos.length;
1079 foreach (i, ref result; results)
1080 result = infos[i].address;
1081 return results;
1083 else
1084 return getAddress(hostname, serviceToPort(service));
1087 /// ditto
1088 Address[] getAddress(scope const(char)[] hostname, ushort port)
1090 if (getaddrinfoPointer && freeaddrinfoPointer)
1091 return getAddress(hostname, to!string(port));
1092 else
1094 // use getHostByName
1095 auto ih = new InternetHost;
1096 if (!ih.getHostByName(hostname))
1097 throw new AddressException(
1098 text("Unable to resolve host '", hostname, "'"));
1100 Address[] results;
1101 foreach (uint addr; ih.addrList)
1102 results ~= new InternetAddress(addr, port);
1103 return results;
1108 @safe unittest
1110 softUnittest({
1111 auto addresses = getAddress("63.105.9.61");
1112 assert(addresses.length && addresses[0].toAddrString() == "63.105.9.61");
1114 if (getaddrinfoPointer)
1116 // test via gethostbyname
1117 auto getaddrinfoPointerBackup = getaddrinfoPointer;
1118 cast() getaddrinfoPointer = null;
1119 scope(exit) cast() getaddrinfoPointer = getaddrinfoPointerBackup;
1121 addresses = getAddress("63.105.9.61");
1122 assert(addresses.length && addresses[0].toAddrString() == "63.105.9.61");
1129 * Provides _protocol-independent parsing of network addresses. Does not
1130 * attempt name resolution. Uses `getAddressInfo` with
1131 * `AddressInfoFlags.NUMERICHOST` if the current system supports it, and
1132 * `InternetAddress` otherwise.
1134 * Returns: An `Address` instance representing specified address.
1136 * Throws: `SocketException` on failure.
1138 * Example:
1139 * ---
1140 * writeln("Enter IP address:");
1141 * string ip = readln().chomp();
1142 * try
1144 * Address address = parseAddress(ip);
1145 * writefln("Looking up reverse of %s:",
1146 * address.toAddrString());
1147 * try
1149 * string reverse = address.toHostNameString();
1150 * if (reverse)
1151 * writefln(" Reverse name: %s", reverse);
1152 * else
1153 * writeln(" Reverse hostname not found.");
1155 * catch (SocketException e)
1156 * writefln(" Lookup error: %s", e.msg);
1158 * catch (SocketException e)
1160 * writefln(" %s is not a valid IP address: %s",
1161 * ip, e.msg);
1163 * ---
1165 Address parseAddress(scope const(char)[] hostaddr, scope const(char)[] service = null)
1167 if (getaddrinfoPointer && freeaddrinfoPointer)
1168 return getAddressInfo(hostaddr, service, AddressInfoFlags.NUMERICHOST)[0].address;
1169 else
1170 return parseAddress(hostaddr, serviceToPort(service));
1173 /// ditto
1174 Address parseAddress(scope const(char)[] hostaddr, ushort port)
1176 if (getaddrinfoPointer && freeaddrinfoPointer)
1177 return parseAddress(hostaddr, to!string(port));
1178 else
1180 auto in4_addr = InternetAddress.parse(hostaddr);
1181 enforce(in4_addr != InternetAddress.ADDR_NONE,
1182 new SocketParameterException("Invalid IP address"));
1183 return new InternetAddress(in4_addr, port);
1188 @safe unittest
1190 softUnittest({
1191 auto address = parseAddress("63.105.9.61");
1192 assert(address.toAddrString() == "63.105.9.61");
1194 if (getaddrinfoPointer)
1196 // test via inet_addr
1197 auto getaddrinfoPointerBackup = getaddrinfoPointer;
1198 cast() getaddrinfoPointer = null;
1199 scope(exit) cast() getaddrinfoPointer = getaddrinfoPointerBackup;
1201 address = parseAddress("63.105.9.61");
1202 assert(address.toAddrString() == "63.105.9.61");
1205 assert(collectException!SocketException(parseAddress("Invalid IP address")));
1211 * Class for exceptions thrown from an `Address`.
1213 class AddressException: SocketOSException
1215 mixin socketOSExceptionCtors;
1220 * Abstract class for representing a socket address.
1222 * Example:
1223 * ---
1224 * writeln("About www.google.com port 80:");
1225 * try
1227 * Address[] addresses = getAddress("www.google.com", 80);
1228 * writefln(" %d addresses found.", addresses.length);
1229 * foreach (int i, Address a; addresses)
1231 * writefln(" Address %d:", i+1);
1232 * writefln(" IP address: %s", a.toAddrString());
1233 * writefln(" Hostname: %s", a.toHostNameString());
1234 * writefln(" Port: %s", a.toPortString());
1235 * writefln(" Service name: %s",
1236 * a.toServiceNameString());
1239 * catch (SocketException e)
1240 * writefln(" Lookup error: %s", e.msg);
1241 * ---
1243 abstract class Address
1245 /// Returns pointer to underlying `sockaddr` structure.
1246 abstract @property sockaddr* name() pure nothrow @nogc;
1247 abstract @property const(sockaddr)* name() const pure nothrow @nogc; /// ditto
1249 /// Returns actual size of underlying `sockaddr` structure.
1250 abstract @property socklen_t nameLen() const pure nothrow @nogc;
1252 // Socket.remoteAddress, Socket.localAddress, and Socket.receiveFrom
1253 // use setNameLen to set the actual size of the address as returned by
1254 // getsockname, getpeername, and recvfrom, respectively.
1255 // The following implementation is sufficient for fixed-length addresses,
1256 // and ensures that the length is not changed.
1257 // Must be overridden for variable-length addresses.
1258 protected void setNameLen(socklen_t len)
1260 if (len != this.nameLen)
1261 throw new AddressException(
1262 format("%s expects address of length %d, not %d", typeid(this),
1263 this.nameLen, len), 0);
1266 /// Family of this address.
1267 @property AddressFamily addressFamily() const pure nothrow @nogc
1269 return cast(AddressFamily) name.sa_family;
1272 // Common code for toAddrString and toHostNameString
1273 private string toHostString(bool numeric) @trusted const
1275 // getnameinfo() is the recommended way to perform a reverse (name)
1276 // lookup on both Posix and Windows. However, it is only available
1277 // on Windows XP and above, and not included with the WinSock import
1278 // libraries shipped with DMD. Thus, we check for getnameinfo at
1279 // runtime in the shared module constructor, and use it if it's
1280 // available in the base class method. Classes for specific network
1281 // families (e.g. InternetHost) override this method and use a
1282 // deprecated, albeit commonly-available method when getnameinfo()
1283 // is not available.
1284 // http://technet.microsoft.com/en-us/library/aa450403.aspx
1285 if (getnameinfoPointer)
1287 auto buf = new char[NI_MAXHOST];
1288 auto ret = getnameinfoPointer(
1289 name, nameLen,
1290 buf.ptr, cast(uint) buf.length,
1291 null, 0,
1292 numeric ? NI_NUMERICHOST : NI_NAMEREQD);
1294 if (!numeric)
1296 if (ret == EAI_NONAME)
1297 return null;
1298 version (Windows)
1299 if (ret == WSANO_DATA)
1300 return null;
1303 enforce(ret == 0, new AddressException("Could not get " ~
1304 (numeric ? "host address" : "host name")));
1305 return assumeUnique(buf[0 .. strlen(buf.ptr)]);
1308 throw new SocketFeatureException((numeric ? "Host address" : "Host name") ~
1309 " lookup for this address family is not available on this system.");
1312 // Common code for toPortString and toServiceNameString
1313 private string toServiceString(bool numeric) @trusted const
1315 // See toHostNameString() for details about getnameinfo().
1316 if (getnameinfoPointer)
1318 auto buf = new char[NI_MAXSERV];
1319 enforce(getnameinfoPointer(
1320 name, nameLen,
1321 null, 0,
1322 buf.ptr, cast(uint) buf.length,
1323 numeric ? NI_NUMERICSERV : NI_NAMEREQD
1324 ) == 0, new AddressException("Could not get " ~
1325 (numeric ? "port number" : "service name")));
1326 return assumeUnique(buf[0 .. strlen(buf.ptr)]);
1329 throw new SocketFeatureException((numeric ? "Port number" : "Service name") ~
1330 " lookup for this address family is not available on this system.");
1334 * Attempts to retrieve the host address as a human-readable string.
1336 * Throws: `AddressException` on failure, or `SocketFeatureException`
1337 * if address retrieval for this address family is not available on the
1338 * current system.
1340 string toAddrString() const
1342 return toHostString(true);
1346 * Attempts to retrieve the host name as a fully qualified domain name.
1348 * Returns: The FQDN corresponding to this `Address`, or `null` if
1349 * the host name did not resolve.
1351 * Throws: `AddressException` on error, or `SocketFeatureException`
1352 * if host name lookup for this address family is not available on the
1353 * current system.
1355 string toHostNameString() const
1357 return toHostString(false);
1361 * Attempts to retrieve the numeric port number as a string.
1363 * Throws: `AddressException` on failure, or `SocketFeatureException`
1364 * if port number retrieval for this address family is not available on the
1365 * current system.
1367 string toPortString() const
1369 return toServiceString(true);
1373 * Attempts to retrieve the service name as a string.
1375 * Throws: `AddressException` on failure, or `SocketFeatureException`
1376 * if service name lookup for this address family is not available on the
1377 * current system.
1379 string toServiceNameString() const
1381 return toServiceString(false);
1384 /// Human readable string representing this address.
1385 override string toString() const
1389 string host = toAddrString();
1390 string port = toPortString();
1391 if (host.indexOf(':') >= 0)
1392 return "[" ~ host ~ "]:" ~ port;
1393 else
1394 return host ~ ":" ~ port;
1396 catch (SocketException)
1397 return "Unknown";
1402 * Encapsulates an unknown socket address.
1404 class UnknownAddress: Address
1406 protected:
1407 sockaddr sa;
1410 public:
1411 override @property sockaddr* name() return
1413 return &sa;
1416 override @property const(sockaddr)* name() const return
1418 return &sa;
1422 override @property socklen_t nameLen() const
1424 return cast(socklen_t) sa.sizeof;
1431 * Encapsulates a reference to an arbitrary
1432 * socket address.
1434 class UnknownAddressReference: Address
1436 protected:
1437 sockaddr* sa;
1438 socklen_t len;
1440 public:
1441 /// Constructs an `Address` with a reference to the specified `sockaddr`.
1442 this(sockaddr* sa, socklen_t len) pure nothrow @nogc
1444 this.sa = sa;
1445 this.len = len;
1448 /// Constructs an `Address` with a copy of the specified `sockaddr`.
1449 this(const(sockaddr)* sa, socklen_t len) @system pure nothrow
1451 this.sa = cast(sockaddr*) (cast(ubyte*) sa)[0 .. len].dup.ptr;
1452 this.len = len;
1455 override @property sockaddr* name()
1457 return sa;
1460 override @property const(sockaddr)* name() const
1462 return sa;
1466 override @property socklen_t nameLen() const
1468 return cast(socklen_t) len;
1474 * Encapsulates an IPv4 (Internet Protocol version 4) socket address.
1476 * Consider using `getAddress`, `parseAddress` and `Address` methods
1477 * instead of using this class directly.
1479 class InternetAddress: Address
1481 protected:
1482 sockaddr_in sin;
1485 this() pure nothrow @nogc
1490 public:
1491 override @property sockaddr* name() return
1493 return cast(sockaddr*)&sin;
1496 override @property const(sockaddr)* name() const return
1498 return cast(const(sockaddr)*)&sin;
1502 override @property socklen_t nameLen() const
1504 return cast(socklen_t) sin.sizeof;
1508 enum uint ADDR_ANY = INADDR_ANY; /// Any IPv4 host address.
1509 enum uint ADDR_NONE = INADDR_NONE; /// An invalid IPv4 host address.
1510 enum ushort PORT_ANY = 0; /// Any IPv4 port number.
1512 /// Returns the IPv4 _port number (in host byte order).
1513 @property ushort port() const pure nothrow @nogc
1515 return ntohs(sin.sin_port);
1518 /// Returns the IPv4 address number (in host byte order).
1519 @property uint addr() const pure nothrow @nogc
1521 return ntohl(sin.sin_addr.s_addr);
1525 * Construct a new `InternetAddress`.
1526 * Params:
1527 * addr = an IPv4 address string in the dotted-decimal form a.b.c.d,
1528 * or a host name which will be resolved using an `InternetHost`
1529 * object.
1530 * port = port number, may be `PORT_ANY`.
1532 this(scope const(char)[] addr, ushort port)
1534 uint uiaddr = parse(addr);
1535 if (ADDR_NONE == uiaddr)
1537 InternetHost ih = new InternetHost;
1538 if (!ih.getHostByName(addr))
1539 //throw new AddressException("Invalid internet address");
1540 throw new AddressException(
1541 text("Unable to resolve host '", addr, "'"));
1542 uiaddr = ih.addrList[0];
1544 sin.sin_family = AddressFamily.INET;
1545 sin.sin_addr.s_addr = htonl(uiaddr);
1546 sin.sin_port = htons(port);
1550 * Construct a new `InternetAddress`.
1551 * Params:
1552 * addr = (optional) an IPv4 address in host byte order, may be `ADDR_ANY`.
1553 * port = port number, may be `PORT_ANY`.
1555 this(uint addr, ushort port) pure nothrow @nogc
1557 sin.sin_family = AddressFamily.INET;
1558 sin.sin_addr.s_addr = htonl(addr);
1559 sin.sin_port = htons(port);
1562 /// ditto
1563 this(ushort port) pure nothrow @nogc
1565 sin.sin_family = AddressFamily.INET;
1566 sin.sin_addr.s_addr = ADDR_ANY;
1567 sin.sin_port = htons(port);
1571 * Construct a new `InternetAddress`.
1572 * Params:
1573 * addr = A sockaddr_in as obtained from lower-level API calls such as getifaddrs.
1575 this(sockaddr_in addr) pure nothrow @nogc
1577 assert(addr.sin_family == AddressFamily.INET, "Socket address is not of INET family.");
1578 sin = addr;
1581 /// Human readable string representing the IPv4 address in dotted-decimal form.
1582 override string toAddrString() @trusted const
1584 return to!string(inet_ntoa(sin.sin_addr));
1587 /// Human readable string representing the IPv4 port.
1588 override string toPortString() const
1590 return std.conv.to!string(port);
1594 * Attempts to retrieve the host name as a fully qualified domain name.
1596 * Returns: The FQDN corresponding to this `InternetAddress`, or
1597 * `null` if the host name did not resolve.
1599 * Throws: `AddressException` on error.
1601 override string toHostNameString() const
1603 // getnameinfo() is the recommended way to perform a reverse (name)
1604 // lookup on both Posix and Windows. However, it is only available
1605 // on Windows XP and above, and not included with the WinSock import
1606 // libraries shipped with DMD. Thus, we check for getnameinfo at
1607 // runtime in the shared module constructor, and fall back to the
1608 // deprecated getHostByAddr() if it could not be found. See also:
1609 // http://technet.microsoft.com/en-us/library/aa450403.aspx
1611 if (getnameinfoPointer)
1612 return super.toHostNameString();
1613 else
1615 auto host = new InternetHost();
1616 if (!host.getHostByAddr(ntohl(sin.sin_addr.s_addr)))
1617 return null;
1618 return host.name;
1623 * Provides support for comparing equality with another
1624 * InternetAddress of the same type.
1625 * Returns: true if the InternetAddresses share the same address and
1626 * port number.
1628 override bool opEquals(Object o) const
1630 auto other = cast(InternetAddress) o;
1631 return other && this.sin.sin_addr.s_addr == other.sin.sin_addr.s_addr &&
1632 this.sin.sin_port == other.sin.sin_port;
1636 @system unittest
1638 auto addr1 = new InternetAddress("127.0.0.1", 80);
1639 auto addr2 = new InternetAddress("127.0.0.2", 80);
1641 assert(addr1 == addr1);
1642 assert(addr1 != addr2);
1646 * Parse an IPv4 address string in the dotted-decimal form $(I a.b.c.d)
1647 * and return the number.
1648 * Returns: If the string is not a legitimate IPv4 address,
1649 * `ADDR_NONE` is returned.
1651 static uint parse(scope const(char)[] addr) @trusted nothrow
1653 return ntohl(inet_addr(addr.tempCString()));
1657 * Convert an IPv4 address number in host byte order to a human readable
1658 * string representing the IPv4 address in dotted-decimal form.
1660 static string addrToString(uint addr) @trusted nothrow
1662 in_addr sin_addr;
1663 sin_addr.s_addr = htonl(addr);
1664 return to!string(inet_ntoa(sin_addr));
1669 @safe unittest
1671 softUnittest({
1672 const InternetAddress ia = new InternetAddress("63.105.9.61", 80);
1673 assert(ia.toString() == "63.105.9.61:80");
1676 softUnittest({
1677 // test construction from a sockaddr_in
1678 sockaddr_in sin;
1680 sin.sin_addr.s_addr = htonl(0x7F_00_00_01); // 127.0.0.1
1681 sin.sin_family = AddressFamily.INET;
1682 sin.sin_port = htons(80);
1684 const InternetAddress ia = new InternetAddress(sin);
1685 assert(ia.toString() == "127.0.0.1:80");
1688 softUnittest({
1689 // test reverse lookup
1690 auto ih = new InternetHost;
1691 if (ih.getHostByName("digitalmars.com"))
1693 const ia = new InternetAddress(ih.addrList[0], 80);
1694 assert(ia.toHostNameString() == "digitalmars.com");
1696 if (getnameinfoPointer)
1698 // test reverse lookup, via gethostbyaddr
1699 auto getnameinfoPointerBackup = getnameinfoPointer;
1700 cast() getnameinfoPointer = null;
1701 scope(exit) cast() getnameinfoPointer = getnameinfoPointerBackup;
1703 assert(ia.toHostNameString() == "digitalmars.com");
1708 if (runSlowTests)
1709 softUnittest({
1710 // test failing reverse lookup
1711 const InternetAddress ia = new InternetAddress("255.255.255.255", 80);
1712 assert(ia.toHostNameString() is null);
1714 if (getnameinfoPointer)
1716 // test failing reverse lookup, via gethostbyaddr
1717 auto getnameinfoPointerBackup = getnameinfoPointer;
1718 cast() getnameinfoPointer = null;
1719 scope(exit) cast() getnameinfoPointer = getnameinfoPointerBackup;
1721 assert(ia.toHostNameString() is null);
1728 * Encapsulates an IPv6 (Internet Protocol version 6) socket address.
1730 * Consider using `getAddress`, `parseAddress` and `Address` methods
1731 * instead of using this class directly.
1733 class Internet6Address: Address
1735 protected:
1736 sockaddr_in6 sin6;
1739 this() pure nothrow @nogc
1744 public:
1745 override @property sockaddr* name() return
1747 return cast(sockaddr*)&sin6;
1750 override @property const(sockaddr)* name() const return
1752 return cast(const(sockaddr)*)&sin6;
1756 override @property socklen_t nameLen() const
1758 return cast(socklen_t) sin6.sizeof;
1762 /// Any IPv6 host address.
1763 static @property ref const(ubyte)[16] ADDR_ANY() pure nothrow @nogc
1765 static if (is(typeof(IN6ADDR_ANY)))
1767 version (Windows)
1769 static immutable addr = IN6ADDR_ANY.s6_addr;
1770 return addr;
1772 else
1773 return IN6ADDR_ANY.s6_addr;
1775 else static if (is(typeof(in6addr_any)))
1777 return in6addr_any.s6_addr;
1779 else
1780 static assert(0);
1783 /// Any IPv6 port number.
1784 enum ushort PORT_ANY = 0;
1786 /// Returns the IPv6 port number.
1787 @property ushort port() const pure nothrow @nogc
1789 return ntohs(sin6.sin6_port);
1792 /// Returns the IPv6 address.
1793 @property ubyte[16] addr() const pure nothrow @nogc
1795 return sin6.sin6_addr.s6_addr;
1799 * Construct a new `Internet6Address`.
1800 * Params:
1801 * addr = an IPv6 host address string in the form described in RFC 2373,
1802 * or a host name which will be resolved using `getAddressInfo`.
1803 * service = (optional) service name.
1805 this(scope const(char)[] addr, scope const(char)[] service = null) @trusted
1807 auto results = getAddressInfo(addr, service, AddressFamily.INET6);
1808 assert(results.length && results[0].family == AddressFamily.INET6);
1809 sin6 = *cast(sockaddr_in6*) results[0].address.name;
1813 * Construct a new `Internet6Address`.
1814 * Params:
1815 * addr = an IPv6 host address string in the form described in RFC 2373,
1816 * or a host name which will be resolved using `getAddressInfo`.
1817 * port = port number, may be `PORT_ANY`.
1819 this(scope const(char)[] addr, ushort port)
1821 if (port == PORT_ANY)
1822 this(addr);
1823 else
1824 this(addr, to!string(port));
1828 * Construct a new `Internet6Address`.
1829 * Params:
1830 * addr = (optional) an IPv6 host address in host byte order, or
1831 * `ADDR_ANY`.
1832 * port = port number, may be `PORT_ANY`.
1834 this(ubyte[16] addr, ushort port) pure nothrow @nogc
1836 sin6.sin6_family = AddressFamily.INET6;
1837 sin6.sin6_addr.s6_addr = addr;
1838 sin6.sin6_port = htons(port);
1841 /// ditto
1842 this(ushort port) pure nothrow @nogc
1844 sin6.sin6_family = AddressFamily.INET6;
1845 sin6.sin6_addr.s6_addr = ADDR_ANY;
1846 sin6.sin6_port = htons(port);
1850 * Construct a new `Internet6Address`.
1851 * Params:
1852 * addr = A sockaddr_in6 as obtained from lower-level API calls such as getifaddrs.
1854 this(sockaddr_in6 addr) pure nothrow @nogc
1856 assert(addr.sin6_family == AddressFamily.INET6);
1857 sin6 = addr;
1861 * Parse an IPv6 host address string as described in RFC 2373, and return the
1862 * address.
1863 * Throws: `SocketException` on error.
1865 static ubyte[16] parse(scope const(char)[] addr) @trusted
1867 // Although we could use inet_pton here, it's only available on Windows
1868 // versions starting with Vista, so use getAddressInfo with NUMERICHOST
1869 // instead.
1870 auto results = getAddressInfo(addr, AddressInfoFlags.NUMERICHOST);
1871 if (results.length && results[0].family == AddressFamily.INET6)
1872 return (cast(sockaddr_in6*) results[0].address.name).sin6_addr.s6_addr;
1873 throw new AddressException("Not an IPv6 address", 0);
1878 @safe unittest
1880 softUnittest({
1881 const Internet6Address ia = new Internet6Address("::1", 80);
1882 assert(ia.toString() == "[::1]:80");
1885 softUnittest({
1886 // test construction from a sockaddr_in6
1887 sockaddr_in6 sin;
1889 sin.sin6_addr.s6_addr = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]; // [::1]
1890 sin.sin6_family = AddressFamily.INET6;
1891 sin.sin6_port = htons(80);
1893 const Internet6Address ia = new Internet6Address(sin);
1894 assert(ia.toString() == "[::1]:80");
1899 version (StdDdoc)
1901 static if (!is(sockaddr_un))
1903 // This exists only to allow the constructor taking
1904 // a sockaddr_un to be compilable for documentation
1905 // on platforms that don't supply a sockaddr_un.
1906 struct sockaddr_un
1912 * Encapsulates an address for a Unix domain socket (`AF_UNIX`),
1913 * i.e. a socket bound to a path name in the file system.
1914 * Available only on supported systems.
1916 * Linux also supports an abstract address namespace, in which addresses
1917 * are independent of the file system. A socket address is abstract
1918 * iff `path` starts with a _null byte (`'\0'`). Null bytes in other
1919 * positions of an abstract address are allowed and have no special
1920 * meaning.
1922 * Example:
1923 * ---
1924 * auto addr = new UnixAddress("/var/run/dbus/system_bus_socket");
1925 * auto abstractAddr = new UnixAddress("\0/tmp/dbus-OtHLWmCLPR");
1926 * ---
1928 * See_Also: $(HTTP http://man7.org/linux/man-pages/man7/unix.7.html, UNIX(7))
1930 class UnixAddress: Address
1932 private this() pure nothrow @nogc {}
1934 /// Construct a new `UnixAddress` from the specified path.
1935 this(scope const(char)[] path) { }
1938 * Construct a new `UnixAddress`.
1939 * Params:
1940 * addr = A sockaddr_un as obtained from lower-level API calls.
1942 this(sockaddr_un addr) pure nothrow @nogc { }
1944 /// Get the underlying _path.
1945 @property string path() const { return null; }
1947 /// ditto
1948 override string toString() const { return null; }
1950 override @property sockaddr* name() { return null; }
1951 override @property const(sockaddr)* name() const { return null; }
1952 override @property socklen_t nameLen() const { return 0; }
1955 else
1956 static if (is(sockaddr_un))
1958 class UnixAddress: Address
1960 protected:
1961 socklen_t _nameLen;
1963 struct
1965 align (1):
1966 sockaddr_un sun;
1967 char unused = '\0'; // placeholder for a terminating '\0'
1970 this() pure nothrow @nogc
1972 sun.sun_family = AddressFamily.UNIX;
1973 sun.sun_path = '?';
1974 _nameLen = sun.sizeof;
1977 override void setNameLen(socklen_t len) @trusted
1979 if (len > sun.sizeof)
1980 throw new SocketParameterException("Not enough socket address storage");
1981 _nameLen = len;
1984 public:
1985 override @property sockaddr* name() return
1987 return cast(sockaddr*)&sun;
1990 override @property const(sockaddr)* name() const return
1992 return cast(const(sockaddr)*)&sun;
1995 override @property socklen_t nameLen() @trusted const
1997 return _nameLen;
2000 this(scope const(char)[] path) @trusted pure
2002 enforce(path.length <= sun.sun_path.sizeof, new SocketParameterException("Path too long"));
2003 sun.sun_family = AddressFamily.UNIX;
2004 sun.sun_path.ptr[0 .. path.length] = (cast(byte[]) path)[];
2005 _nameLen = cast(socklen_t)
2007 auto len = sockaddr_un.init.sun_path.offsetof + path.length;
2008 // Pathname socket address must be terminated with '\0'
2009 // which must be included in the address length.
2010 if (sun.sun_path.ptr[0])
2012 sun.sun_path.ptr[path.length] = 0;
2013 ++len;
2015 return len;
2016 }();
2019 this(sockaddr_un addr) pure nothrow @nogc
2021 assert(addr.sun_family == AddressFamily.UNIX);
2022 sun = addr;
2025 @property string path() @trusted const pure
2027 auto len = _nameLen - sockaddr_un.init.sun_path.offsetof;
2028 if (len == 0)
2029 return null; // An empty path may be returned from getpeername
2030 // For pathname socket address we need to strip off the terminating '\0'
2031 if (sun.sun_path.ptr[0])
2032 --len;
2033 return (cast(const(char)*) sun.sun_path.ptr)[0 .. len].idup;
2036 override string toString() const pure
2038 return path;
2042 @safe unittest
2044 import core.stdc.stdio : remove;
2046 version (iOSDerived)
2048 // Slightly different version of `std.file.deleteme` to reduce the path
2049 // length on iOS derived platforms. Due to the sandbox, the length
2050 // of paths can quickly become too long.
2051 static string deleteme()
2053 import std.conv : text;
2054 import std.process : thisProcessID;
2055 import std.file : tempDir;
2057 return text(tempDir, thisProcessID);
2061 else
2062 import std.file : deleteme;
2064 immutable ubyte[] data = [1, 2, 3, 4];
2065 Socket[2] pair;
2067 const basePath = deleteme;
2068 auto names = [ basePath ~ "-socket" ];
2069 version (linux)
2070 names ~= "\0" ~ basePath ~ "-abstract\0unix\0socket";
2072 foreach (name; names)
2074 auto address = new UnixAddress(name);
2076 auto listener = new Socket(AddressFamily.UNIX, SocketType.STREAM);
2077 scope(exit) listener.close();
2078 listener.bind(address);
2079 scope(exit) () @trusted { if (name[0]) remove(name.tempCString()); } ();
2080 assert(listener.localAddress.toString == name);
2082 listener.listen(1);
2084 pair[0] = new Socket(AddressFamily.UNIX, SocketType.STREAM);
2085 scope(exit) listener.close();
2087 pair[0].connect(address);
2088 scope(exit) pair[0].close();
2090 pair[1] = listener.accept();
2091 scope(exit) pair[1].close();
2093 pair[0].send(data);
2095 auto buf = new ubyte[data.length];
2096 pair[1].receive(buf);
2097 assert(buf == data);
2099 // getpeername is free to return an empty name for a unix
2100 // domain socket pair or unbound socket. Let's confirm it
2101 // returns successfully and doesn't throw anything.
2102 // See https://issues.dlang.org/show_bug.cgi?id=20544
2103 assertNotThrown(pair[1].remoteAddress().toString());
2110 * Exception thrown by `Socket.accept`.
2112 class SocketAcceptException: SocketOSException
2114 mixin socketOSExceptionCtors;
2117 /// How a socket is shutdown:
2118 enum SocketShutdown: int
2120 RECEIVE = SD_RECEIVE, /// socket receives are disallowed
2121 SEND = SD_SEND, /// socket sends are disallowed
2122 BOTH = SD_BOTH, /// both RECEIVE and SEND
2126 /// Socket flags that may be OR'ed together:
2127 enum SocketFlags: int
2129 NONE = 0, /// no flags specified
2131 OOB = MSG_OOB, /// out-of-band stream data
2132 PEEK = MSG_PEEK, /// peek at incoming data without removing it from the queue, only for receiving
2133 DONTROUTE = MSG_DONTROUTE, /// data should not be subject to routing; this flag may be ignored. Only for sending
2137 /// Duration timeout value.
2138 struct TimeVal
2140 _ctimeval ctimeval;
2141 alias tv_sec_t = typeof(ctimeval.tv_sec);
2142 alias tv_usec_t = typeof(ctimeval.tv_usec);
2144 /// Number of _seconds.
2145 pure nothrow @nogc @property
2146 ref inout(tv_sec_t) seconds() inout return
2148 return ctimeval.tv_sec;
2151 /// Number of additional _microseconds.
2152 pure nothrow @nogc @property
2153 ref inout(tv_usec_t) microseconds() inout return
2155 return ctimeval.tv_usec;
2161 * A collection of sockets for use with `Socket.select`.
2163 * `SocketSet` wraps the platform `fd_set` type. However, unlike
2164 * `fd_set`, `SocketSet` is not statically limited to `FD_SETSIZE`
2165 * or any other limit, and grows as needed.
2167 class SocketSet
2169 private:
2170 version (Windows)
2172 // On Windows, fd_set is an array of socket handles,
2173 // following a word containing the fd_set instance size.
2174 // We use one dynamic array for everything, and use its first
2175 // element(s) for the count.
2177 alias fd_set_count_type = typeof(fd_set.init.fd_count);
2178 alias fd_set_type = typeof(fd_set.init.fd_array[0]);
2179 static assert(fd_set_type.sizeof == socket_t.sizeof);
2181 // Number of fd_set_type elements at the start of our array that are
2182 // used for the socket count and alignment
2184 enum FD_SET_OFFSET = fd_set.fd_array.offsetof / fd_set_type.sizeof;
2185 static assert(FD_SET_OFFSET);
2186 static assert(fd_set.fd_count.offsetof % fd_set_type.sizeof == 0);
2188 fd_set_type[] set;
2190 void resize(size_t size) pure nothrow
2192 set.length = FD_SET_OFFSET + size;
2195 ref inout(fd_set_count_type) count() @trusted @property inout pure nothrow @nogc
2197 assert(set.length);
2198 return *cast(inout(fd_set_count_type)*)set.ptr;
2201 size_t capacity() @property const pure nothrow @nogc
2203 return set.length - FD_SET_OFFSET;
2206 inout(socket_t)[] fds() @trusted inout @property pure nothrow @nogc
2208 return cast(inout(socket_t)[])set[FD_SET_OFFSET .. FD_SET_OFFSET+count];
2211 else
2212 version (Posix)
2214 // On Posix, fd_set is a bit array. We assume that the fd_set
2215 // type (declared in core.sys.posix.sys.select) is a structure
2216 // containing a single field, a static array.
2218 static assert(fd_set.tupleof.length == 1);
2220 // This is the type used in the fd_set array.
2221 // Using the type of the correct size is important for big-endian
2222 // architectures.
2224 alias fd_set_type = typeof(fd_set.init.tupleof[0][0]);
2226 // Number of file descriptors represented by one fd_set_type
2228 enum FD_NFDBITS = 8 * fd_set_type.sizeof;
2230 static fd_set_type mask(uint n) pure nothrow @nogc
2232 return (cast(fd_set_type) 1) << (n % FD_NFDBITS);
2235 // Array size to fit that many sockets
2237 static size_t lengthFor(size_t size) pure nothrow @nogc
2239 return (size + (FD_NFDBITS-1)) / FD_NFDBITS;
2242 fd_set_type[] set;
2244 void resize(size_t size) pure nothrow
2246 set.length = lengthFor(size);
2249 // Make sure we can fit that many sockets
2251 void setMinCapacity(size_t size) pure nothrow
2253 auto length = lengthFor(size);
2254 if (set.length < length)
2255 set.length = length;
2258 size_t capacity() @property const pure nothrow @nogc
2260 return set.length * FD_NFDBITS;
2263 int maxfd;
2265 else
2266 static assert(false, "Unknown platform");
2268 public:
2271 * Create a SocketSet with a specific initial capacity (defaults to
2272 * `FD_SETSIZE`, the system's default capacity).
2274 this(size_t size = FD_SETSIZE) pure nothrow
2276 resize(size);
2277 reset();
2280 /// Reset the `SocketSet` so that there are 0 `Socket`s in the collection.
2281 void reset() pure nothrow @nogc
2283 version (Windows)
2284 count = 0;
2285 else
2287 set[] = 0;
2288 maxfd = -1;
2293 void add(socket_t s) @trusted pure nothrow
2295 version (Windows)
2297 if (count == capacity)
2299 set.length *= 2;
2300 set.length = set.capacity;
2302 ++count;
2303 fds[$-1] = s;
2305 else
2307 auto index = s / FD_NFDBITS;
2308 auto length = set.length;
2309 if (index >= length)
2311 while (index >= length)
2312 length *= 2;
2313 set.length = length;
2314 set.length = set.capacity;
2316 set[index] |= mask(s);
2317 if (maxfd < s)
2318 maxfd = s;
2323 * Add a `Socket` to the collection.
2324 * The socket must not already be in the collection.
2326 void add(Socket s) pure nothrow
2328 add(s.sock);
2331 void remove(socket_t s) pure nothrow
2333 version (Windows)
2335 import std.algorithm.searching : countUntil;
2336 auto fds = fds;
2337 auto p = fds.countUntil(s);
2338 if (p >= 0)
2339 fds[p] = fds[--count];
2341 else
2343 auto index = s / FD_NFDBITS;
2344 if (index >= set.length)
2345 return;
2346 set[index] &= ~mask(s);
2347 // note: adjusting maxfd would require scanning the set, not worth it
2353 * Remove this `Socket` from the collection.
2354 * Does nothing if the socket is not in the collection already.
2356 void remove(Socket s) pure nothrow
2358 remove(s.sock);
2361 int isSet(socket_t s) const pure nothrow @nogc
2363 version (Windows)
2365 import std.algorithm.searching : canFind;
2366 return fds.canFind(s) ? 1 : 0;
2368 else
2370 if (s > maxfd)
2371 return 0;
2372 auto index = s / FD_NFDBITS;
2373 return (set[index] & mask(s)) ? 1 : 0;
2378 /// Return nonzero if this `Socket` is in the collection.
2379 int isSet(Socket s) const pure nothrow @nogc
2381 return isSet(s.sock);
2386 * Returns:
2387 * The current capacity of this `SocketSet`. The exact
2388 * meaning of the return value varies from platform to platform.
2390 * Note:
2391 * Since D 2.065, this value does not indicate a
2392 * restriction, and `SocketSet` will grow its capacity as
2393 * needed automatically.
2395 @property uint max() const pure nothrow @nogc
2397 return cast(uint) capacity;
2401 fd_set* toFd_set() @trusted pure nothrow @nogc
2403 return cast(fd_set*) set.ptr;
2407 int selectn() const pure nothrow @nogc
2409 version (Windows)
2411 return count;
2413 else version (Posix)
2415 return maxfd + 1;
2420 @safe unittest
2422 auto fds = cast(socket_t[])
2423 [cast(socket_t) 1, 2, 0, 1024, 17, 42, 1234, 77, 77+32, 77+64];
2424 auto set = new SocketSet();
2425 foreach (fd; fds) assert(!set.isSet(fd));
2426 foreach (fd; fds) set.add(fd);
2427 foreach (fd; fds) assert(set.isSet(fd));
2429 // Make sure SocketSet reimplements fd_set correctly
2430 auto fdset = set.toFd_set();
2431 foreach (fd; fds[0]..cast(socket_t)(fds[$-1]+1))
2432 assert(cast(bool) set.isSet(fd) == cast(bool)(() @trusted => FD_ISSET(fd, fdset))());
2434 foreach (fd; fds)
2436 assert(set.isSet(fd));
2437 set.remove(fd);
2438 assert(!set.isSet(fd));
2442 @safe unittest
2444 version (iOSDerived)
2446 enum PAIRS = 256;
2447 enum LIMIT = 1024;
2449 else
2451 enum PAIRS = 768;
2452 enum LIMIT = 2048;
2455 softUnittest({
2456 version (Posix)
2457 () @trusted
2459 static assert(LIMIT > PAIRS*2);
2460 import core.sys.posix.sys.resource;
2461 rlimit fileLimit;
2462 getrlimit(RLIMIT_NOFILE, &fileLimit);
2463 assert(fileLimit.rlim_max > LIMIT, "Open file hard limit too low");
2464 fileLimit.rlim_cur = LIMIT;
2465 setrlimit(RLIMIT_NOFILE, &fileLimit);
2466 } ();
2468 Socket[2][PAIRS] pairs;
2469 foreach (ref pair; pairs)
2470 pair = socketPair();
2471 scope(exit)
2473 foreach (pair; pairs)
2475 pair[0].close();
2476 pair[1].close();
2480 import std.random;
2481 auto rng = Xorshift(42);
2482 pairs[].randomShuffle(rng);
2484 auto readSet = new SocketSet();
2485 auto writeSet = new SocketSet();
2486 auto errorSet = new SocketSet();
2488 foreach (testPair; pairs)
2490 void fillSets()
2492 readSet.reset();
2493 writeSet.reset();
2494 errorSet.reset();
2495 foreach (ref pair; pairs)
2496 foreach (s; pair[])
2498 readSet.add(s);
2499 writeSet.add(s);
2500 errorSet.add(s);
2504 fillSets();
2505 auto n = Socket.select(readSet, writeSet, errorSet);
2506 assert(n == PAIRS*2); // All in writeSet
2507 assert(writeSet.isSet(testPair[0]));
2508 assert(writeSet.isSet(testPair[1]));
2509 assert(!readSet.isSet(testPair[0]));
2510 assert(!readSet.isSet(testPair[1]));
2511 assert(!errorSet.isSet(testPair[0]));
2512 assert(!errorSet.isSet(testPair[1]));
2514 ubyte[1] b;
2515 // Socket.send can't be marked with `scope`
2516 // -> @safe DIP1000 code can't use it - see https://github.com/dlang/phobos/pull/6204
2517 () @trusted {
2518 testPair[0].send(b[]);
2519 }();
2520 fillSets();
2521 n = Socket.select(readSet, null, null);
2522 assert(n == 1); // testPair[1]
2523 assert(readSet.isSet(testPair[1]));
2524 assert(!readSet.isSet(testPair[0]));
2525 // Socket.receive can't be marked with `scope`
2526 // -> @safe DIP1000 code can't use it - see https://github.com/dlang/phobos/pull/6204
2527 () @trusted {
2528 testPair[1].receive(b[]);
2529 }();
2534 // https://issues.dlang.org/show_bug.cgi?id=14012
2535 // https://issues.dlang.org/show_bug.cgi?id=14013
2536 @safe unittest
2538 auto set = new SocketSet(1);
2539 assert(set.max >= 0);
2541 enum LIMIT = 4096;
2542 foreach (n; 0 .. LIMIT)
2543 set.add(cast(socket_t) n);
2544 assert(set.max >= LIMIT);
2547 /// The level at which a socket option is defined:
2548 enum SocketOptionLevel: int
2550 SOCKET = SOL_SOCKET, /// Socket level
2551 IP = ProtocolType.IP, /// Internet Protocol version 4 level
2552 ICMP = ProtocolType.ICMP, /// Internet Control Message Protocol level
2553 IGMP = ProtocolType.IGMP, /// Internet Group Management Protocol level
2554 GGP = ProtocolType.GGP, /// Gateway to Gateway Protocol level
2555 TCP = ProtocolType.TCP, /// Transmission Control Protocol level
2556 PUP = ProtocolType.PUP, /// PARC Universal Packet Protocol level
2557 UDP = ProtocolType.UDP, /// User Datagram Protocol level
2558 IDP = ProtocolType.IDP, /// Xerox NS protocol level
2559 RAW = ProtocolType.RAW, /// Raw IP packet level
2560 IPV6 = ProtocolType.IPV6, /// Internet Protocol version 6 level
2563 /// _Linger information for use with SocketOption.LINGER.
2564 struct Linger
2566 _clinger clinger;
2568 private alias l_onoff_t = typeof(_clinger.init.l_onoff );
2569 private alias l_linger_t = typeof(_clinger.init.l_linger);
2571 /// Nonzero for _on.
2572 pure nothrow @nogc @property
2573 ref inout(l_onoff_t) on() inout return
2575 return clinger.l_onoff;
2578 /// Linger _time.
2579 pure nothrow @nogc @property
2580 ref inout(l_linger_t) time() inout return
2582 return clinger.l_linger;
2586 /// Specifies a socket option:
2587 enum SocketOption: int
2589 DEBUG = SO_DEBUG, /// Record debugging information
2590 BROADCAST = SO_BROADCAST, /// Allow transmission of broadcast messages
2591 REUSEADDR = SO_REUSEADDR, /// Allow local reuse of address
2592 LINGER = SO_LINGER, /// Linger on close if unsent data is present
2593 OOBINLINE = SO_OOBINLINE, /// Receive out-of-band data in band
2594 SNDBUF = SO_SNDBUF, /// Send buffer size
2595 RCVBUF = SO_RCVBUF, /// Receive buffer size
2596 DONTROUTE = SO_DONTROUTE, /// Do not route
2597 SNDTIMEO = SO_SNDTIMEO, /// Send timeout
2598 RCVTIMEO = SO_RCVTIMEO, /// Receive timeout
2599 ERROR = SO_ERROR, /// Retrieve and clear error status
2600 KEEPALIVE = SO_KEEPALIVE, /// Enable keep-alive packets
2601 ACCEPTCONN = SO_ACCEPTCONN, /// Listen
2602 RCVLOWAT = SO_RCVLOWAT, /// Minimum number of input bytes to process
2603 SNDLOWAT = SO_SNDLOWAT, /// Minimum number of output bytes to process
2604 TYPE = SO_TYPE, /// Socket type
2606 // SocketOptionLevel.TCP:
2607 TCP_NODELAY = .TCP_NODELAY, /// Disable the Nagle algorithm for send coalescing
2609 // SocketOptionLevel.IPV6:
2610 IPV6_UNICAST_HOPS = .IPV6_UNICAST_HOPS, /// IP unicast hop limit
2611 IPV6_MULTICAST_IF = .IPV6_MULTICAST_IF, /// IP multicast interface
2612 IPV6_MULTICAST_LOOP = .IPV6_MULTICAST_LOOP, /// IP multicast loopback
2613 IPV6_MULTICAST_HOPS = .IPV6_MULTICAST_HOPS, /// IP multicast hops
2614 IPV6_JOIN_GROUP = .IPV6_JOIN_GROUP, /// Add an IP group membership
2615 IPV6_LEAVE_GROUP = .IPV6_LEAVE_GROUP, /// Drop an IP group membership
2616 IPV6_V6ONLY = .IPV6_V6ONLY, /// Treat wildcard bind as AF_INET6-only
2621 * Class that creates a network communication endpoint using
2622 * the Berkeley sockets interface.
2624 class Socket
2626 private:
2627 socket_t sock;
2628 AddressFamily _family;
2630 version (Windows)
2631 bool _blocking = true; /// Property to get or set whether the socket is blocking or nonblocking.
2633 // The WinSock timeouts seem to be effectively skewed by a constant
2634 // offset of about half a second (value in milliseconds). This has
2635 // been confirmed on updated (as of Jun 2011) Windows XP, Windows 7
2636 // and Windows Server 2008 R2 boxes. The unittest below tests this
2637 // behavior.
2638 enum WINSOCK_TIMEOUT_SKEW = 500;
2640 @safe unittest
2642 if (runSlowTests)
2643 softUnittest({
2644 import std.datetime.stopwatch : StopWatch;
2645 import std.typecons : Yes;
2647 enum msecs = 1000;
2648 auto pair = socketPair();
2649 auto testSock = pair[0];
2650 testSock.setOption(SocketOptionLevel.SOCKET,
2651 SocketOption.RCVTIMEO, dur!"msecs"(msecs));
2653 auto sw = StopWatch(Yes.autoStart);
2654 ubyte[1] buf;
2655 testSock.receive(buf);
2656 sw.stop();
2658 Duration readBack = void;
2659 testSock.getOption(SocketOptionLevel.SOCKET, SocketOption.RCVTIMEO, readBack);
2661 assert(readBack.total!"msecs" == msecs);
2662 assert(sw.peek().total!"msecs" > msecs - 100 && sw.peek().total!"msecs" < msecs + 100);
2666 void setSock(socket_t handle)
2668 assert(handle != socket_t.init);
2669 sock = handle;
2671 // Set the option to disable SIGPIPE on send() if the platform
2672 // has it (e.g. on OS X).
2673 static if (is(typeof(SO_NOSIGPIPE)))
2675 setOption(SocketOptionLevel.SOCKET, cast(SocketOption) SO_NOSIGPIPE, true);
2680 // For use with accepting().
2681 protected this() pure nothrow @nogc
2686 public:
2689 * Create a blocking socket. If a single protocol type exists to support
2690 * this socket type within the address family, the `ProtocolType` may be
2691 * omitted.
2693 this(AddressFamily af, SocketType type, ProtocolType protocol) @trusted
2695 _family = af;
2696 auto handle = cast(socket_t) socket(af, type, protocol);
2697 if (handle == socket_t.init)
2698 throw new SocketOSException("Unable to create socket");
2699 setSock(handle);
2702 /// ditto
2703 this(AddressFamily af, SocketType type)
2705 /* A single protocol exists to support this socket type within the
2706 * protocol family, so the ProtocolType is assumed.
2708 this(af, type, cast(ProtocolType) 0); // Pseudo protocol number.
2712 /// ditto
2713 this(AddressFamily af, SocketType type, scope const(char)[] protocolName) @trusted
2715 protoent* proto;
2716 proto = getprotobyname(protocolName.tempCString());
2717 if (!proto)
2718 throw new SocketOSException("Unable to find the protocol");
2719 this(af, type, cast(ProtocolType) proto.p_proto);
2724 * Create a blocking socket using the parameters from the specified
2725 * `AddressInfo` structure.
2727 this(const scope AddressInfo info)
2729 this(info.family, info.type, info.protocol);
2732 /// Use an existing socket handle.
2733 this(socket_t sock, AddressFamily af) pure nothrow @nogc
2735 assert(sock != socket_t.init);
2736 this.sock = sock;
2737 this._family = af;
2741 ~this() nothrow @nogc
2743 close();
2747 /// Get underlying socket handle.
2748 @property socket_t handle() const pure nothrow @nogc
2750 return sock;
2754 * Releases the underlying socket handle from the Socket object. Once it
2755 * is released, you cannot use the Socket object's methods anymore. This
2756 * also means the Socket destructor will no longer close the socket - it
2757 * becomes your responsibility.
2759 * To get the handle without releasing it, use the `handle` property.
2761 @property socket_t release() pure nothrow @nogc
2763 auto h = sock;
2764 this.sock = socket_t.init;
2765 return h;
2769 * Get/set socket's blocking flag.
2771 * When a socket is blocking, calls to receive(), accept(), and send()
2772 * will block and wait for data/action.
2773 * A non-blocking socket will immediately return instead of blocking.
2775 @property bool blocking() @trusted const nothrow @nogc
2777 version (Windows)
2779 return _blocking;
2781 else version (Posix)
2783 return !(fcntl(handle, F_GETFL, 0) & O_NONBLOCK);
2787 /// ditto
2788 @property void blocking(bool byes) @trusted
2790 version (Windows)
2792 uint num = !byes;
2793 if (_SOCKET_ERROR == ioctlsocket(sock, FIONBIO, &num))
2794 goto err;
2795 _blocking = byes;
2797 else version (Posix)
2799 int x = fcntl(sock, F_GETFL, 0);
2800 if (-1 == x)
2801 goto err;
2802 if (byes)
2803 x &= ~O_NONBLOCK;
2804 else
2805 x |= O_NONBLOCK;
2806 if (-1 == fcntl(sock, F_SETFL, x))
2807 goto err;
2809 return; // Success.
2811 err:
2812 throw new SocketOSException("Unable to set socket blocking");
2816 /// Get the socket's address family.
2817 @property AddressFamily addressFamily()
2819 return _family;
2822 /// Property that indicates if this is a valid, alive socket.
2823 @property bool isAlive() @trusted const
2825 int type;
2826 socklen_t typesize = cast(socklen_t) type.sizeof;
2827 return !getsockopt(sock, SOL_SOCKET, SO_TYPE, cast(char*)&type, &typesize);
2831 * Associate a local address with this socket.
2833 * Params:
2834 * addr = The $(LREF Address) to associate this socket with.
2836 * Throws: $(LREF SocketOSException) when unable to bind the socket.
2838 void bind(Address addr) @trusted
2840 if (_SOCKET_ERROR == .bind(sock, addr.name, addr.nameLen))
2841 throw new SocketOSException("Unable to bind socket");
2845 * Establish a connection. If the socket is blocking, connect waits for
2846 * the connection to be made. If the socket is nonblocking, connect
2847 * returns immediately and the connection attempt is still in progress.
2849 void connect(Address to) @trusted
2851 if (_SOCKET_ERROR == .connect(sock, to.name, to.nameLen))
2853 int err;
2854 err = _lasterr();
2856 if (!blocking)
2858 version (Windows)
2860 if (WSAEWOULDBLOCK == err)
2861 return;
2863 else version (Posix)
2865 if (EINPROGRESS == err)
2866 return;
2868 else
2870 static assert(0);
2873 throw new SocketOSException("Unable to connect socket", err);
2878 * Listen for an incoming connection. `bind` must be called before you
2879 * can `listen`. The `backlog` is a request of how many pending
2880 * incoming connections are queued until `accept`ed.
2882 void listen(int backlog) @trusted
2884 if (_SOCKET_ERROR == .listen(sock, backlog))
2885 throw new SocketOSException("Unable to listen on socket");
2889 * Called by `accept` when a new `Socket` must be created for a new
2890 * connection. To use a derived class, override this method and return an
2891 * instance of your class. The returned `Socket`'s handle must not be
2892 * set; `Socket` has a protected constructor `this()` to use in this
2893 * situation.
2895 * Override to use a derived class.
2896 * The returned socket's handle must not be set.
2898 protected Socket accepting() pure nothrow
2900 return new Socket;
2904 * Accept an incoming connection. If the socket is blocking, `accept`
2905 * waits for a connection request. Throws `SocketAcceptException` if
2906 * unable to _accept. See `accepting` for use with derived classes.
2908 Socket accept() @trusted
2910 auto newsock = cast(socket_t).accept(sock, null, null);
2911 if (socket_t.init == newsock)
2912 throw new SocketAcceptException("Unable to accept socket connection");
2914 Socket newSocket;
2917 newSocket = accepting();
2918 assert(newSocket.sock == socket_t.init);
2920 newSocket.setSock(newsock);
2921 version (Windows)
2922 newSocket._blocking = _blocking; //inherits blocking mode
2923 newSocket._family = _family; //same family
2925 catch (Throwable o)
2927 _close(newsock);
2928 throw o;
2931 return newSocket;
2934 /// Disables sends and/or receives.
2935 void shutdown(SocketShutdown how) @trusted nothrow @nogc
2937 .shutdown(sock, cast(int) how);
2941 private static void _close(socket_t sock) @system nothrow @nogc
2943 version (Windows)
2945 .closesocket(sock);
2947 else version (Posix)
2949 .close(sock);
2955 * Immediately drop any connections and release socket resources.
2956 * The `Socket` object is no longer usable after `close`.
2957 * Calling `shutdown` before `close` is recommended
2958 * for connection-oriented sockets.
2960 void close() scope @trusted nothrow @nogc
2962 _close(sock);
2963 sock = socket_t.init;
2968 * Returns: The local machine's host name
2970 static @property string hostName() @trusted // getter
2972 char[256] result; // Host names are limited to 255 chars.
2973 if (_SOCKET_ERROR == .gethostname(result.ptr, result.length))
2974 throw new SocketOSException("Unable to obtain host name");
2975 return to!string(result.ptr);
2978 /// Remote endpoint `Address`.
2979 @property Address remoteAddress() @trusted
2981 Address addr = createAddress();
2982 socklen_t nameLen = addr.nameLen;
2983 if (_SOCKET_ERROR == .getpeername(sock, addr.name, &nameLen))
2984 throw new SocketOSException("Unable to obtain remote socket address");
2985 addr.setNameLen(nameLen);
2986 assert(addr.addressFamily == _family);
2987 return addr;
2990 /// Local endpoint `Address`.
2991 @property Address localAddress() @trusted
2993 Address addr = createAddress();
2994 socklen_t nameLen = addr.nameLen;
2995 if (_SOCKET_ERROR == .getsockname(sock, addr.name, &nameLen))
2996 throw new SocketOSException("Unable to obtain local socket address");
2997 addr.setNameLen(nameLen);
2998 assert(addr.addressFamily == _family);
2999 return addr;
3003 * Send or receive error code. See `wouldHaveBlocked`,
3004 * `lastSocketError` and `Socket.getErrorText` for obtaining more
3005 * information about the error.
3007 enum int ERROR = _SOCKET_ERROR;
3009 private static int capToInt(size_t size) nothrow @nogc
3011 // Windows uses int instead of size_t for length arguments.
3012 // Luckily, the send/recv functions make no guarantee that
3013 // all the data is sent, so we use that to send at most
3014 // int.max bytes.
3015 return size > size_t(int.max) ? int.max : cast(int) size;
3019 * Send data on the connection. If the socket is blocking and there is no
3020 * buffer space left, `send` waits.
3021 * Returns: The number of bytes actually sent, or `Socket.ERROR` on
3022 * failure.
3024 ptrdiff_t send(scope const(void)[] buf, SocketFlags flags) @trusted
3026 static if (is(typeof(MSG_NOSIGNAL)))
3028 flags = cast(SocketFlags)(flags | MSG_NOSIGNAL);
3030 version (Windows)
3031 auto sent = .send(sock, buf.ptr, capToInt(buf.length), cast(int) flags);
3032 else
3033 auto sent = .send(sock, buf.ptr, buf.length, cast(int) flags);
3034 return sent;
3037 /// ditto
3038 ptrdiff_t send(scope const(void)[] buf)
3040 return send(buf, SocketFlags.NONE);
3044 * Send data to a specific destination Address. If the destination address is
3045 * not specified, a connection must have been made and that address is used.
3046 * If the socket is blocking and there is no buffer space left, `sendTo` waits.
3047 * Returns: The number of bytes actually sent, or `Socket.ERROR` on
3048 * failure.
3050 ptrdiff_t sendTo(scope const(void)[] buf, SocketFlags flags, Address to) @trusted
3052 static if (is(typeof(MSG_NOSIGNAL)))
3054 flags = cast(SocketFlags)(flags | MSG_NOSIGNAL);
3056 version (Windows)
3057 return .sendto(
3058 sock, buf.ptr, capToInt(buf.length),
3059 cast(int) flags, to.name, to.nameLen
3061 else
3062 return .sendto(sock, buf.ptr, buf.length, cast(int) flags, to.name, to.nameLen);
3065 /// ditto
3066 ptrdiff_t sendTo(scope const(void)[] buf, Address to)
3068 return sendTo(buf, SocketFlags.NONE, to);
3072 //assumes you connect()ed
3073 /// ditto
3074 ptrdiff_t sendTo(scope const(void)[] buf, SocketFlags flags) @trusted
3076 static if (is(typeof(MSG_NOSIGNAL)))
3078 flags = cast(SocketFlags)(flags | MSG_NOSIGNAL);
3080 version (Windows)
3081 return .sendto(sock, buf.ptr, capToInt(buf.length), cast(int) flags, null, 0);
3082 else
3083 return .sendto(sock, buf.ptr, buf.length, cast(int) flags, null, 0);
3087 //assumes you connect()ed
3088 /// ditto
3089 ptrdiff_t sendTo(scope const(void)[] buf)
3091 return sendTo(buf, SocketFlags.NONE);
3096 * Receive data on the connection. If the socket is blocking, `receive`
3097 * waits until there is data to be received.
3098 * Returns: The number of bytes actually received, `0` if the remote side
3099 * has closed the connection, or `Socket.ERROR` on failure.
3101 ptrdiff_t receive(scope void[] buf, SocketFlags flags) @trusted
3103 version (Windows) // Does not use size_t
3105 return buf.length
3106 ? .recv(sock, buf.ptr, capToInt(buf.length), cast(int) flags)
3107 : 0;
3109 else
3111 return buf.length
3112 ? .recv(sock, buf.ptr, buf.length, cast(int) flags)
3113 : 0;
3117 /// ditto
3118 ptrdiff_t receive(scope void[] buf)
3120 return receive(buf, SocketFlags.NONE);
3124 * Receive data and get the remote endpoint `Address`.
3125 * If the socket is blocking, `receiveFrom` waits until there is data to
3126 * be received.
3127 * Returns: The number of bytes actually received, `0` if the remote side
3128 * has closed the connection, or `Socket.ERROR` on failure.
3130 ptrdiff_t receiveFrom(scope void[] buf, SocketFlags flags, ref Address from) @trusted
3132 if (!buf.length) //return 0 and don't think the connection closed
3133 return 0;
3134 if (from is null || from.addressFamily != _family)
3135 from = createAddress();
3136 socklen_t nameLen = from.nameLen;
3137 version (Windows)
3138 auto read = .recvfrom(sock, buf.ptr, capToInt(buf.length), cast(int) flags, from.name, &nameLen);
3140 else
3141 auto read = .recvfrom(sock, buf.ptr, buf.length, cast(int) flags, from.name, &nameLen);
3143 if (read >= 0)
3145 from.setNameLen(nameLen);
3146 assert(from.addressFamily == _family);
3148 return read;
3152 /// ditto
3153 ptrdiff_t receiveFrom(scope void[] buf, ref Address from)
3155 return receiveFrom(buf, SocketFlags.NONE, from);
3159 //assumes you connect()ed
3160 /// ditto
3161 ptrdiff_t receiveFrom(scope void[] buf, SocketFlags flags) @trusted
3163 if (!buf.length) //return 0 and don't think the connection closed
3164 return 0;
3165 version (Windows)
3167 auto read = .recvfrom(sock, buf.ptr, capToInt(buf.length), cast(int) flags, null, null);
3168 // if (!read) //connection closed
3169 return read;
3171 else
3173 auto read = .recvfrom(sock, buf.ptr, buf.length, cast(int) flags, null, null);
3174 // if (!read) //connection closed
3175 return read;
3180 //assumes you connect()ed
3181 /// ditto
3182 ptrdiff_t receiveFrom(scope void[] buf)
3184 return receiveFrom(buf, SocketFlags.NONE);
3189 * Get a socket option.
3190 * Returns: The number of bytes written to `result`.
3191 * The length, in bytes, of the actual result - very different from getsockopt()
3193 int getOption(SocketOptionLevel level, SocketOption option, scope void[] result) @trusted
3195 socklen_t len = cast(socklen_t) result.length;
3196 if (_SOCKET_ERROR == .getsockopt(sock, cast(int) level, cast(int) option, result.ptr, &len))
3197 throw new SocketOSException("Unable to get socket option");
3198 return len;
3202 /// Common case of getting integer and boolean options.
3203 int getOption(SocketOptionLevel level, SocketOption option, out int32_t result) @trusted
3205 return getOption(level, option, (&result)[0 .. 1]);
3209 /// Get the linger option.
3210 int getOption(SocketOptionLevel level, SocketOption option, out Linger result) @trusted
3212 //return getOption(cast(SocketOptionLevel) SocketOptionLevel.SOCKET, SocketOption.LINGER, (&result)[0 .. 1]);
3213 return getOption(level, option, (&result.clinger)[0 .. 1]);
3216 /// Get a timeout (duration) option.
3217 void getOption(SocketOptionLevel level, SocketOption option, out Duration result) @trusted
3219 enforce(option == SocketOption.SNDTIMEO || option == SocketOption.RCVTIMEO,
3220 new SocketParameterException("Not a valid timeout option: " ~ to!string(option)));
3221 // WinSock returns the timeout values as a milliseconds DWORD,
3222 // while Linux and BSD return a timeval struct.
3223 version (Windows)
3225 int msecs;
3226 getOption(level, option, (&msecs)[0 .. 1]);
3227 if (option == SocketOption.RCVTIMEO)
3228 msecs += WINSOCK_TIMEOUT_SKEW;
3229 result = dur!"msecs"(msecs);
3231 else version (Posix)
3233 TimeVal tv;
3234 getOption(level, option, (&tv.ctimeval)[0 .. 1]);
3235 result = dur!"seconds"(tv.seconds) + dur!"usecs"(tv.microseconds);
3237 else static assert(false);
3240 /// Set a socket option.
3241 void setOption(SocketOptionLevel level, SocketOption option, scope void[] value) @trusted
3243 if (_SOCKET_ERROR == .setsockopt(sock, cast(int) level,
3244 cast(int) option, value.ptr, cast(uint) value.length))
3245 throw new SocketOSException("Unable to set socket option");
3249 /// Common case for setting integer and boolean options.
3250 void setOption(SocketOptionLevel level, SocketOption option, int32_t value) @trusted
3252 setOption(level, option, (&value)[0 .. 1]);
3256 /// Set the linger option.
3257 void setOption(SocketOptionLevel level, SocketOption option, Linger value) @trusted
3259 //setOption(cast(SocketOptionLevel) SocketOptionLevel.SOCKET, SocketOption.LINGER, (&value)[0 .. 1]);
3260 setOption(level, option, (&value.clinger)[0 .. 1]);
3264 * Sets a timeout (duration) option, i.e. `SocketOption.SNDTIMEO` or
3265 * `RCVTIMEO`. Zero indicates no timeout.
3267 * In a typical application, you might also want to consider using
3268 * a non-blocking socket instead of setting a timeout on a blocking one.
3270 * Note: While the receive timeout setting is generally quite accurate
3271 * on *nix systems even for smaller durations, there are two issues to
3272 * be aware of on Windows: First, although undocumented, the effective
3273 * timeout duration seems to be the one set on the socket plus half
3274 * a second. `setOption()` tries to compensate for that, but still,
3275 * timeouts under 500ms are not possible on Windows. Second, be aware
3276 * that the actual amount of time spent until a blocking call returns
3277 * randomly varies on the order of 10ms.
3279 * Params:
3280 * level = The level at which a socket option is defined.
3281 * option = Either `SocketOption.SNDTIMEO` or `SocketOption.RCVTIMEO`.
3282 * value = The timeout duration to set. Must not be negative.
3284 * Throws: `SocketException` if setting the options fails.
3286 * Example:
3287 * ---
3288 * import std.datetime;
3289 * import std.typecons;
3290 * auto pair = socketPair();
3291 * scope(exit) foreach (s; pair) s.close();
3293 * // Set a receive timeout, and then wait at one end of
3294 * // the socket pair, knowing that no data will arrive.
3295 * pair[0].setOption(SocketOptionLevel.SOCKET,
3296 * SocketOption.RCVTIMEO, dur!"seconds"(1));
3298 * auto sw = StopWatch(Yes.autoStart);
3299 * ubyte[1] buffer;
3300 * pair[0].receive(buffer);
3301 * writefln("Waited %s ms until the socket timed out.",
3302 * sw.peek.msecs);
3303 * ---
3305 void setOption(SocketOptionLevel level, SocketOption option, Duration value) @trusted
3307 enforce(option == SocketOption.SNDTIMEO || option == SocketOption.RCVTIMEO,
3308 new SocketParameterException("Not a valid timeout option: " ~ to!string(option)));
3310 enforce(value >= dur!"hnsecs"(0), new SocketParameterException(
3311 "Timeout duration must not be negative."));
3313 version (Windows)
3315 import std.algorithm.comparison : max;
3317 auto msecs = to!int(value.total!"msecs");
3318 if (msecs != 0 && option == SocketOption.RCVTIMEO)
3319 msecs = max(1, msecs - WINSOCK_TIMEOUT_SKEW);
3320 setOption(level, option, msecs);
3322 else version (Posix)
3324 _ctimeval tv;
3325 value.split!("seconds", "usecs")(tv.tv_sec, tv.tv_usec);
3326 setOption(level, option, (&tv)[0 .. 1]);
3328 else static assert(false);
3332 * Get a text description of this socket's error status, and clear the
3333 * socket's error status.
3335 string getErrorText()
3337 int32_t error;
3338 getOption(SocketOptionLevel.SOCKET, SocketOption.ERROR, error);
3339 return formatSocketError(error);
3343 * Enables TCP keep-alive with the specified parameters.
3345 * Params:
3346 * time = Number of seconds with no activity until the first
3347 * keep-alive packet is sent.
3348 * interval = Number of seconds between when successive keep-alive
3349 * packets are sent if no acknowledgement is received.
3351 * Throws: `SocketOSException` if setting the options fails, or
3352 * `SocketFeatureException` if setting keep-alive parameters is
3353 * unsupported on the current platform.
3355 void setKeepAlive(int time, int interval) @trusted
3357 version (Windows)
3359 tcp_keepalive options;
3360 options.onoff = 1;
3361 options.keepalivetime = time * 1000;
3362 options.keepaliveinterval = interval * 1000;
3363 uint cbBytesReturned;
3364 enforce(WSAIoctl(sock, SIO_KEEPALIVE_VALS,
3365 &options, options.sizeof,
3366 null, 0,
3367 &cbBytesReturned, null, null) == 0,
3368 new SocketOSException("Error setting keep-alive"));
3370 else
3371 static if (is(typeof(TCP_KEEPIDLE)) && is(typeof(TCP_KEEPINTVL)))
3373 setOption(SocketOptionLevel.TCP, cast(SocketOption) TCP_KEEPIDLE, time);
3374 setOption(SocketOptionLevel.TCP, cast(SocketOption) TCP_KEEPINTVL, interval);
3375 setOption(SocketOptionLevel.SOCKET, SocketOption.KEEPALIVE, true);
3377 else
3378 throw new SocketFeatureException("Setting keep-alive options " ~
3379 "is not supported on this platform");
3383 * Wait for a socket to change status. A wait timeout of $(REF Duration, core, time) or
3384 * `TimeVal`, may be specified; if a timeout is not specified or the
3385 * `TimeVal` is `null`, the maximum timeout is used. The `TimeVal`
3386 * timeout has an unspecified value when `select` returns.
3387 * Returns: The number of sockets with status changes, `0` on timeout,
3388 * or `-1` on interruption. If the return value is greater than `0`,
3389 * the `SocketSets` are updated to only contain the sockets having status
3390 * changes. For a connecting socket, a write status change means the
3391 * connection is established and it's able to send. For a listening socket,
3392 * a read status change means there is an incoming connection request and
3393 * it's able to accept.
3395 * `SocketSet`'s updated to include only those sockets which an event occured.
3396 * For a `connect()`ing socket, writeability means connected.
3397 * For a `listen()`ing socket, readability means listening
3398 * `Winsock`; possibly internally limited to 64 sockets per set.
3400 * Returns:
3401 * the number of events, 0 on timeout, or -1 on interruption
3403 static int select(SocketSet checkRead, SocketSet checkWrite, SocketSet checkError, Duration timeout) @trusted
3405 auto vals = timeout.split!("seconds", "usecs")();
3406 TimeVal tv;
3407 tv.seconds = cast(tv.tv_sec_t ) vals.seconds;
3408 tv.microseconds = cast(tv.tv_usec_t) vals.usecs;
3409 return select(checkRead, checkWrite, checkError, &tv);
3412 /// ditto
3413 //maximum timeout
3414 static int select(SocketSet checkRead, SocketSet checkWrite, SocketSet checkError)
3416 return select(checkRead, checkWrite, checkError, null);
3419 /// Ditto
3420 static int select(SocketSet checkRead, SocketSet checkWrite, SocketSet checkError, TimeVal* timeout) @trusted
3423 //make sure none of the SocketSet's are the same object
3424 if (checkRead)
3426 assert(checkRead !is checkWrite);
3427 assert(checkRead !is checkError);
3429 if (checkWrite)
3431 assert(checkWrite !is checkError);
3436 fd_set* fr, fw, fe;
3437 int n = 0;
3439 version (Windows)
3441 // Windows has a problem with empty fd_set`s that aren't null.
3442 fr = checkRead && checkRead.count ? checkRead.toFd_set() : null;
3443 fw = checkWrite && checkWrite.count ? checkWrite.toFd_set() : null;
3444 fe = checkError && checkError.count ? checkError.toFd_set() : null;
3446 else
3448 if (checkRead)
3450 fr = checkRead.toFd_set();
3451 n = checkRead.selectn();
3453 else
3455 fr = null;
3458 if (checkWrite)
3460 fw = checkWrite.toFd_set();
3461 int _n;
3462 _n = checkWrite.selectn();
3463 if (_n > n)
3464 n = _n;
3466 else
3468 fw = null;
3471 if (checkError)
3473 fe = checkError.toFd_set();
3474 int _n;
3475 _n = checkError.selectn();
3476 if (_n > n)
3477 n = _n;
3479 else
3481 fe = null;
3484 // Make sure the sets' capacity matches, to avoid select reading
3485 // out of bounds just because one set was bigger than another
3486 if (checkRead ) checkRead .setMinCapacity(n);
3487 if (checkWrite) checkWrite.setMinCapacity(n);
3488 if (checkError) checkError.setMinCapacity(n);
3491 int result = .select(n, fr, fw, fe, &timeout.ctimeval);
3493 version (Windows)
3495 if (_SOCKET_ERROR == result && WSAGetLastError() == WSAEINTR)
3496 return -1;
3498 else version (Posix)
3500 if (_SOCKET_ERROR == result && errno == EINTR)
3501 return -1;
3503 else
3505 static assert(0);
3508 if (_SOCKET_ERROR == result)
3509 throw new SocketOSException("Socket select error");
3511 return result;
3516 * Can be overridden to support other addresses.
3517 * Returns: A new `Address` object for the current address family.
3519 protected Address createAddress() pure nothrow
3521 Address result;
3522 switch (_family)
3524 static if (is(sockaddr_un))
3526 case AddressFamily.UNIX:
3527 result = new UnixAddress;
3528 break;
3531 case AddressFamily.INET:
3532 result = new InternetAddress;
3533 break;
3535 case AddressFamily.INET6:
3536 result = new Internet6Address;
3537 break;
3539 default:
3540 result = new UnknownAddress;
3542 return result;
3548 /// Shortcut class for a TCP Socket.
3549 class TcpSocket: Socket
3551 /// Constructs a blocking TCP Socket.
3552 this(AddressFamily family)
3554 super(family, SocketType.STREAM, ProtocolType.TCP);
3557 /// Constructs a blocking IPv4 TCP Socket.
3558 this()
3560 this(AddressFamily.INET);
3564 //shortcut
3565 /// Constructs a blocking TCP Socket and connects to the given `Address`.
3566 this(Address connectTo)
3568 this(connectTo.addressFamily);
3569 connect(connectTo);
3574 /// Shortcut class for a UDP Socket.
3575 class UdpSocket: Socket
3577 /// Constructs a blocking UDP Socket.
3578 this(AddressFamily family)
3580 super(family, SocketType.DGRAM, ProtocolType.UDP);
3584 /// Constructs a blocking IPv4 UDP Socket.
3585 this()
3587 this(AddressFamily.INET);
3591 @safe unittest
3593 byte[] buf;
3594 buf.length = 1;
3595 Address addr;
3596 auto s = new UdpSocket;
3597 s.blocking = false;
3598 s.bind(new InternetAddress(InternetAddress.PORT_ANY));
3599 s.receiveFrom(buf, addr);
3602 // https://issues.dlang.org/show_bug.cgi?id=16514
3603 @safe unittest
3605 void checkAttributes(string attributes)()
3607 mixin(attributes ~ q{ void function() fun = {};});
3608 fun();
3611 class TestSocket : Socket
3613 override
3615 @property pure nothrow @nogc @safe socket_t handle() const
3617 checkAttributes!q{pure nothrow @nogc @safe}; assert(0);
3619 @property nothrow @nogc @trusted bool blocking() const
3621 checkAttributes!q{nothrow @nogc @trusted}; assert(0);
3623 @property @trusted void blocking(bool byes)
3625 checkAttributes!q{@trusted};
3627 @property @safe AddressFamily addressFamily()
3629 checkAttributes!q{@safe}; assert(0);
3631 @property @trusted bool isAlive() const
3633 checkAttributes!q{@trusted}; assert(0);
3635 @trusted void bind(Address addr)
3637 checkAttributes!q{@trusted};
3639 @trusted void connect(Address to)
3641 checkAttributes!q{@trusted};
3643 @trusted void listen(int backlog)
3645 checkAttributes!q{@trusted};
3647 protected pure nothrow @safe Socket accepting()
3649 checkAttributes!q{pure nothrow @safe}; assert(0);
3651 @trusted Socket accept()
3653 checkAttributes!q{@trusted}; assert(0);
3655 nothrow @nogc @trusted void shutdown(SocketShutdown how)
3657 checkAttributes!q{nothrow @nogc @trusted};
3659 nothrow @nogc @trusted scope void close()
3661 checkAttributes!q{nothrow @nogc @trusted};
3663 @property @trusted Address remoteAddress()
3665 checkAttributes!q{@trusted}; assert(0);
3667 @property @trusted Address localAddress()
3669 checkAttributes!q{@trusted}; assert(0);
3671 @trusted ptrdiff_t send(scope const(void)[] buf, SocketFlags flags)
3673 checkAttributes!q{@trusted}; assert(0);
3675 @safe ptrdiff_t send(scope const(void)[] buf)
3677 checkAttributes!q{@safe}; assert(0);
3679 @trusted ptrdiff_t sendTo(scope const(void)[] buf, SocketFlags flags, Address to)
3681 checkAttributes!q{@trusted}; assert(0);
3683 @safe ptrdiff_t sendTo(scope const(void)[] buf, Address to)
3685 checkAttributes!q{@safe}; assert(0);
3687 @trusted ptrdiff_t sendTo(scope const(void)[] buf, SocketFlags flags)
3689 checkAttributes!q{@trusted}; assert(0);
3691 @safe ptrdiff_t sendTo(scope const(void)[] buf)
3693 checkAttributes!q{@safe}; assert(0);
3695 @trusted ptrdiff_t receive(scope void[] buf, SocketFlags flags)
3697 checkAttributes!q{@trusted}; assert(0);
3699 @safe ptrdiff_t receive(scope void[] buf)
3701 checkAttributes!q{@safe}; assert(0);
3703 @trusted ptrdiff_t receiveFrom(scope void[] buf, SocketFlags flags, ref Address from)
3705 checkAttributes!q{@trusted}; assert(0);
3707 @safe ptrdiff_t receiveFrom(scope void[] buf, ref Address from)
3709 checkAttributes!q{@safe}; assert(0);
3711 @trusted ptrdiff_t receiveFrom(scope void[] buf, SocketFlags flags)
3713 checkAttributes!q{@trusted}; assert(0);
3715 @safe ptrdiff_t receiveFrom(scope void[] buf)
3717 checkAttributes!q{@safe}; assert(0);
3719 @trusted int getOption(SocketOptionLevel level, SocketOption option, scope void[] result)
3721 checkAttributes!q{@trusted}; assert(0);
3723 @trusted int getOption(SocketOptionLevel level, SocketOption option, out int32_t result)
3725 checkAttributes!q{@trusted}; assert(0);
3727 @trusted int getOption(SocketOptionLevel level, SocketOption option, out Linger result)
3729 checkAttributes!q{@trusted}; assert(0);
3731 @trusted void getOption(SocketOptionLevel level, SocketOption option, out Duration result)
3733 checkAttributes!q{@trusted};
3735 @trusted void setOption(SocketOptionLevel level, SocketOption option, scope void[] value)
3737 checkAttributes!q{@trusted};
3739 @trusted void setOption(SocketOptionLevel level, SocketOption option, int32_t value)
3741 checkAttributes!q{@trusted};
3743 @trusted void setOption(SocketOptionLevel level, SocketOption option, Linger value)
3745 checkAttributes!q{@trusted};
3747 @trusted void setOption(SocketOptionLevel level, SocketOption option, Duration value)
3749 checkAttributes!q{@trusted};
3751 @safe string getErrorText()
3753 checkAttributes!q{@safe}; assert(0);
3755 @trusted void setKeepAlive(int time, int interval)
3757 checkAttributes!q{@trusted};
3759 protected pure nothrow @safe Address createAddress()
3761 checkAttributes!q{pure nothrow @safe}; assert(0);
3768 * Creates a pair of connected sockets.
3770 * The two sockets are indistinguishable.
3772 * Throws: `SocketException` if creation of the sockets fails.
3774 Socket[2] socketPair() @trusted
3776 version (Posix)
3778 int[2] socks;
3779 if (socketpair(AF_UNIX, SOCK_STREAM, 0, socks) == -1)
3780 throw new SocketOSException("Unable to create socket pair");
3782 Socket toSocket(size_t id)
3784 auto s = new Socket;
3785 s.setSock(cast(socket_t) socks[id]);
3786 s._family = AddressFamily.UNIX;
3787 return s;
3790 return [toSocket(0), toSocket(1)];
3792 else version (Windows)
3794 // We do not have socketpair() on Windows, just manually create a
3795 // pair of sockets connected over some localhost port.
3796 Socket[2] result;
3798 auto listener = new TcpSocket();
3799 listener.setOption(SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, true);
3800 listener.bind(new InternetAddress(INADDR_LOOPBACK, InternetAddress.PORT_ANY));
3801 auto addr = listener.localAddress;
3802 listener.listen(1);
3804 result[0] = new TcpSocket(addr);
3805 result[1] = listener.accept();
3807 listener.close();
3808 return result;
3810 else
3811 static assert(false);
3815 @safe unittest
3817 immutable ubyte[4] data = [1, 2, 3, 4];
3818 auto pair = socketPair();
3819 scope(exit) foreach (s; pair) s.close();
3821 pair[0].send(data[]);
3823 auto buf = new ubyte[data.length];
3824 pair[1].receive(buf);
3825 assert(buf == data);