d: Merge upstream dmd 47871363d, druntime, c52e28b7, phobos 99e9c1b77.
[official-gcc.git] / libphobos / src / std / socket.d
blob915159f180fad460acc27c9698ea0d74f0216e3a
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);
127 /// Base exception thrown by `std.socket`.
128 class SocketException: Exception
130 mixin basicExceptionCtors;
133 version (CRuntime_Glibc) version = GNU_STRERROR;
134 version (CRuntime_UClibc) version = GNU_STRERROR;
137 * Needs to be public so that SocketOSException can be thrown outside of
138 * std.socket (since it uses it as a default argument), but it probably doesn't
139 * need to actually show up in the docs, since there's not really any public
140 * need for it outside of being a default argument.
142 string formatSocketError(int err) @trusted
144 version (Posix)
146 char[80] buf;
147 const(char)* cs;
148 version (GNU_STRERROR)
150 cs = strerror_r(err, buf.ptr, buf.length);
152 else
154 auto errs = strerror_r(err, buf.ptr, buf.length);
155 if (errs == 0)
156 cs = buf.ptr;
157 else
158 return "Socket error " ~ to!string(err);
161 auto len = strlen(cs);
163 if (cs[len - 1] == '\n')
164 len--;
165 if (cs[len - 1] == '\r')
166 len--;
167 return cs[0 .. len].idup;
169 else
170 version (Windows)
172 return generateSysErrorMsg(err);
174 else
175 return "Socket error " ~ to!string(err);
178 /// Retrieve the error message for the most recently encountered network error.
179 @property string lastSocketError()
181 return formatSocketError(_lasterr());
185 * Socket exceptions representing network errors reported by the operating
186 * system.
188 class SocketOSException: SocketException
190 int errorCode; /// Platform-specific error code.
193 this(string msg,
194 string file = __FILE__,
195 size_t line = __LINE__,
196 Throwable next = null,
197 int err = _lasterr(),
198 string function(int) @trusted errorFormatter = &formatSocketError)
200 errorCode = err;
202 if (msg.length)
203 super(msg ~ ": " ~ errorFormatter(err), file, line, next);
204 else
205 super(errorFormatter(err), file, line, next);
209 this(string msg,
210 Throwable next,
211 string file = __FILE__,
212 size_t line = __LINE__,
213 int err = _lasterr(),
214 string function(int) @trusted errorFormatter = &formatSocketError)
216 this(msg, file, line, next, err, errorFormatter);
220 this(string msg,
221 int err,
222 string function(int) @trusted errorFormatter = &formatSocketError,
223 string file = __FILE__,
224 size_t line = __LINE__,
225 Throwable next = null)
227 this(msg, file, line, next, err, errorFormatter);
231 /// Socket exceptions representing invalid parameters specified by user code.
232 class SocketParameterException: SocketException
234 mixin basicExceptionCtors;
238 * Socket exceptions representing attempts to use network capabilities not
239 * available on the current system.
241 class SocketFeatureException: SocketException
243 mixin basicExceptionCtors;
248 * Returns:
249 * `true` if the last socket operation failed because the socket
250 * was in non-blocking mode and the operation would have blocked,
251 * or if the socket is in blocking mode and set a SNDTIMEO or RCVTIMEO,
252 * and the operation timed out.
254 bool wouldHaveBlocked() nothrow @nogc
256 version (Windows)
257 return _lasterr() == WSAEWOULDBLOCK || _lasterr() == WSAETIMEDOUT;
258 else version (Posix)
259 return _lasterr() == EAGAIN;
260 else
261 static assert(0, "No socket support for this platform yet.");
264 @safe unittest
266 auto sockets = socketPair();
267 auto s = sockets[0];
268 s.setOption(SocketOptionLevel.SOCKET, SocketOption.RCVTIMEO, dur!"msecs"(10));
269 ubyte[] buffer = new ubyte[](16);
270 auto rec = s.receive(buffer);
271 assert(rec == -1 && wouldHaveBlocked());
275 private immutable
277 typeof(&getnameinfo) getnameinfoPointer;
278 typeof(&getaddrinfo) getaddrinfoPointer;
279 typeof(&freeaddrinfo) freeaddrinfoPointer;
282 shared static this() @system
284 version (Windows)
286 WSADATA wd;
288 // Winsock will still load if an older version is present.
289 // The version is just a request.
290 int val;
291 val = WSAStartup(0x2020, &wd);
292 if (val) // Request Winsock 2.2 for IPv6.
293 throw new SocketOSException("Unable to initialize socket library", val);
295 // These functions may not be present on older Windows versions.
296 // See the comment in InternetAddress.toHostNameString() for details.
297 auto ws2Lib = GetModuleHandleA("ws2_32.dll");
298 if (ws2Lib)
300 getnameinfoPointer = cast(typeof(getnameinfoPointer))
301 GetProcAddress(ws2Lib, "getnameinfo");
302 getaddrinfoPointer = cast(typeof(getaddrinfoPointer))
303 GetProcAddress(ws2Lib, "getaddrinfo");
304 freeaddrinfoPointer = cast(typeof(freeaddrinfoPointer))
305 GetProcAddress(ws2Lib, "freeaddrinfo");
308 else version (Posix)
310 getnameinfoPointer = &getnameinfo;
311 getaddrinfoPointer = &getaddrinfo;
312 freeaddrinfoPointer = &freeaddrinfo;
317 shared static ~this() @system nothrow @nogc
319 version (Windows)
321 WSACleanup();
326 * The communication domain used to resolve an address.
328 enum AddressFamily: ushort
330 UNSPEC = AF_UNSPEC, /// Unspecified address family
331 UNIX = AF_UNIX, /// Local communication
332 INET = AF_INET, /// Internet Protocol version 4
333 IPX = AF_IPX, /// Novell IPX
334 APPLETALK = AF_APPLETALK, /// AppleTalk
335 INET6 = AF_INET6, /// Internet Protocol version 6
340 * Communication semantics
342 enum SocketType: int
344 STREAM = SOCK_STREAM, /// Sequenced, reliable, two-way communication-based byte streams
345 DGRAM = SOCK_DGRAM, /// Connectionless, unreliable datagrams with a fixed maximum length; data may be lost or arrive out of order
346 RAW = SOCK_RAW, /// Raw protocol access
347 RDM = SOCK_RDM, /// Reliably-delivered message datagrams
348 SEQPACKET = SOCK_SEQPACKET, /// Sequenced, reliable, two-way connection-based datagrams with a fixed maximum length
353 * Protocol
355 enum ProtocolType: int
357 IP = IPPROTO_IP, /// Internet Protocol version 4
358 ICMP = IPPROTO_ICMP, /// Internet Control Message Protocol
359 IGMP = IPPROTO_IGMP, /// Internet Group Management Protocol
360 GGP = IPPROTO_GGP, /// Gateway to Gateway Protocol
361 TCP = IPPROTO_TCP, /// Transmission Control Protocol
362 PUP = IPPROTO_PUP, /// PARC Universal Packet Protocol
363 UDP = IPPROTO_UDP, /// User Datagram Protocol
364 IDP = IPPROTO_IDP, /// Xerox NS protocol
365 RAW = IPPROTO_RAW, /// Raw IP packets
366 IPV6 = IPPROTO_IPV6, /// Internet Protocol version 6
371 * `Protocol` is a class for retrieving protocol information.
373 * Example:
374 * ---
375 * auto proto = new Protocol;
376 * writeln("About protocol TCP:");
377 * if (proto.getProtocolByType(ProtocolType.TCP))
379 * writefln(" Name: %s", proto.name);
380 * foreach (string s; proto.aliases)
381 * writefln(" Alias: %s", s);
383 * else
384 * writeln(" No information found");
385 * ---
387 class Protocol
389 /// These members are populated when one of the following functions are called successfully:
390 ProtocolType type;
391 string name; /// ditto
392 string[] aliases; /// ditto
395 void populate(protoent* proto) @system pure nothrow
397 type = cast(ProtocolType) proto.p_proto;
398 name = to!string(proto.p_name);
400 int i;
401 for (i = 0;; i++)
403 if (!proto.p_aliases[i])
404 break;
407 if (i)
409 aliases = new string[i];
410 for (i = 0; i != aliases.length; i++)
412 aliases[i] =
413 to!string(proto.p_aliases[i]);
416 else
418 aliases = null;
422 /** Returns: false on failure */
423 bool getProtocolByName(scope const(char)[] name) @trusted nothrow
425 protoent* proto;
426 proto = getprotobyname(name.tempCString());
427 if (!proto)
428 return false;
429 populate(proto);
430 return true;
434 /** Returns: false on failure */
435 // Same as getprotobynumber().
436 bool getProtocolByType(ProtocolType type) @trusted nothrow
438 protoent* proto;
439 proto = getprotobynumber(type);
440 if (!proto)
441 return false;
442 populate(proto);
443 return true;
448 // Skip this test on Android because getprotobyname/number are
449 // unimplemented in bionic.
450 version (CRuntime_Bionic) {} else
451 @safe unittest
453 // import std.stdio : writefln;
454 softUnittest({
455 Protocol proto = new Protocol;
456 assert(proto.getProtocolByType(ProtocolType.TCP));
457 //writeln("About protocol TCP:");
458 //writefln("\tName: %s", proto.name);
459 // foreach (string s; proto.aliases)
460 // {
461 // writefln("\tAlias: %s", s);
462 // }
463 assert(proto.name == "tcp");
464 assert(proto.aliases.length == 1 && proto.aliases[0] == "TCP");
470 * `Service` is a class for retrieving service information.
472 * Example:
473 * ---
474 * auto serv = new Service;
475 * writeln("About service epmap:");
476 * if (serv.getServiceByName("epmap", "tcp"))
478 * writefln(" Service: %s", serv.name);
479 * writefln(" Port: %d", serv.port);
480 * writefln(" Protocol: %s", serv.protocolName);
481 * foreach (string s; serv.aliases)
482 * writefln(" Alias: %s", s);
484 * else
485 * writefln(" No service for epmap.");
486 * ---
488 class Service
490 /// These members are populated when one of the following functions are called successfully:
491 string name;
492 string[] aliases; /// ditto
493 ushort port; /// ditto
494 string protocolName; /// ditto
497 void populate(servent* serv) @system pure nothrow
499 name = to!string(serv.s_name);
500 port = ntohs(cast(ushort) serv.s_port);
501 protocolName = to!string(serv.s_proto);
503 int i;
504 for (i = 0;; i++)
506 if (!serv.s_aliases[i])
507 break;
510 if (i)
512 aliases = new string[i];
513 for (i = 0; i != aliases.length; i++)
515 aliases[i] =
516 to!string(serv.s_aliases[i]);
519 else
521 aliases = null;
526 * If a protocol name is omitted, any protocol will be matched.
527 * Returns: false on failure.
529 bool getServiceByName(scope const(char)[] name, scope const(char)[] protocolName = null) @trusted nothrow
531 servent* serv;
532 serv = getservbyname(name.tempCString(), protocolName.tempCString());
533 if (!serv)
534 return false;
535 populate(serv);
536 return true;
540 /// ditto
541 bool getServiceByPort(ushort port, scope const(char)[] protocolName = null) @trusted nothrow
543 servent* serv;
544 serv = getservbyport(port, protocolName.tempCString());
545 if (!serv)
546 return false;
547 populate(serv);
548 return true;
553 @safe unittest
555 import std.stdio : writefln;
556 softUnittest({
557 Service serv = new Service;
558 if (serv.getServiceByName("epmap", "tcp"))
560 // writefln("About service epmap:");
561 // writefln("\tService: %s", serv.name);
562 // writefln("\tPort: %d", serv.port);
563 // writefln("\tProtocol: %s", serv.protocolName);
564 // foreach (string s; serv.aliases)
565 // {
566 // writefln("\tAlias: %s", s);
567 // }
568 // For reasons unknown this is loc-srv on Wine and epmap on Windows
569 assert(serv.name == "loc-srv" || serv.name == "epmap", serv.name);
570 assert(serv.port == 135);
571 assert(serv.protocolName == "tcp");
573 else
575 writefln("No service for epmap.");
581 private mixin template socketOSExceptionCtors()
584 this(string msg, string file = __FILE__, size_t line = __LINE__,
585 Throwable next = null, int err = _lasterr())
587 super(msg, file, line, next, err);
591 this(string msg, Throwable next, string file = __FILE__,
592 size_t line = __LINE__, int err = _lasterr())
594 super(msg, next, file, line, err);
598 this(string msg, int err, string file = __FILE__, size_t line = __LINE__,
599 Throwable next = null)
601 super(msg, next, file, line, err);
607 * Class for exceptions thrown from an `InternetHost`.
609 class HostException: SocketOSException
611 mixin socketOSExceptionCtors;
615 * `InternetHost` is a class for resolving IPv4 addresses.
617 * Consider using `getAddress`, `parseAddress` and `Address` methods
618 * instead of using this class directly.
620 class InternetHost
622 /// These members are populated when one of the following functions are called successfully:
623 string name;
624 string[] aliases; /// ditto
625 uint[] addrList; /// ditto
628 void validHostent(in hostent* he)
630 if (he.h_addrtype != cast(int) AddressFamily.INET || he.h_length != 4)
631 throw new HostException("Address family mismatch");
635 void populate(hostent* he) @system pure nothrow
637 int i;
638 char* p;
640 name = to!string(he.h_name);
642 for (i = 0;; i++)
644 p = he.h_aliases[i];
645 if (!p)
646 break;
649 if (i)
651 aliases = new string[i];
652 for (i = 0; i != aliases.length; i++)
654 aliases[i] =
655 to!string(he.h_aliases[i]);
658 else
660 aliases = null;
663 for (i = 0;; i++)
665 p = he.h_addr_list[i];
666 if (!p)
667 break;
670 if (i)
672 addrList = new uint[i];
673 for (i = 0; i != addrList.length; i++)
675 addrList[i] = ntohl(*(cast(uint*) he.h_addr_list[i]));
678 else
680 addrList = null;
684 private bool getHostNoSync(string opMixin, T)(T param) @system
686 mixin(opMixin);
687 if (!he)
688 return false;
689 validHostent(he);
690 populate(he);
691 return true;
694 version (Windows)
695 alias getHost = getHostNoSync;
696 else
698 // posix systems use global state for return value, so we
699 // must synchronize across all threads
700 private bool getHost(string opMixin, T)(T param) @system
702 synchronized(this.classinfo)
703 return getHostNoSync!(opMixin, T)(param);
708 * Resolve host name.
709 * Returns: false if unable to resolve.
711 bool getHostByName(scope const(char)[] name) @trusted
713 static if (is(typeof(gethostbyname_r)))
715 return getHostNoSync!q{
716 hostent he_v;
717 hostent* he;
718 ubyte[256] buffer_v = void;
719 auto buffer = buffer_v[];
720 auto param_zTmp = param.tempCString();
721 while (true)
723 he = &he_v;
724 int errno;
725 if (gethostbyname_r(param_zTmp, he, buffer.ptr, buffer.length, &he, &errno) == ERANGE)
726 buffer.length = buffer.length * 2;
727 else
728 break;
730 }(name);
732 else
734 return getHost!q{
735 auto he = gethostbyname(param.tempCString());
736 }(name);
741 * Resolve IPv4 address number.
743 * Params:
744 * addr = The IPv4 address to resolve, in host byte order.
745 * Returns:
746 * false if unable to resolve.
748 bool getHostByAddr(uint addr) @trusted
750 return getHost!q{
751 auto x = htonl(param);
752 auto he = gethostbyaddr(&x, 4, cast(int) AddressFamily.INET);
753 }(addr);
757 * Same as previous, but addr is an IPv4 address string in the
758 * dotted-decimal form $(I a.b.c.d).
759 * Returns: false if unable to resolve.
761 bool getHostByAddr(scope const(char)[] addr) @trusted
763 return getHost!q{
764 auto x = inet_addr(param.tempCString());
765 enforce(x != INADDR_NONE,
766 new SocketParameterException("Invalid IPv4 address"));
767 auto he = gethostbyaddr(&x, 4, cast(int) AddressFamily.INET);
768 }(addr);
773 @safe unittest
775 InternetHost ih = new InternetHost;
777 ih.getHostByAddr(0x7F_00_00_01);
778 assert(ih.addrList[0] == 0x7F_00_00_01);
779 ih.getHostByAddr("127.0.0.1");
780 assert(ih.addrList[0] == 0x7F_00_00_01);
782 if (!ih.getHostByName("www.digitalmars.com"))
783 return; // don't fail if not connected to internet
785 assert(ih.addrList.length);
786 InternetAddress ia = new InternetAddress(ih.addrList[0], InternetAddress.PORT_ANY);
787 assert(ih.name == "www.digitalmars.com" || ih.name == "digitalmars.com",
788 ih.name);
790 /* The following assert randomly fails in the test suite.
791 * https://issues.dlang.org/show_bug.cgi?id=22791
792 * So just ignore it when it fails.
794 //assert(ih.getHostByAddr(ih.addrList[0]));
795 if (ih.getHostByAddr(ih.addrList[0]))
797 string getHostNameFromInt = ih.name.dup;
799 assert(ih.getHostByAddr(ia.toAddrString()));
800 string getHostNameFromStr = ih.name.dup;
802 assert(getHostNameFromInt == getHostNameFromStr);
807 /// Holds information about a socket _address retrieved by `getAddressInfo`.
808 struct AddressInfo
810 AddressFamily family; /// Address _family
811 SocketType type; /// Socket _type
812 ProtocolType protocol; /// Protocol
813 Address address; /// Socket _address
814 string canonicalName; /// Canonical name, when `AddressInfoFlags.CANONNAME` is used.
818 * A subset of flags supported on all platforms with getaddrinfo.
819 * Specifies option flags for `getAddressInfo`.
821 enum AddressInfoFlags: int
823 /// The resulting addresses will be used in a call to `Socket.bind`.
824 PASSIVE = AI_PASSIVE,
826 /// The canonical name is returned in `canonicalName` member in the first `AddressInfo`.
827 CANONNAME = AI_CANONNAME,
830 * The `node` parameter passed to `getAddressInfo` must be a numeric string.
831 * This will suppress any potentially lengthy network host address lookups.
833 NUMERICHOST = AI_NUMERICHOST,
838 * On POSIX, getaddrinfo uses its own error codes, and thus has its own
839 * formatting function.
841 private string formatGaiError(int err) @trusted
843 version (Windows)
845 return generateSysErrorMsg(err);
847 else
849 synchronized
850 return to!string(gai_strerror(err));
855 * Provides _protocol-independent translation from host names to socket
856 * addresses. If advanced functionality is not required, consider using
857 * `getAddress` for compatibility with older systems.
859 * Returns: Array with one `AddressInfo` per socket address.
861 * Throws: `SocketOSException` on failure, or `SocketFeatureException`
862 * if this functionality is not available on the current system.
864 * Params:
865 * node = string containing host name or numeric address
866 * options = optional additional parameters, identified by type:
867 * $(UL $(LI `string` - service name or port number)
868 * $(LI `AddressInfoFlags` - option flags)
869 * $(LI `AddressFamily` - address family to filter by)
870 * $(LI `SocketType` - socket type to filter by)
871 * $(LI `ProtocolType` - protocol to filter by))
873 * Example:
874 * ---
875 * // Roundtrip DNS resolution
876 * auto results = getAddressInfo("www.digitalmars.com");
877 * assert(results[0].address.toHostNameString() ==
878 * "digitalmars.com");
880 * // Canonical name
881 * results = getAddressInfo("www.digitalmars.com",
882 * AddressInfoFlags.CANONNAME);
883 * assert(results[0].canonicalName == "digitalmars.com");
885 * // IPv6 resolution
886 * results = getAddressInfo("ipv6.google.com");
887 * assert(results[0].family == AddressFamily.INET6);
889 * // Multihomed resolution
890 * results = getAddressInfo("google.com");
891 * assert(results.length > 1);
893 * // Parsing IPv4
894 * results = getAddressInfo("127.0.0.1",
895 * AddressInfoFlags.NUMERICHOST);
896 * assert(results.length && results[0].family ==
897 * AddressFamily.INET);
899 * // Parsing IPv6
900 * results = getAddressInfo("::1",
901 * AddressInfoFlags.NUMERICHOST);
902 * assert(results.length && results[0].family ==
903 * AddressFamily.INET6);
904 * ---
906 AddressInfo[] getAddressInfo(T...)(scope const(char)[] node, scope T options)
908 const(char)[] service = null;
909 addrinfo hints;
910 hints.ai_family = AF_UNSPEC;
912 foreach (i, option; options)
914 static if (is(typeof(option) : const(char)[]))
915 service = options[i];
916 else
917 static if (is(typeof(option) == AddressInfoFlags))
918 hints.ai_flags |= option;
919 else
920 static if (is(typeof(option) == AddressFamily))
921 hints.ai_family = option;
922 else
923 static if (is(typeof(option) == SocketType))
924 hints.ai_socktype = option;
925 else
926 static if (is(typeof(option) == ProtocolType))
927 hints.ai_protocol = option;
928 else
929 static assert(0, "Unknown getAddressInfo option type: " ~ typeof(option).stringof);
932 return () @trusted { return getAddressInfoImpl(node, service, &hints); }();
935 @system unittest
937 struct Oops
939 const(char[]) breakSafety()
941 *cast(int*) 0xcafebabe = 0xdeadbeef;
942 return null;
944 alias breakSafety this;
946 assert(!__traits(compiles, () {
947 getAddressInfo("", Oops.init);
948 }), "getAddressInfo breaks @safe");
951 private AddressInfo[] getAddressInfoImpl(scope const(char)[] node, scope const(char)[] service, addrinfo* hints) @system
953 import std.array : appender;
955 if (getaddrinfoPointer && freeaddrinfoPointer)
957 addrinfo* ai_res;
959 int ret = getaddrinfoPointer(
960 node.tempCString(),
961 service.tempCString(),
962 hints, &ai_res);
963 enforce(ret == 0, new SocketOSException("getaddrinfo error", ret, &formatGaiError));
964 scope(exit) freeaddrinfoPointer(ai_res);
966 auto result = appender!(AddressInfo[])();
968 // Use const to force UnknownAddressReference to copy the sockaddr.
969 for (const(addrinfo)* ai = ai_res; ai; ai = ai.ai_next)
970 result ~= AddressInfo(
971 cast(AddressFamily) ai.ai_family,
972 cast(SocketType ) ai.ai_socktype,
973 cast(ProtocolType ) ai.ai_protocol,
974 new UnknownAddressReference(ai.ai_addr, cast(socklen_t) ai.ai_addrlen),
975 ai.ai_canonname ? to!string(ai.ai_canonname) : null);
977 assert(result.data.length > 0);
978 return result.data;
981 throw new SocketFeatureException("Address info lookup is not available " ~
982 "on this system.");
986 @safe unittest
988 softUnittest({
989 if (getaddrinfoPointer)
991 // Roundtrip DNS resolution
992 auto results = getAddressInfo("www.digitalmars.com");
993 assert(results[0].address.toHostNameString() == "digitalmars.com");
995 // Canonical name
996 results = getAddressInfo("www.digitalmars.com",
997 AddressInfoFlags.CANONNAME);
998 assert(results[0].canonicalName == "digitalmars.com");
1000 // IPv6 resolution
1001 //results = getAddressInfo("ipv6.google.com");
1002 //assert(results[0].family == AddressFamily.INET6);
1004 // Multihomed resolution
1005 //results = getAddressInfo("google.com");
1006 //assert(results.length > 1);
1008 // Parsing IPv4
1009 results = getAddressInfo("127.0.0.1", AddressInfoFlags.NUMERICHOST);
1010 assert(results.length && results[0].family == AddressFamily.INET);
1012 // Parsing IPv6
1013 results = getAddressInfo("::1", AddressInfoFlags.NUMERICHOST);
1014 assert(results.length && results[0].family == AddressFamily.INET6);
1018 if (getaddrinfoPointer)
1020 auto results = getAddressInfo(null, "1234", AddressInfoFlags.PASSIVE,
1021 SocketType.STREAM, ProtocolType.TCP, AddressFamily.INET);
1022 assert(results.length == 1 && results[0].address.toString() == "0.0.0.0:1234");
1027 private ushort serviceToPort(scope const(char)[] service)
1029 if (service == "")
1030 return InternetAddress.PORT_ANY;
1031 else
1032 if (isNumeric(service))
1033 return to!ushort(service);
1034 else
1036 auto s = new Service();
1037 s.getServiceByName(service);
1038 return s.port;
1043 * Provides _protocol-independent translation from host names to socket
1044 * addresses. Uses `getAddressInfo` if the current system supports it,
1045 * and `InternetHost` otherwise.
1047 * Returns: Array with one `Address` instance per socket address.
1049 * Throws: `SocketOSException` on failure.
1051 * Example:
1052 * ---
1053 * writeln("Resolving www.digitalmars.com:");
1054 * try
1056 * auto addresses = getAddress("www.digitalmars.com");
1057 * foreach (address; addresses)
1058 * writefln(" IP: %s", address.toAddrString());
1060 * catch (SocketException e)
1061 * writefln(" Lookup failed: %s", e.msg);
1062 * ---
1064 Address[] getAddress(scope const(char)[] hostname, scope const(char)[] service = null)
1066 if (getaddrinfoPointer && freeaddrinfoPointer)
1068 // use getAddressInfo
1069 auto infos = getAddressInfo(hostname, service);
1070 Address[] results;
1071 results.length = infos.length;
1072 foreach (i, ref result; results)
1073 result = infos[i].address;
1074 return results;
1076 else
1077 return getAddress(hostname, serviceToPort(service));
1080 /// ditto
1081 Address[] getAddress(scope const(char)[] hostname, ushort port)
1083 if (getaddrinfoPointer && freeaddrinfoPointer)
1084 return getAddress(hostname, to!string(port));
1085 else
1087 // use getHostByName
1088 auto ih = new InternetHost;
1089 if (!ih.getHostByName(hostname))
1090 throw new AddressException(
1091 text("Unable to resolve host '", hostname, "'"));
1093 Address[] results;
1094 foreach (uint addr; ih.addrList)
1095 results ~= new InternetAddress(addr, port);
1096 return results;
1101 @safe unittest
1103 softUnittest({
1104 auto addresses = getAddress("63.105.9.61");
1105 assert(addresses.length && addresses[0].toAddrString() == "63.105.9.61");
1107 if (getaddrinfoPointer)
1109 // test via gethostbyname
1110 auto getaddrinfoPointerBackup = getaddrinfoPointer;
1111 cast() getaddrinfoPointer = null;
1112 scope(exit) cast() getaddrinfoPointer = getaddrinfoPointerBackup;
1114 addresses = getAddress("63.105.9.61");
1115 assert(addresses.length && addresses[0].toAddrString() == "63.105.9.61");
1122 * Provides _protocol-independent parsing of network addresses. Does not
1123 * attempt name resolution. Uses `getAddressInfo` with
1124 * `AddressInfoFlags.NUMERICHOST` if the current system supports it, and
1125 * `InternetAddress` otherwise.
1127 * Returns: An `Address` instance representing specified address.
1129 * Throws: `SocketException` on failure.
1131 * Example:
1132 * ---
1133 * writeln("Enter IP address:");
1134 * string ip = readln().chomp();
1135 * try
1137 * Address address = parseAddress(ip);
1138 * writefln("Looking up reverse of %s:",
1139 * address.toAddrString());
1140 * try
1142 * string reverse = address.toHostNameString();
1143 * if (reverse)
1144 * writefln(" Reverse name: %s", reverse);
1145 * else
1146 * writeln(" Reverse hostname not found.");
1148 * catch (SocketException e)
1149 * writefln(" Lookup error: %s", e.msg);
1151 * catch (SocketException e)
1153 * writefln(" %s is not a valid IP address: %s",
1154 * ip, e.msg);
1156 * ---
1158 Address parseAddress(scope const(char)[] hostaddr, scope const(char)[] service = null)
1160 if (getaddrinfoPointer && freeaddrinfoPointer)
1161 return getAddressInfo(hostaddr, service, AddressInfoFlags.NUMERICHOST)[0].address;
1162 else
1163 return parseAddress(hostaddr, serviceToPort(service));
1166 /// ditto
1167 Address parseAddress(scope const(char)[] hostaddr, ushort port)
1169 if (getaddrinfoPointer && freeaddrinfoPointer)
1170 return parseAddress(hostaddr, to!string(port));
1171 else
1173 auto in4_addr = InternetAddress.parse(hostaddr);
1174 enforce(in4_addr != InternetAddress.ADDR_NONE,
1175 new SocketParameterException("Invalid IP address"));
1176 return new InternetAddress(in4_addr, port);
1181 @safe unittest
1183 softUnittest({
1184 auto address = parseAddress("63.105.9.61");
1185 assert(address.toAddrString() == "63.105.9.61");
1187 if (getaddrinfoPointer)
1189 // test via inet_addr
1190 auto getaddrinfoPointerBackup = getaddrinfoPointer;
1191 cast() getaddrinfoPointer = null;
1192 scope(exit) cast() getaddrinfoPointer = getaddrinfoPointerBackup;
1194 address = parseAddress("63.105.9.61");
1195 assert(address.toAddrString() == "63.105.9.61");
1198 assert(collectException!SocketException(parseAddress("Invalid IP address")));
1204 * Class for exceptions thrown from an `Address`.
1206 class AddressException: SocketOSException
1208 mixin socketOSExceptionCtors;
1213 * `Address` is an abstract class for representing a socket addresses.
1215 * Example:
1216 * ---
1217 * writeln("About www.google.com port 80:");
1218 * try
1220 * Address[] addresses = getAddress("www.google.com", 80);
1221 * writefln(" %d addresses found.", addresses.length);
1222 * foreach (int i, Address a; addresses)
1224 * writefln(" Address %d:", i+1);
1225 * writefln(" IP address: %s", a.toAddrString());
1226 * writefln(" Hostname: %s", a.toHostNameString());
1227 * writefln(" Port: %s", a.toPortString());
1228 * writefln(" Service name: %s",
1229 * a.toServiceNameString());
1232 * catch (SocketException e)
1233 * writefln(" Lookup error: %s", e.msg);
1234 * ---
1236 abstract class Address
1238 /// Returns pointer to underlying `sockaddr` structure.
1239 abstract @property sockaddr* name() pure nothrow @nogc;
1240 abstract @property const(sockaddr)* name() const pure nothrow @nogc; /// ditto
1242 /// Returns actual size of underlying `sockaddr` structure.
1243 abstract @property socklen_t nameLen() const pure nothrow @nogc;
1245 // Socket.remoteAddress, Socket.localAddress, and Socket.receiveFrom
1246 // use setNameLen to set the actual size of the address as returned by
1247 // getsockname, getpeername, and recvfrom, respectively.
1248 // The following implementation is sufficient for fixed-length addresses,
1249 // and ensures that the length is not changed.
1250 // Must be overridden for variable-length addresses.
1251 protected void setNameLen(socklen_t len)
1253 if (len != this.nameLen)
1254 throw new AddressException(
1255 format("%s expects address of length %d, not %d", typeid(this),
1256 this.nameLen, len), 0);
1259 /// Family of this address.
1260 @property AddressFamily addressFamily() const pure nothrow @nogc
1262 return cast(AddressFamily) name.sa_family;
1265 // Common code for toAddrString and toHostNameString
1266 private string toHostString(bool numeric) @trusted const
1268 // getnameinfo() is the recommended way to perform a reverse (name)
1269 // lookup on both Posix and Windows. However, it is only available
1270 // on Windows XP and above, and not included with the WinSock import
1271 // libraries shipped with DMD. Thus, we check for getnameinfo at
1272 // runtime in the shared module constructor, and use it if it's
1273 // available in the base class method. Classes for specific network
1274 // families (e.g. InternetHost) override this method and use a
1275 // deprecated, albeit commonly-available method when getnameinfo()
1276 // is not available.
1277 // http://technet.microsoft.com/en-us/library/aa450403.aspx
1278 if (getnameinfoPointer)
1280 auto buf = new char[NI_MAXHOST];
1281 auto ret = getnameinfoPointer(
1282 name, nameLen,
1283 buf.ptr, cast(uint) buf.length,
1284 null, 0,
1285 numeric ? NI_NUMERICHOST : NI_NAMEREQD);
1287 if (!numeric)
1289 if (ret == EAI_NONAME)
1290 return null;
1291 version (Windows)
1292 if (ret == WSANO_DATA)
1293 return null;
1296 enforce(ret == 0, new AddressException("Could not get " ~
1297 (numeric ? "host address" : "host name")));
1298 return assumeUnique(buf[0 .. strlen(buf.ptr)]);
1301 throw new SocketFeatureException((numeric ? "Host address" : "Host name") ~
1302 " lookup for this address family is not available on this system.");
1305 // Common code for toPortString and toServiceNameString
1306 private string toServiceString(bool numeric) @trusted const
1308 // See toHostNameString() for details about getnameinfo().
1309 if (getnameinfoPointer)
1311 auto buf = new char[NI_MAXSERV];
1312 enforce(getnameinfoPointer(
1313 name, nameLen,
1314 null, 0,
1315 buf.ptr, cast(uint) buf.length,
1316 numeric ? NI_NUMERICSERV : NI_NAMEREQD
1317 ) == 0, new AddressException("Could not get " ~
1318 (numeric ? "port number" : "service name")));
1319 return assumeUnique(buf[0 .. strlen(buf.ptr)]);
1322 throw new SocketFeatureException((numeric ? "Port number" : "Service name") ~
1323 " lookup for this address family is not available on this system.");
1327 * Attempts to retrieve the host address as a human-readable string.
1329 * Throws: `AddressException` on failure, or `SocketFeatureException`
1330 * if address retrieval for this address family is not available on the
1331 * current system.
1333 string toAddrString() const
1335 return toHostString(true);
1339 * Attempts to retrieve the host name as a fully qualified domain name.
1341 * Returns: The FQDN corresponding to this `Address`, or `null` if
1342 * the host name did not resolve.
1344 * Throws: `AddressException` on error, or `SocketFeatureException`
1345 * if host name lookup for this address family is not available on the
1346 * current system.
1348 string toHostNameString() const
1350 return toHostString(false);
1354 * Attempts to retrieve the numeric port number as a string.
1356 * Throws: `AddressException` on failure, or `SocketFeatureException`
1357 * if port number retrieval for this address family is not available on the
1358 * current system.
1360 string toPortString() const
1362 return toServiceString(true);
1366 * Attempts to retrieve the service name as a string.
1368 * Throws: `AddressException` on failure, or `SocketFeatureException`
1369 * if service name lookup for this address family is not available on the
1370 * current system.
1372 string toServiceNameString() const
1374 return toServiceString(false);
1377 /// Human readable string representing this address.
1378 override string toString() const
1382 string host = toAddrString();
1383 string port = toPortString();
1384 if (host.indexOf(':') >= 0)
1385 return "[" ~ host ~ "]:" ~ port;
1386 else
1387 return host ~ ":" ~ port;
1389 catch (SocketException)
1390 return "Unknown";
1395 * `UnknownAddress` encapsulates an unknown socket address.
1397 class UnknownAddress: Address
1399 protected:
1400 sockaddr sa;
1403 public:
1404 override @property sockaddr* name() return
1406 return &sa;
1409 override @property const(sockaddr)* name() const return
1411 return &sa;
1415 override @property socklen_t nameLen() const
1417 return cast(socklen_t) sa.sizeof;
1424 * `UnknownAddressReference` encapsulates a reference to an arbitrary
1425 * socket address.
1427 class UnknownAddressReference: Address
1429 protected:
1430 sockaddr* sa;
1431 socklen_t len;
1433 public:
1434 /// Constructs an `Address` with a reference to the specified `sockaddr`.
1435 this(sockaddr* sa, socklen_t len) pure nothrow @nogc
1437 this.sa = sa;
1438 this.len = len;
1441 /// Constructs an `Address` with a copy of the specified `sockaddr`.
1442 this(const(sockaddr)* sa, socklen_t len) @system pure nothrow
1444 this.sa = cast(sockaddr*) (cast(ubyte*) sa)[0 .. len].dup.ptr;
1445 this.len = len;
1448 override @property sockaddr* name()
1450 return sa;
1453 override @property const(sockaddr)* name() const
1455 return sa;
1459 override @property socklen_t nameLen() const
1461 return cast(socklen_t) len;
1467 * `InternetAddress` encapsulates an IPv4 (Internet Protocol version 4)
1468 * socket address.
1470 * Consider using `getAddress`, `parseAddress` and `Address` methods
1471 * instead of using this class directly.
1473 class InternetAddress: Address
1475 protected:
1476 sockaddr_in sin;
1479 this() pure nothrow @nogc
1484 public:
1485 override @property sockaddr* name() return
1487 return cast(sockaddr*)&sin;
1490 override @property const(sockaddr)* name() const return
1492 return cast(const(sockaddr)*)&sin;
1496 override @property socklen_t nameLen() const
1498 return cast(socklen_t) sin.sizeof;
1502 enum uint ADDR_ANY = INADDR_ANY; /// Any IPv4 host address.
1503 enum uint ADDR_NONE = INADDR_NONE; /// An invalid IPv4 host address.
1504 enum ushort PORT_ANY = 0; /// Any IPv4 port number.
1506 /// Returns the IPv4 _port number (in host byte order).
1507 @property ushort port() const pure nothrow @nogc
1509 return ntohs(sin.sin_port);
1512 /// Returns the IPv4 address number (in host byte order).
1513 @property uint addr() const pure nothrow @nogc
1515 return ntohl(sin.sin_addr.s_addr);
1519 * Construct a new `InternetAddress`.
1520 * Params:
1521 * addr = an IPv4 address string in the dotted-decimal form a.b.c.d,
1522 * or a host name which will be resolved using an `InternetHost`
1523 * object.
1524 * port = port number, may be `PORT_ANY`.
1526 this(scope const(char)[] addr, ushort port)
1528 uint uiaddr = parse(addr);
1529 if (ADDR_NONE == uiaddr)
1531 InternetHost ih = new InternetHost;
1532 if (!ih.getHostByName(addr))
1533 //throw new AddressException("Invalid internet address");
1534 throw new AddressException(
1535 text("Unable to resolve host '", addr, "'"));
1536 uiaddr = ih.addrList[0];
1538 sin.sin_family = AddressFamily.INET;
1539 sin.sin_addr.s_addr = htonl(uiaddr);
1540 sin.sin_port = htons(port);
1544 * Construct a new `InternetAddress`.
1545 * Params:
1546 * addr = (optional) an IPv4 address in host byte order, may be `ADDR_ANY`.
1547 * port = port number, may be `PORT_ANY`.
1549 this(uint addr, ushort port) pure nothrow @nogc
1551 sin.sin_family = AddressFamily.INET;
1552 sin.sin_addr.s_addr = htonl(addr);
1553 sin.sin_port = htons(port);
1556 /// ditto
1557 this(ushort port) pure nothrow @nogc
1559 sin.sin_family = AddressFamily.INET;
1560 sin.sin_addr.s_addr = ADDR_ANY;
1561 sin.sin_port = htons(port);
1565 * Construct a new `InternetAddress`.
1566 * Params:
1567 * addr = A sockaddr_in as obtained from lower-level API calls such as getifaddrs.
1569 this(sockaddr_in addr) pure nothrow @nogc
1571 assert(addr.sin_family == AddressFamily.INET, "Socket address is not of INET family.");
1572 sin = addr;
1575 /// Human readable string representing the IPv4 address in dotted-decimal form.
1576 override string toAddrString() @trusted const
1578 return to!string(inet_ntoa(sin.sin_addr));
1581 /// Human readable string representing the IPv4 port.
1582 override string toPortString() const
1584 return std.conv.to!string(port);
1588 * Attempts to retrieve the host name as a fully qualified domain name.
1590 * Returns: The FQDN corresponding to this `InternetAddress`, or
1591 * `null` if the host name did not resolve.
1593 * Throws: `AddressException` on error.
1595 override string toHostNameString() const
1597 // getnameinfo() is the recommended way to perform a reverse (name)
1598 // lookup on both Posix and Windows. However, it is only available
1599 // on Windows XP and above, and not included with the WinSock import
1600 // libraries shipped with DMD. Thus, we check for getnameinfo at
1601 // runtime in the shared module constructor, and fall back to the
1602 // deprecated getHostByAddr() if it could not be found. See also:
1603 // http://technet.microsoft.com/en-us/library/aa450403.aspx
1605 if (getnameinfoPointer)
1606 return super.toHostNameString();
1607 else
1609 auto host = new InternetHost();
1610 if (!host.getHostByAddr(ntohl(sin.sin_addr.s_addr)))
1611 return null;
1612 return host.name;
1617 * Compares with another InternetAddress of same type for equality
1618 * Returns: true if the InternetAddresses share the same address and
1619 * port number.
1621 override bool opEquals(Object o) const
1623 auto other = cast(InternetAddress) o;
1624 return other && this.sin.sin_addr.s_addr == other.sin.sin_addr.s_addr &&
1625 this.sin.sin_port == other.sin.sin_port;
1629 @system unittest
1631 auto addr1 = new InternetAddress("127.0.0.1", 80);
1632 auto addr2 = new InternetAddress("127.0.0.2", 80);
1634 assert(addr1 == addr1);
1635 assert(addr1 != addr2);
1639 * Parse an IPv4 address string in the dotted-decimal form $(I a.b.c.d)
1640 * and return the number.
1641 * Returns: If the string is not a legitimate IPv4 address,
1642 * `ADDR_NONE` is returned.
1644 static uint parse(scope const(char)[] addr) @trusted nothrow
1646 return ntohl(inet_addr(addr.tempCString()));
1650 * Convert an IPv4 address number in host byte order to a human readable
1651 * string representing the IPv4 address in dotted-decimal form.
1653 static string addrToString(uint addr) @trusted nothrow
1655 in_addr sin_addr;
1656 sin_addr.s_addr = htonl(addr);
1657 return to!string(inet_ntoa(sin_addr));
1662 @safe unittest
1664 softUnittest({
1665 const InternetAddress ia = new InternetAddress("63.105.9.61", 80);
1666 assert(ia.toString() == "63.105.9.61:80");
1669 softUnittest({
1670 // test construction from a sockaddr_in
1671 sockaddr_in sin;
1673 sin.sin_addr.s_addr = htonl(0x7F_00_00_01); // 127.0.0.1
1674 sin.sin_family = AddressFamily.INET;
1675 sin.sin_port = htons(80);
1677 const InternetAddress ia = new InternetAddress(sin);
1678 assert(ia.toString() == "127.0.0.1:80");
1681 softUnittest({
1682 // test reverse lookup
1683 auto ih = new InternetHost;
1684 if (ih.getHostByName("digitalmars.com"))
1686 const ia = new InternetAddress(ih.addrList[0], 80);
1687 assert(ia.toHostNameString() == "digitalmars.com");
1689 if (getnameinfoPointer)
1691 // test reverse lookup, via gethostbyaddr
1692 auto getnameinfoPointerBackup = getnameinfoPointer;
1693 cast() getnameinfoPointer = null;
1694 scope(exit) cast() getnameinfoPointer = getnameinfoPointerBackup;
1696 assert(ia.toHostNameString() == "digitalmars.com");
1701 debug (std_socket)
1702 softUnittest({
1703 // test failing reverse lookup
1704 const InternetAddress ia = new InternetAddress("255.255.255.255", 80);
1705 assert(ia.toHostNameString() is null);
1707 if (getnameinfoPointer)
1709 // test failing reverse lookup, via gethostbyaddr
1710 auto getnameinfoPointerBackup = getnameinfoPointer;
1711 cast() getnameinfoPointer = null;
1712 scope(exit) cast() getnameinfoPointer = getnameinfoPointerBackup;
1714 assert(ia.toHostNameString() is null);
1721 * `Internet6Address` encapsulates an IPv6 (Internet Protocol version 6)
1722 * socket address.
1724 * Consider using `getAddress`, `parseAddress` and `Address` methods
1725 * instead of using this class directly.
1727 class Internet6Address: Address
1729 protected:
1730 sockaddr_in6 sin6;
1733 this() pure nothrow @nogc
1738 public:
1739 override @property sockaddr* name() return
1741 return cast(sockaddr*)&sin6;
1744 override @property const(sockaddr)* name() const return
1746 return cast(const(sockaddr)*)&sin6;
1750 override @property socklen_t nameLen() const
1752 return cast(socklen_t) sin6.sizeof;
1756 /// Any IPv6 host address.
1757 static @property ref const(ubyte)[16] ADDR_ANY() pure nothrow @nogc
1759 static if (is(typeof(IN6ADDR_ANY)))
1761 version (Windows)
1763 static immutable addr = IN6ADDR_ANY.s6_addr;
1764 return addr;
1766 else
1767 return IN6ADDR_ANY.s6_addr;
1769 else static if (is(typeof(in6addr_any)))
1771 return in6addr_any.s6_addr;
1773 else
1774 static assert(0);
1777 /// Any IPv6 port number.
1778 enum ushort PORT_ANY = 0;
1780 /// Returns the IPv6 port number.
1781 @property ushort port() const pure nothrow @nogc
1783 return ntohs(sin6.sin6_port);
1786 /// Returns the IPv6 address.
1787 @property ubyte[16] addr() const pure nothrow @nogc
1789 return sin6.sin6_addr.s6_addr;
1793 * Construct a new `Internet6Address`.
1794 * Params:
1795 * addr = an IPv6 host address string in the form described in RFC 2373,
1796 * or a host name which will be resolved using `getAddressInfo`.
1797 * service = (optional) service name.
1799 this(scope const(char)[] addr, scope const(char)[] service = null) @trusted
1801 auto results = getAddressInfo(addr, service, AddressFamily.INET6);
1802 assert(results.length && results[0].family == AddressFamily.INET6);
1803 sin6 = *cast(sockaddr_in6*) results[0].address.name;
1807 * Construct a new `Internet6Address`.
1808 * Params:
1809 * addr = an IPv6 host address string in the form described in RFC 2373,
1810 * or a host name which will be resolved using `getAddressInfo`.
1811 * port = port number, may be `PORT_ANY`.
1813 this(scope const(char)[] addr, ushort port)
1815 if (port == PORT_ANY)
1816 this(addr);
1817 else
1818 this(addr, to!string(port));
1822 * Construct a new `Internet6Address`.
1823 * Params:
1824 * addr = (optional) an IPv6 host address in host byte order, or
1825 * `ADDR_ANY`.
1826 * port = port number, may be `PORT_ANY`.
1828 this(ubyte[16] addr, ushort port) pure nothrow @nogc
1830 sin6.sin6_family = AddressFamily.INET6;
1831 sin6.sin6_addr.s6_addr = addr;
1832 sin6.sin6_port = htons(port);
1835 /// ditto
1836 this(ushort port) pure nothrow @nogc
1838 sin6.sin6_family = AddressFamily.INET6;
1839 sin6.sin6_addr.s6_addr = ADDR_ANY;
1840 sin6.sin6_port = htons(port);
1844 * Construct a new `Internet6Address`.
1845 * Params:
1846 * addr = A sockaddr_in6 as obtained from lower-level API calls such as getifaddrs.
1848 this(sockaddr_in6 addr) pure nothrow @nogc
1850 assert(addr.sin6_family == AddressFamily.INET6);
1851 sin6 = addr;
1855 * Parse an IPv6 host address string as described in RFC 2373, and return the
1856 * address.
1857 * Throws: `SocketException` on error.
1859 static ubyte[16] parse(scope const(char)[] addr) @trusted
1861 // Although we could use inet_pton here, it's only available on Windows
1862 // versions starting with Vista, so use getAddressInfo with NUMERICHOST
1863 // instead.
1864 auto results = getAddressInfo(addr, AddressInfoFlags.NUMERICHOST);
1865 if (results.length && results[0].family == AddressFamily.INET6)
1866 return (cast(sockaddr_in6*) results[0].address.name).sin6_addr.s6_addr;
1867 throw new AddressException("Not an IPv6 address", 0);
1872 @safe unittest
1874 softUnittest({
1875 const Internet6Address ia = new Internet6Address("::1", 80);
1876 assert(ia.toString() == "[::1]:80");
1879 softUnittest({
1880 // test construction from a sockaddr_in6
1881 sockaddr_in6 sin;
1883 sin.sin6_addr.s6_addr = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]; // [::1]
1884 sin.sin6_family = AddressFamily.INET6;
1885 sin.sin6_port = htons(80);
1887 const Internet6Address ia = new Internet6Address(sin);
1888 assert(ia.toString() == "[::1]:80");
1893 version (StdDdoc)
1895 static if (!is(sockaddr_un))
1897 // This exists only to allow the constructor taking
1898 // a sockaddr_un to be compilable for documentation
1899 // on platforms that don't supply a sockaddr_un.
1900 struct sockaddr_un
1906 * `UnixAddress` encapsulates an address for a Unix domain socket
1907 * (`AF_UNIX`), i.e. a socket bound to a path name in the file system.
1908 * Available only on supported systems.
1910 * Linux also supports an abstract address namespace, in which addresses
1911 * are independent of the file system. A socket address is abstract
1912 * iff `path` starts with a _null byte (`'\0'`). Null bytes in other
1913 * positions of an abstract address are allowed and have no special
1914 * meaning.
1916 * Example:
1917 * ---
1918 * auto addr = new UnixAddress("/var/run/dbus/system_bus_socket");
1919 * auto abstractAddr = new UnixAddress("\0/tmp/dbus-OtHLWmCLPR");
1920 * ---
1922 * See_Also: $(HTTP http://man7.org/linux/man-pages/man7/unix.7.html, UNIX(7))
1924 class UnixAddress: Address
1926 private this() pure nothrow @nogc {}
1928 /// Construct a new `UnixAddress` from the specified path.
1929 this(scope const(char)[] path) { }
1932 * Construct a new `UnixAddress`.
1933 * Params:
1934 * addr = A sockaddr_un as obtained from lower-level API calls.
1936 this(sockaddr_un addr) pure nothrow @nogc { }
1938 /// Get the underlying _path.
1939 @property string path() const { return null; }
1941 /// ditto
1942 override string toString() const { return null; }
1944 override @property sockaddr* name() { return null; }
1945 override @property const(sockaddr)* name() const { return null; }
1946 override @property socklen_t nameLen() const { return 0; }
1949 else
1950 static if (is(sockaddr_un))
1952 class UnixAddress: Address
1954 protected:
1955 socklen_t _nameLen;
1957 struct
1959 align (1):
1960 sockaddr_un sun;
1961 char unused = '\0'; // placeholder for a terminating '\0'
1964 this() pure nothrow @nogc
1966 sun.sun_family = AddressFamily.UNIX;
1967 sun.sun_path = '?';
1968 _nameLen = sun.sizeof;
1971 override void setNameLen(socklen_t len) @trusted
1973 if (len > sun.sizeof)
1974 throw new SocketParameterException("Not enough socket address storage");
1975 _nameLen = len;
1978 public:
1979 override @property sockaddr* name() return
1981 return cast(sockaddr*)&sun;
1984 override @property const(sockaddr)* name() const return
1986 return cast(const(sockaddr)*)&sun;
1989 override @property socklen_t nameLen() @trusted const
1991 return _nameLen;
1994 this(scope const(char)[] path) @trusted pure
1996 enforce(path.length <= sun.sun_path.sizeof, new SocketParameterException("Path too long"));
1997 sun.sun_family = AddressFamily.UNIX;
1998 sun.sun_path.ptr[0 .. path.length] = (cast(byte[]) path)[];
1999 _nameLen = cast(socklen_t)
2001 auto len = sockaddr_un.init.sun_path.offsetof + path.length;
2002 // Pathname socket address must be terminated with '\0'
2003 // which must be included in the address length.
2004 if (sun.sun_path.ptr[0])
2006 sun.sun_path.ptr[path.length] = 0;
2007 ++len;
2009 return len;
2010 }();
2013 this(sockaddr_un addr) pure nothrow @nogc
2015 assert(addr.sun_family == AddressFamily.UNIX);
2016 sun = addr;
2019 @property string path() @trusted const pure
2021 auto len = _nameLen - sockaddr_un.init.sun_path.offsetof;
2022 if (len == 0)
2023 return null; // An empty path may be returned from getpeername
2024 // For pathname socket address we need to strip off the terminating '\0'
2025 if (sun.sun_path.ptr[0])
2026 --len;
2027 return (cast(const(char)*) sun.sun_path.ptr)[0 .. len].idup;
2030 override string toString() const pure
2032 return path;
2036 @safe unittest
2038 import core.stdc.stdio : remove;
2040 version (iOSDerived)
2042 // Slightly different version of `std.file.deleteme` to reduce the path
2043 // length on iOS derived platforms. Due to the sandbox, the length
2044 // of paths can quickly become too long.
2045 static string deleteme()
2047 import std.conv : text;
2048 import std.process : thisProcessID;
2049 import std.file : tempDir;
2051 return text(tempDir, thisProcessID);
2055 else
2056 import std.file : deleteme;
2058 immutable ubyte[] data = [1, 2, 3, 4];
2059 Socket[2] pair;
2061 const basePath = deleteme;
2062 auto names = [ basePath ~ "-socket" ];
2063 version (linux)
2064 names ~= "\0" ~ basePath ~ "-abstract\0unix\0socket";
2066 foreach (name; names)
2068 auto address = new UnixAddress(name);
2070 auto listener = new Socket(AddressFamily.UNIX, SocketType.STREAM);
2071 scope(exit) listener.close();
2072 listener.bind(address);
2073 scope(exit) () @trusted { if (name[0]) remove(name.tempCString()); } ();
2074 assert(listener.localAddress.toString == name);
2076 listener.listen(1);
2078 pair[0] = new Socket(AddressFamily.UNIX, SocketType.STREAM);
2079 scope(exit) listener.close();
2081 pair[0].connect(address);
2082 scope(exit) pair[0].close();
2084 pair[1] = listener.accept();
2085 scope(exit) pair[1].close();
2087 pair[0].send(data);
2089 auto buf = new ubyte[data.length];
2090 pair[1].receive(buf);
2091 assert(buf == data);
2093 // getpeername is free to return an empty name for a unix
2094 // domain socket pair or unbound socket. Let's confirm it
2095 // returns successfully and doesn't throw anything.
2096 // See https://issues.dlang.org/show_bug.cgi?id=20544
2097 assertNotThrown(pair[1].remoteAddress().toString());
2104 * Class for exceptions thrown by `Socket.accept`.
2106 class SocketAcceptException: SocketOSException
2108 mixin socketOSExceptionCtors;
2111 /// How a socket is shutdown:
2112 enum SocketShutdown: int
2114 RECEIVE = SD_RECEIVE, /// socket receives are disallowed
2115 SEND = SD_SEND, /// socket sends are disallowed
2116 BOTH = SD_BOTH, /// both RECEIVE and SEND
2120 /// Flags may be OR'ed together:
2121 enum SocketFlags: int
2123 NONE = 0, /// no flags specified
2125 OOB = MSG_OOB, /// out-of-band stream data
2126 PEEK = MSG_PEEK, /// peek at incoming data without removing it from the queue, only for receiving
2127 DONTROUTE = MSG_DONTROUTE, /// data should not be subject to routing; this flag may be ignored. Only for sending
2131 /// Duration timeout value.
2132 struct TimeVal
2134 _ctimeval ctimeval;
2135 alias tv_sec_t = typeof(ctimeval.tv_sec);
2136 alias tv_usec_t = typeof(ctimeval.tv_usec);
2138 /// Number of _seconds.
2139 pure nothrow @nogc @property
2140 ref inout(tv_sec_t) seconds() inout return
2142 return ctimeval.tv_sec;
2145 /// Number of additional _microseconds.
2146 pure nothrow @nogc @property
2147 ref inout(tv_usec_t) microseconds() inout return
2149 return ctimeval.tv_usec;
2155 * A collection of sockets for use with `Socket.select`.
2157 * `SocketSet` wraps the platform `fd_set` type. However, unlike
2158 * `fd_set`, `SocketSet` is not statically limited to `FD_SETSIZE`
2159 * or any other limit, and grows as needed.
2161 class SocketSet
2163 private:
2164 version (Windows)
2166 // On Windows, fd_set is an array of socket handles,
2167 // following a word containing the fd_set instance size.
2168 // We use one dynamic array for everything, and use its first
2169 // element(s) for the count.
2171 alias fd_set_count_type = typeof(fd_set.init.fd_count);
2172 alias fd_set_type = typeof(fd_set.init.fd_array[0]);
2173 static assert(fd_set_type.sizeof == socket_t.sizeof);
2175 // Number of fd_set_type elements at the start of our array that are
2176 // used for the socket count and alignment
2178 enum FD_SET_OFFSET = fd_set.fd_array.offsetof / fd_set_type.sizeof;
2179 static assert(FD_SET_OFFSET);
2180 static assert(fd_set.fd_count.offsetof % fd_set_type.sizeof == 0);
2182 fd_set_type[] set;
2184 void resize(size_t size) pure nothrow
2186 set.length = FD_SET_OFFSET + size;
2189 ref inout(fd_set_count_type) count() @trusted @property inout pure nothrow @nogc
2191 assert(set.length);
2192 return *cast(inout(fd_set_count_type)*)set.ptr;
2195 size_t capacity() @property const pure nothrow @nogc
2197 return set.length - FD_SET_OFFSET;
2200 inout(socket_t)[] fds() @trusted inout @property pure nothrow @nogc
2202 return cast(inout(socket_t)[])set[FD_SET_OFFSET .. FD_SET_OFFSET+count];
2205 else
2206 version (Posix)
2208 // On Posix, fd_set is a bit array. We assume that the fd_set
2209 // type (declared in core.sys.posix.sys.select) is a structure
2210 // containing a single field, a static array.
2212 static assert(fd_set.tupleof.length == 1);
2214 // This is the type used in the fd_set array.
2215 // Using the type of the correct size is important for big-endian
2216 // architectures.
2218 alias fd_set_type = typeof(fd_set.init.tupleof[0][0]);
2220 // Number of file descriptors represented by one fd_set_type
2222 enum FD_NFDBITS = 8 * fd_set_type.sizeof;
2224 static fd_set_type mask(uint n) pure nothrow @nogc
2226 return (cast(fd_set_type) 1) << (n % FD_NFDBITS);
2229 // Array size to fit that many sockets
2231 static size_t lengthFor(size_t size) pure nothrow @nogc
2233 return (size + (FD_NFDBITS-1)) / FD_NFDBITS;
2236 fd_set_type[] set;
2238 void resize(size_t size) pure nothrow
2240 set.length = lengthFor(size);
2243 // Make sure we can fit that many sockets
2245 void setMinCapacity(size_t size) pure nothrow
2247 auto length = lengthFor(size);
2248 if (set.length < length)
2249 set.length = length;
2252 size_t capacity() @property const pure nothrow @nogc
2254 return set.length * FD_NFDBITS;
2257 int maxfd;
2259 else
2260 static assert(false, "Unknown platform");
2262 public:
2265 * Create a SocketSet with a specific initial capacity (defaults to
2266 * `FD_SETSIZE`, the system's default capacity).
2268 this(size_t size = FD_SETSIZE) pure nothrow
2270 resize(size);
2271 reset();
2274 /// Reset the `SocketSet` so that there are 0 `Socket`s in the collection.
2275 void reset() pure nothrow @nogc
2277 version (Windows)
2278 count = 0;
2279 else
2281 set[] = 0;
2282 maxfd = -1;
2287 void add(socket_t s) @trusted pure nothrow
2289 version (Windows)
2291 if (count == capacity)
2293 set.length *= 2;
2294 set.length = set.capacity;
2296 ++count;
2297 fds[$-1] = s;
2299 else
2301 auto index = s / FD_NFDBITS;
2302 auto length = set.length;
2303 if (index >= length)
2305 while (index >= length)
2306 length *= 2;
2307 set.length = length;
2308 set.length = set.capacity;
2310 set[index] |= mask(s);
2311 if (maxfd < s)
2312 maxfd = s;
2317 * Add a `Socket` to the collection.
2318 * The socket must not already be in the collection.
2320 void add(Socket s) pure nothrow
2322 add(s.sock);
2325 void remove(socket_t s) pure nothrow
2327 version (Windows)
2329 import std.algorithm.searching : countUntil;
2330 auto fds = fds;
2331 auto p = fds.countUntil(s);
2332 if (p >= 0)
2333 fds[p] = fds[--count];
2335 else
2337 auto index = s / FD_NFDBITS;
2338 if (index >= set.length)
2339 return;
2340 set[index] &= ~mask(s);
2341 // note: adjusting maxfd would require scanning the set, not worth it
2347 * Remove this `Socket` from the collection.
2348 * Does nothing if the socket is not in the collection already.
2350 void remove(Socket s) pure nothrow
2352 remove(s.sock);
2355 int isSet(socket_t s) const pure nothrow @nogc
2357 version (Windows)
2359 import std.algorithm.searching : canFind;
2360 return fds.canFind(s) ? 1 : 0;
2362 else
2364 if (s > maxfd)
2365 return 0;
2366 auto index = s / FD_NFDBITS;
2367 return (set[index] & mask(s)) ? 1 : 0;
2372 /// Return nonzero if this `Socket` is in the collection.
2373 int isSet(Socket s) const pure nothrow @nogc
2375 return isSet(s.sock);
2380 * Returns:
2381 * The current capacity of this `SocketSet`. The exact
2382 * meaning of the return value varies from platform to platform.
2384 * Note:
2385 * Since D 2.065, this value does not indicate a
2386 * restriction, and `SocketSet` will grow its capacity as
2387 * needed automatically.
2389 @property uint max() const pure nothrow @nogc
2391 return cast(uint) capacity;
2395 fd_set* toFd_set() @trusted pure nothrow @nogc
2397 return cast(fd_set*) set.ptr;
2401 int selectn() const pure nothrow @nogc
2403 version (Windows)
2405 return count;
2407 else version (Posix)
2409 return maxfd + 1;
2414 @safe unittest
2416 auto fds = cast(socket_t[])
2417 [cast(socket_t) 1, 2, 0, 1024, 17, 42, 1234, 77, 77+32, 77+64];
2418 auto set = new SocketSet();
2419 foreach (fd; fds) assert(!set.isSet(fd));
2420 foreach (fd; fds) set.add(fd);
2421 foreach (fd; fds) assert(set.isSet(fd));
2423 // Make sure SocketSet reimplements fd_set correctly
2424 auto fdset = set.toFd_set();
2425 foreach (fd; fds[0]..cast(socket_t)(fds[$-1]+1))
2426 assert(cast(bool) set.isSet(fd) == cast(bool)(() @trusted => FD_ISSET(fd, fdset))());
2428 foreach (fd; fds)
2430 assert(set.isSet(fd));
2431 set.remove(fd);
2432 assert(!set.isSet(fd));
2436 @safe unittest
2438 version (iOSDerived)
2440 enum PAIRS = 256;
2441 enum LIMIT = 1024;
2443 else
2445 enum PAIRS = 768;
2446 enum LIMIT = 2048;
2449 softUnittest({
2450 version (Posix)
2451 () @trusted
2453 static assert(LIMIT > PAIRS*2);
2454 import core.sys.posix.sys.resource;
2455 rlimit fileLimit;
2456 getrlimit(RLIMIT_NOFILE, &fileLimit);
2457 assert(fileLimit.rlim_max > LIMIT, "Open file hard limit too low");
2458 fileLimit.rlim_cur = LIMIT;
2459 setrlimit(RLIMIT_NOFILE, &fileLimit);
2460 } ();
2462 Socket[2][PAIRS] pairs;
2463 foreach (ref pair; pairs)
2464 pair = socketPair();
2465 scope(exit)
2467 foreach (pair; pairs)
2469 pair[0].close();
2470 pair[1].close();
2474 import std.random;
2475 auto rng = Xorshift(42);
2476 pairs[].randomShuffle(rng);
2478 auto readSet = new SocketSet();
2479 auto writeSet = new SocketSet();
2480 auto errorSet = new SocketSet();
2482 foreach (testPair; pairs)
2484 void fillSets()
2486 readSet.reset();
2487 writeSet.reset();
2488 errorSet.reset();
2489 foreach (ref pair; pairs)
2490 foreach (s; pair[])
2492 readSet.add(s);
2493 writeSet.add(s);
2494 errorSet.add(s);
2498 fillSets();
2499 auto n = Socket.select(readSet, writeSet, errorSet);
2500 assert(n == PAIRS*2); // All in writeSet
2501 assert(writeSet.isSet(testPair[0]));
2502 assert(writeSet.isSet(testPair[1]));
2503 assert(!readSet.isSet(testPair[0]));
2504 assert(!readSet.isSet(testPair[1]));
2505 assert(!errorSet.isSet(testPair[0]));
2506 assert(!errorSet.isSet(testPair[1]));
2508 ubyte[1] b;
2509 // Socket.send can't be marked with `scope`
2510 // -> @safe DIP1000 code can't use it - see https://github.com/dlang/phobos/pull/6204
2511 () @trusted {
2512 testPair[0].send(b[]);
2513 }();
2514 fillSets();
2515 n = Socket.select(readSet, null, null);
2516 assert(n == 1); // testPair[1]
2517 assert(readSet.isSet(testPair[1]));
2518 assert(!readSet.isSet(testPair[0]));
2519 // Socket.receive can't be marked with `scope`
2520 // -> @safe DIP1000 code can't use it - see https://github.com/dlang/phobos/pull/6204
2521 () @trusted {
2522 testPair[1].receive(b[]);
2523 }();
2528 // https://issues.dlang.org/show_bug.cgi?id=14012
2529 // https://issues.dlang.org/show_bug.cgi?id=14013
2530 @safe unittest
2532 auto set = new SocketSet(1);
2533 assert(set.max >= 0);
2535 enum LIMIT = 4096;
2536 foreach (n; 0 .. LIMIT)
2537 set.add(cast(socket_t) n);
2538 assert(set.max >= LIMIT);
2541 /// The level at which a socket option is defined:
2542 enum SocketOptionLevel: int
2544 SOCKET = SOL_SOCKET, /// Socket level
2545 IP = ProtocolType.IP, /// Internet Protocol version 4 level
2546 ICMP = ProtocolType.ICMP, /// Internet Control Message Protocol level
2547 IGMP = ProtocolType.IGMP, /// Internet Group Management Protocol level
2548 GGP = ProtocolType.GGP, /// Gateway to Gateway Protocol level
2549 TCP = ProtocolType.TCP, /// Transmission Control Protocol level
2550 PUP = ProtocolType.PUP, /// PARC Universal Packet Protocol level
2551 UDP = ProtocolType.UDP, /// User Datagram Protocol level
2552 IDP = ProtocolType.IDP, /// Xerox NS protocol level
2553 RAW = ProtocolType.RAW, /// Raw IP packet level
2554 IPV6 = ProtocolType.IPV6, /// Internet Protocol version 6 level
2557 /// _Linger information for use with SocketOption.LINGER.
2558 struct Linger
2560 _clinger clinger;
2562 private alias l_onoff_t = typeof(_clinger.init.l_onoff );
2563 private alias l_linger_t = typeof(_clinger.init.l_linger);
2565 /// Nonzero for _on.
2566 pure nothrow @nogc @property
2567 ref inout(l_onoff_t) on() inout return
2569 return clinger.l_onoff;
2572 /// Linger _time.
2573 pure nothrow @nogc @property
2574 ref inout(l_linger_t) time() inout return
2576 return clinger.l_linger;
2580 /// Specifies a socket option:
2581 enum SocketOption: int
2583 DEBUG = SO_DEBUG, /// Record debugging information
2584 BROADCAST = SO_BROADCAST, /// Allow transmission of broadcast messages
2585 REUSEADDR = SO_REUSEADDR, /// Allow local reuse of address
2586 LINGER = SO_LINGER, /// Linger on close if unsent data is present
2587 OOBINLINE = SO_OOBINLINE, /// Receive out-of-band data in band
2588 SNDBUF = SO_SNDBUF, /// Send buffer size
2589 RCVBUF = SO_RCVBUF, /// Receive buffer size
2590 DONTROUTE = SO_DONTROUTE, /// Do not route
2591 SNDTIMEO = SO_SNDTIMEO, /// Send timeout
2592 RCVTIMEO = SO_RCVTIMEO, /// Receive timeout
2593 ERROR = SO_ERROR, /// Retrieve and clear error status
2594 KEEPALIVE = SO_KEEPALIVE, /// Enable keep-alive packets
2595 ACCEPTCONN = SO_ACCEPTCONN, /// Listen
2596 RCVLOWAT = SO_RCVLOWAT, /// Minimum number of input bytes to process
2597 SNDLOWAT = SO_SNDLOWAT, /// Minimum number of output bytes to process
2598 TYPE = SO_TYPE, /// Socket type
2600 // SocketOptionLevel.TCP:
2601 TCP_NODELAY = .TCP_NODELAY, /// Disable the Nagle algorithm for send coalescing
2603 // SocketOptionLevel.IPV6:
2604 IPV6_UNICAST_HOPS = .IPV6_UNICAST_HOPS, /// IP unicast hop limit
2605 IPV6_MULTICAST_IF = .IPV6_MULTICAST_IF, /// IP multicast interface
2606 IPV6_MULTICAST_LOOP = .IPV6_MULTICAST_LOOP, /// IP multicast loopback
2607 IPV6_MULTICAST_HOPS = .IPV6_MULTICAST_HOPS, /// IP multicast hops
2608 IPV6_JOIN_GROUP = .IPV6_JOIN_GROUP, /// Add an IP group membership
2609 IPV6_LEAVE_GROUP = .IPV6_LEAVE_GROUP, /// Drop an IP group membership
2610 IPV6_V6ONLY = .IPV6_V6ONLY, /// Treat wildcard bind as AF_INET6-only
2615 * `Socket` is a class that creates a network communication endpoint using
2616 * the Berkeley sockets interface.
2618 class Socket
2620 private:
2621 socket_t sock;
2622 AddressFamily _family;
2624 version (Windows)
2625 bool _blocking = false; /// Property to get or set whether the socket is blocking or nonblocking.
2627 // The WinSock timeouts seem to be effectively skewed by a constant
2628 // offset of about half a second (value in milliseconds). This has
2629 // been confirmed on updated (as of Jun 2011) Windows XP, Windows 7
2630 // and Windows Server 2008 R2 boxes. The unittest below tests this
2631 // behavior.
2632 enum WINSOCK_TIMEOUT_SKEW = 500;
2634 @safe unittest
2636 debug (std_socket)
2637 softUnittest({
2638 import std.datetime.stopwatch;
2639 import std.typecons;
2641 enum msecs = 1000;
2642 auto pair = socketPair();
2643 auto sock = pair[0];
2644 sock.setOption(SocketOptionLevel.SOCKET,
2645 SocketOption.RCVTIMEO, dur!"msecs"(msecs));
2647 auto sw = StopWatch(Yes.autoStart);
2648 ubyte[1] buf;
2649 sock.receive(buf);
2650 sw.stop();
2652 Duration readBack = void;
2653 sock.getOption(SocketOptionLevel.SOCKET, SocketOption.RCVTIMEO, readBack);
2655 assert(readBack.total!"msecs" == msecs);
2656 assert(sw.peek().total!"msecs" > msecs - 100 && sw.peek().total!"msecs" < msecs + 100);
2660 void setSock(socket_t handle)
2662 assert(handle != socket_t.init);
2663 sock = handle;
2665 // Set the option to disable SIGPIPE on send() if the platform
2666 // has it (e.g. on OS X).
2667 static if (is(typeof(SO_NOSIGPIPE)))
2669 setOption(SocketOptionLevel.SOCKET, cast(SocketOption) SO_NOSIGPIPE, true);
2674 // For use with accepting().
2675 protected this() pure nothrow @nogc
2680 public:
2683 * Create a blocking socket. If a single protocol type exists to support
2684 * this socket type within the address family, the `ProtocolType` may be
2685 * omitted.
2687 this(AddressFamily af, SocketType type, ProtocolType protocol) @trusted
2689 _family = af;
2690 auto handle = cast(socket_t) socket(af, type, protocol);
2691 if (handle == socket_t.init)
2692 throw new SocketOSException("Unable to create socket");
2693 setSock(handle);
2696 /// ditto
2697 this(AddressFamily af, SocketType type)
2699 /* A single protocol exists to support this socket type within the
2700 * protocol family, so the ProtocolType is assumed.
2702 this(af, type, cast(ProtocolType) 0); // Pseudo protocol number.
2706 /// ditto
2707 this(AddressFamily af, SocketType type, scope const(char)[] protocolName) @trusted
2709 protoent* proto;
2710 proto = getprotobyname(protocolName.tempCString());
2711 if (!proto)
2712 throw new SocketOSException("Unable to find the protocol");
2713 this(af, type, cast(ProtocolType) proto.p_proto);
2718 * Create a blocking socket using the parameters from the specified
2719 * `AddressInfo` structure.
2721 this(const scope AddressInfo info)
2723 this(info.family, info.type, info.protocol);
2726 /// Use an existing socket handle.
2727 this(socket_t sock, AddressFamily af) pure nothrow @nogc
2729 assert(sock != socket_t.init);
2730 this.sock = sock;
2731 this._family = af;
2735 ~this() nothrow @nogc
2737 close();
2741 /// Get underlying socket handle.
2742 @property socket_t handle() const pure nothrow @nogc
2744 return sock;
2748 * Get/set socket's blocking flag.
2750 * When a socket is blocking, calls to receive(), accept(), and send()
2751 * will block and wait for data/action.
2752 * A non-blocking socket will immediately return instead of blocking.
2754 @property bool blocking() @trusted const nothrow @nogc
2756 version (Windows)
2758 return _blocking;
2760 else version (Posix)
2762 return !(fcntl(handle, F_GETFL, 0) & O_NONBLOCK);
2766 /// ditto
2767 @property void blocking(bool byes) @trusted
2769 version (Windows)
2771 uint num = !byes;
2772 if (_SOCKET_ERROR == ioctlsocket(sock, FIONBIO, &num))
2773 goto err;
2774 _blocking = byes;
2776 else version (Posix)
2778 int x = fcntl(sock, F_GETFL, 0);
2779 if (-1 == x)
2780 goto err;
2781 if (byes)
2782 x &= ~O_NONBLOCK;
2783 else
2784 x |= O_NONBLOCK;
2785 if (-1 == fcntl(sock, F_SETFL, x))
2786 goto err;
2788 return; // Success.
2790 err:
2791 throw new SocketOSException("Unable to set socket blocking");
2795 /// Get the socket's address family.
2796 @property AddressFamily addressFamily()
2798 return _family;
2801 /// Property that indicates if this is a valid, alive socket.
2802 @property bool isAlive() @trusted const
2804 int type;
2805 socklen_t typesize = cast(socklen_t) type.sizeof;
2806 return !getsockopt(sock, SOL_SOCKET, SO_TYPE, cast(char*)&type, &typesize);
2810 * Associate a local address with this socket.
2812 * Params:
2813 * addr = The $(LREF Address) to associate this socket with.
2815 * Throws: $(LREF SocketOSException) when unable to bind the socket.
2817 void bind(Address addr) @trusted
2819 if (_SOCKET_ERROR == .bind(sock, addr.name, addr.nameLen))
2820 throw new SocketOSException("Unable to bind socket");
2824 * Establish a connection. If the socket is blocking, connect waits for
2825 * the connection to be made. If the socket is nonblocking, connect
2826 * returns immediately and the connection attempt is still in progress.
2828 void connect(Address to) @trusted
2830 if (_SOCKET_ERROR == .connect(sock, to.name, to.nameLen))
2832 int err;
2833 err = _lasterr();
2835 if (!blocking)
2837 version (Windows)
2839 if (WSAEWOULDBLOCK == err)
2840 return;
2842 else version (Posix)
2844 if (EINPROGRESS == err)
2845 return;
2847 else
2849 static assert(0);
2852 throw new SocketOSException("Unable to connect socket", err);
2857 * Listen for an incoming connection. `bind` must be called before you
2858 * can `listen`. The `backlog` is a request of how many pending
2859 * incoming connections are queued until `accept`ed.
2861 void listen(int backlog) @trusted
2863 if (_SOCKET_ERROR == .listen(sock, backlog))
2864 throw new SocketOSException("Unable to listen on socket");
2868 * Called by `accept` when a new `Socket` must be created for a new
2869 * connection. To use a derived class, override this method and return an
2870 * instance of your class. The returned `Socket`'s handle must not be
2871 * set; `Socket` has a protected constructor `this()` to use in this
2872 * situation.
2874 * Override to use a derived class.
2875 * The returned socket's handle must not be set.
2877 protected Socket accepting() pure nothrow
2879 return new Socket;
2883 * Accept an incoming connection. If the socket is blocking, `accept`
2884 * waits for a connection request. Throws `SocketAcceptException` if
2885 * unable to _accept. See `accepting` for use with derived classes.
2887 Socket accept() @trusted
2889 auto newsock = cast(socket_t).accept(sock, null, null);
2890 if (socket_t.init == newsock)
2891 throw new SocketAcceptException("Unable to accept socket connection");
2893 Socket newSocket;
2896 newSocket = accepting();
2897 assert(newSocket.sock == socket_t.init);
2899 newSocket.setSock(newsock);
2900 version (Windows)
2901 newSocket._blocking = _blocking; //inherits blocking mode
2902 newSocket._family = _family; //same family
2904 catch (Throwable o)
2906 _close(newsock);
2907 throw o;
2910 return newSocket;
2913 /// Disables sends and/or receives.
2914 void shutdown(SocketShutdown how) @trusted nothrow @nogc
2916 .shutdown(sock, cast(int) how);
2920 private static void _close(socket_t sock) @system nothrow @nogc
2922 version (Windows)
2924 .closesocket(sock);
2926 else version (Posix)
2928 .close(sock);
2934 * Immediately drop any connections and release socket resources.
2935 * The `Socket` object is no longer usable after `close`.
2936 * Calling `shutdown` before `close` is recommended
2937 * for connection-oriented sockets.
2939 void close() @trusted nothrow @nogc
2941 _close(sock);
2942 sock = socket_t.init;
2947 * Returns: the local machine's host name
2949 static @property string hostName() @trusted // getter
2951 char[256] result; // Host names are limited to 255 chars.
2952 if (_SOCKET_ERROR == .gethostname(result.ptr, result.length))
2953 throw new SocketOSException("Unable to obtain host name");
2954 return to!string(result.ptr);
2957 /// Remote endpoint `Address`.
2958 @property Address remoteAddress() @trusted
2960 Address addr = createAddress();
2961 socklen_t nameLen = addr.nameLen;
2962 if (_SOCKET_ERROR == .getpeername(sock, addr.name, &nameLen))
2963 throw new SocketOSException("Unable to obtain remote socket address");
2964 addr.setNameLen(nameLen);
2965 assert(addr.addressFamily == _family);
2966 return addr;
2969 /// Local endpoint `Address`.
2970 @property Address localAddress() @trusted
2972 Address addr = createAddress();
2973 socklen_t nameLen = addr.nameLen;
2974 if (_SOCKET_ERROR == .getsockname(sock, addr.name, &nameLen))
2975 throw new SocketOSException("Unable to obtain local socket address");
2976 addr.setNameLen(nameLen);
2977 assert(addr.addressFamily == _family);
2978 return addr;
2982 * Send or receive error code. See `wouldHaveBlocked`,
2983 * `lastSocketError` and `Socket.getErrorText` for obtaining more
2984 * information about the error.
2986 enum int ERROR = _SOCKET_ERROR;
2988 private static int capToInt(size_t size) nothrow @nogc
2990 // Windows uses int instead of size_t for length arguments.
2991 // Luckily, the send/recv functions make no guarantee that
2992 // all the data is sent, so we use that to send at most
2993 // int.max bytes.
2994 return size > size_t(int.max) ? int.max : cast(int) size;
2998 * Send data on the connection. If the socket is blocking and there is no
2999 * buffer space left, `send` waits.
3000 * Returns: The number of bytes actually sent, or `Socket.ERROR` on
3001 * failure.
3003 ptrdiff_t send(const(void)[] buf, SocketFlags flags) @trusted
3005 static if (is(typeof(MSG_NOSIGNAL)))
3007 flags = cast(SocketFlags)(flags | MSG_NOSIGNAL);
3009 version (Windows)
3010 auto sent = .send(sock, buf.ptr, capToInt(buf.length), cast(int) flags);
3011 else
3012 auto sent = .send(sock, buf.ptr, buf.length, cast(int) flags);
3013 return sent;
3016 /// ditto
3017 ptrdiff_t send(const(void)[] buf)
3019 return send(buf, SocketFlags.NONE);
3023 * Send data to a specific destination Address. If the destination address is
3024 * not specified, a connection must have been made and that address is used.
3025 * If the socket is blocking and there is no buffer space left, `sendTo` waits.
3026 * Returns: The number of bytes actually sent, or `Socket.ERROR` on
3027 * failure.
3029 ptrdiff_t sendTo(const(void)[] buf, SocketFlags flags, Address to) @trusted
3031 static if (is(typeof(MSG_NOSIGNAL)))
3033 flags = cast(SocketFlags)(flags | MSG_NOSIGNAL);
3035 version (Windows)
3036 return .sendto(
3037 sock, buf.ptr, capToInt(buf.length),
3038 cast(int) flags, to.name, to.nameLen
3040 else
3041 return .sendto(sock, buf.ptr, buf.length, cast(int) flags, to.name, to.nameLen);
3044 /// ditto
3045 ptrdiff_t sendTo(const(void)[] buf, Address to)
3047 return sendTo(buf, SocketFlags.NONE, to);
3051 //assumes you connect()ed
3052 /// ditto
3053 ptrdiff_t sendTo(const(void)[] buf, SocketFlags flags) @trusted
3055 static if (is(typeof(MSG_NOSIGNAL)))
3057 flags = cast(SocketFlags)(flags | MSG_NOSIGNAL);
3059 version (Windows)
3060 return .sendto(sock, buf.ptr, capToInt(buf.length), cast(int) flags, null, 0);
3061 else
3062 return .sendto(sock, buf.ptr, buf.length, cast(int) flags, null, 0);
3066 //assumes you connect()ed
3067 /// ditto
3068 ptrdiff_t sendTo(const(void)[] buf)
3070 return sendTo(buf, SocketFlags.NONE);
3075 * Receive data on the connection. If the socket is blocking, `receive`
3076 * waits until there is data to be received.
3077 * Returns: The number of bytes actually received, `0` if the remote side
3078 * has closed the connection, or `Socket.ERROR` on failure.
3080 ptrdiff_t receive(void[] buf, SocketFlags flags) @trusted
3082 version (Windows) // Does not use size_t
3084 return buf.length
3085 ? .recv(sock, buf.ptr, capToInt(buf.length), cast(int) flags)
3086 : 0;
3088 else
3090 return buf.length
3091 ? .recv(sock, buf.ptr, buf.length, cast(int) flags)
3092 : 0;
3096 /// ditto
3097 ptrdiff_t receive(void[] buf)
3099 return receive(buf, SocketFlags.NONE);
3103 * Receive data and get the remote endpoint `Address`.
3104 * If the socket is blocking, `receiveFrom` waits until there is data to
3105 * be received.
3106 * Returns: The number of bytes actually received, `0` if the remote side
3107 * has closed the connection, or `Socket.ERROR` on failure.
3109 ptrdiff_t receiveFrom(void[] buf, SocketFlags flags, ref Address from) @trusted
3111 if (!buf.length) //return 0 and don't think the connection closed
3112 return 0;
3113 if (from is null || from.addressFamily != _family)
3114 from = createAddress();
3115 socklen_t nameLen = from.nameLen;
3116 version (Windows)
3117 auto read = .recvfrom(sock, buf.ptr, capToInt(buf.length), cast(int) flags, from.name, &nameLen);
3119 else
3120 auto read = .recvfrom(sock, buf.ptr, buf.length, cast(int) flags, from.name, &nameLen);
3122 if (read >= 0)
3124 from.setNameLen(nameLen);
3125 assert(from.addressFamily == _family);
3127 return read;
3131 /// ditto
3132 ptrdiff_t receiveFrom(void[] buf, ref Address from)
3134 return receiveFrom(buf, SocketFlags.NONE, from);
3138 //assumes you connect()ed
3139 /// ditto
3140 ptrdiff_t receiveFrom(void[] buf, SocketFlags flags) @trusted
3142 if (!buf.length) //return 0 and don't think the connection closed
3143 return 0;
3144 version (Windows)
3146 auto read = .recvfrom(sock, buf.ptr, capToInt(buf.length), cast(int) flags, null, null);
3147 // if (!read) //connection closed
3148 return read;
3150 else
3152 auto read = .recvfrom(sock, buf.ptr, buf.length, cast(int) flags, null, null);
3153 // if (!read) //connection closed
3154 return read;
3159 //assumes you connect()ed
3160 /// ditto
3161 ptrdiff_t receiveFrom(void[] buf)
3163 return receiveFrom(buf, SocketFlags.NONE);
3168 * Get a socket option.
3169 * Returns: The number of bytes written to `result`.
3170 * The length, in bytes, of the actual result - very different from getsockopt()
3172 int getOption(SocketOptionLevel level, SocketOption option, void[] result) @trusted
3174 socklen_t len = cast(socklen_t) result.length;
3175 if (_SOCKET_ERROR == .getsockopt(sock, cast(int) level, cast(int) option, result.ptr, &len))
3176 throw new SocketOSException("Unable to get socket option");
3177 return len;
3181 /// Common case of getting integer and boolean options.
3182 int getOption(SocketOptionLevel level, SocketOption option, out int32_t result) @trusted
3184 return getOption(level, option, (&result)[0 .. 1]);
3188 /// Get the linger option.
3189 int getOption(SocketOptionLevel level, SocketOption option, out Linger result) @trusted
3191 //return getOption(cast(SocketOptionLevel) SocketOptionLevel.SOCKET, SocketOption.LINGER, (&result)[0 .. 1]);
3192 return getOption(level, option, (&result.clinger)[0 .. 1]);
3195 /// Get a timeout (duration) option.
3196 void getOption(SocketOptionLevel level, SocketOption option, out Duration result) @trusted
3198 enforce(option == SocketOption.SNDTIMEO || option == SocketOption.RCVTIMEO,
3199 new SocketParameterException("Not a valid timeout option: " ~ to!string(option)));
3200 // WinSock returns the timeout values as a milliseconds DWORD,
3201 // while Linux and BSD return a timeval struct.
3202 version (Windows)
3204 int msecs;
3205 getOption(level, option, (&msecs)[0 .. 1]);
3206 if (option == SocketOption.RCVTIMEO)
3207 msecs += WINSOCK_TIMEOUT_SKEW;
3208 result = dur!"msecs"(msecs);
3210 else version (Posix)
3212 TimeVal tv;
3213 getOption(level, option, (&tv.ctimeval)[0 .. 1]);
3214 result = dur!"seconds"(tv.seconds) + dur!"usecs"(tv.microseconds);
3216 else static assert(false);
3219 /// Set a socket option.
3220 void setOption(SocketOptionLevel level, SocketOption option, void[] value) @trusted
3222 if (_SOCKET_ERROR == .setsockopt(sock, cast(int) level,
3223 cast(int) option, value.ptr, cast(uint) value.length))
3224 throw new SocketOSException("Unable to set socket option");
3228 /// Common case for setting integer and boolean options.
3229 void setOption(SocketOptionLevel level, SocketOption option, int32_t value) @trusted
3231 setOption(level, option, (&value)[0 .. 1]);
3235 /// Set the linger option.
3236 void setOption(SocketOptionLevel level, SocketOption option, Linger value) @trusted
3238 //setOption(cast(SocketOptionLevel) SocketOptionLevel.SOCKET, SocketOption.LINGER, (&value)[0 .. 1]);
3239 setOption(level, option, (&value.clinger)[0 .. 1]);
3243 * Sets a timeout (duration) option, i.e. `SocketOption.SNDTIMEO` or
3244 * `RCVTIMEO`. Zero indicates no timeout.
3246 * In a typical application, you might also want to consider using
3247 * a non-blocking socket instead of setting a timeout on a blocking one.
3249 * Note: While the receive timeout setting is generally quite accurate
3250 * on *nix systems even for smaller durations, there are two issues to
3251 * be aware of on Windows: First, although undocumented, the effective
3252 * timeout duration seems to be the one set on the socket plus half
3253 * a second. `setOption()` tries to compensate for that, but still,
3254 * timeouts under 500ms are not possible on Windows. Second, be aware
3255 * that the actual amount of time spent until a blocking call returns
3256 * randomly varies on the order of 10ms.
3258 * Params:
3259 * level = The level at which a socket option is defined.
3260 * option = Either `SocketOption.SNDTIMEO` or `SocketOption.RCVTIMEO`.
3261 * value = The timeout duration to set. Must not be negative.
3263 * Throws: `SocketException` if setting the options fails.
3265 * Example:
3266 * ---
3267 * import std.datetime;
3268 * import std.typecons;
3269 * auto pair = socketPair();
3270 * scope(exit) foreach (s; pair) s.close();
3272 * // Set a receive timeout, and then wait at one end of
3273 * // the socket pair, knowing that no data will arrive.
3274 * pair[0].setOption(SocketOptionLevel.SOCKET,
3275 * SocketOption.RCVTIMEO, dur!"seconds"(1));
3277 * auto sw = StopWatch(Yes.autoStart);
3278 * ubyte[1] buffer;
3279 * pair[0].receive(buffer);
3280 * writefln("Waited %s ms until the socket timed out.",
3281 * sw.peek.msecs);
3282 * ---
3284 void setOption(SocketOptionLevel level, SocketOption option, Duration value) @trusted
3286 enforce(option == SocketOption.SNDTIMEO || option == SocketOption.RCVTIMEO,
3287 new SocketParameterException("Not a valid timeout option: " ~ to!string(option)));
3289 enforce(value >= dur!"hnsecs"(0), new SocketParameterException(
3290 "Timeout duration must not be negative."));
3292 version (Windows)
3294 import std.algorithm.comparison : max;
3296 auto msecs = to!int(value.total!"msecs");
3297 if (msecs != 0 && option == SocketOption.RCVTIMEO)
3298 msecs = max(1, msecs - WINSOCK_TIMEOUT_SKEW);
3299 setOption(level, option, msecs);
3301 else version (Posix)
3303 _ctimeval tv;
3304 value.split!("seconds", "usecs")(tv.tv_sec, tv.tv_usec);
3305 setOption(level, option, (&tv)[0 .. 1]);
3307 else static assert(false);
3311 * Get a text description of this socket's error status, and clear the
3312 * socket's error status.
3314 string getErrorText()
3316 int32_t error;
3317 getOption(SocketOptionLevel.SOCKET, SocketOption.ERROR, error);
3318 return formatSocketError(error);
3322 * Enables TCP keep-alive with the specified parameters.
3324 * Params:
3325 * time = Number of seconds with no activity until the first
3326 * keep-alive packet is sent.
3327 * interval = Number of seconds between when successive keep-alive
3328 * packets are sent if no acknowledgement is received.
3330 * Throws: `SocketOSException` if setting the options fails, or
3331 * `SocketFeatureException` if setting keep-alive parameters is
3332 * unsupported on the current platform.
3334 void setKeepAlive(int time, int interval) @trusted
3336 version (Windows)
3338 tcp_keepalive options;
3339 options.onoff = 1;
3340 options.keepalivetime = time * 1000;
3341 options.keepaliveinterval = interval * 1000;
3342 uint cbBytesReturned;
3343 enforce(WSAIoctl(sock, SIO_KEEPALIVE_VALS,
3344 &options, options.sizeof,
3345 null, 0,
3346 &cbBytesReturned, null, null) == 0,
3347 new SocketOSException("Error setting keep-alive"));
3349 else
3350 static if (is(typeof(TCP_KEEPIDLE)) && is(typeof(TCP_KEEPINTVL)))
3352 setOption(SocketOptionLevel.TCP, cast(SocketOption) TCP_KEEPIDLE, time);
3353 setOption(SocketOptionLevel.TCP, cast(SocketOption) TCP_KEEPINTVL, interval);
3354 setOption(SocketOptionLevel.SOCKET, SocketOption.KEEPALIVE, true);
3356 else
3357 throw new SocketFeatureException("Setting keep-alive options " ~
3358 "is not supported on this platform");
3362 * Wait for a socket to change status. A wait timeout of $(REF Duration, core, time) or
3363 * `TimeVal`, may be specified; if a timeout is not specified or the
3364 * `TimeVal` is `null`, the maximum timeout is used. The `TimeVal`
3365 * timeout has an unspecified value when `select` returns.
3366 * Returns: The number of sockets with status changes, `0` on timeout,
3367 * or `-1` on interruption. If the return value is greater than `0`,
3368 * the `SocketSets` are updated to only contain the sockets having status
3369 * changes. For a connecting socket, a write status change means the
3370 * connection is established and it's able to send. For a listening socket,
3371 * a read status change means there is an incoming connection request and
3372 * it's able to accept.
3374 * `SocketSet`'s updated to include only those sockets which an event occured.
3375 * For a `connect()`ing socket, writeability means connected.
3376 * For a `listen()`ing socket, readability means listening
3377 * `Winsock`; possibly internally limited to 64 sockets per set.
3379 * Returns:
3380 * the number of events, 0 on timeout, or -1 on interruption
3382 static int select(SocketSet checkRead, SocketSet checkWrite, SocketSet checkError, Duration timeout) @trusted
3384 auto vals = timeout.split!("seconds", "usecs")();
3385 TimeVal tv;
3386 tv.seconds = cast(tv.tv_sec_t ) vals.seconds;
3387 tv.microseconds = cast(tv.tv_usec_t) vals.usecs;
3388 return select(checkRead, checkWrite, checkError, &tv);
3391 /// ditto
3392 //maximum timeout
3393 static int select(SocketSet checkRead, SocketSet checkWrite, SocketSet checkError)
3395 return select(checkRead, checkWrite, checkError, null);
3398 /// Ditto
3399 static int select(SocketSet checkRead, SocketSet checkWrite, SocketSet checkError, TimeVal* timeout) @trusted
3402 //make sure none of the SocketSet's are the same object
3403 if (checkRead)
3405 assert(checkRead !is checkWrite);
3406 assert(checkRead !is checkError);
3408 if (checkWrite)
3410 assert(checkWrite !is checkError);
3415 fd_set* fr, fw, fe;
3416 int n = 0;
3418 version (Windows)
3420 // Windows has a problem with empty fd_set`s that aren't null.
3421 fr = checkRead && checkRead.count ? checkRead.toFd_set() : null;
3422 fw = checkWrite && checkWrite.count ? checkWrite.toFd_set() : null;
3423 fe = checkError && checkError.count ? checkError.toFd_set() : null;
3425 else
3427 if (checkRead)
3429 fr = checkRead.toFd_set();
3430 n = checkRead.selectn();
3432 else
3434 fr = null;
3437 if (checkWrite)
3439 fw = checkWrite.toFd_set();
3440 int _n;
3441 _n = checkWrite.selectn();
3442 if (_n > n)
3443 n = _n;
3445 else
3447 fw = null;
3450 if (checkError)
3452 fe = checkError.toFd_set();
3453 int _n;
3454 _n = checkError.selectn();
3455 if (_n > n)
3456 n = _n;
3458 else
3460 fe = null;
3463 // Make sure the sets' capacity matches, to avoid select reading
3464 // out of bounds just because one set was bigger than another
3465 if (checkRead ) checkRead .setMinCapacity(n);
3466 if (checkWrite) checkWrite.setMinCapacity(n);
3467 if (checkError) checkError.setMinCapacity(n);
3470 int result = .select(n, fr, fw, fe, &timeout.ctimeval);
3472 version (Windows)
3474 if (_SOCKET_ERROR == result && WSAGetLastError() == WSAEINTR)
3475 return -1;
3477 else version (Posix)
3479 if (_SOCKET_ERROR == result && errno == EINTR)
3480 return -1;
3482 else
3484 static assert(0);
3487 if (_SOCKET_ERROR == result)
3488 throw new SocketOSException("Socket select error");
3490 return result;
3495 * Can be overridden to support other addresses.
3496 * Returns: a new `Address` object for the current address family.
3498 protected Address createAddress() pure nothrow
3500 Address result;
3501 switch (_family)
3503 static if (is(sockaddr_un))
3505 case AddressFamily.UNIX:
3506 result = new UnixAddress;
3507 break;
3510 case AddressFamily.INET:
3511 result = new InternetAddress;
3512 break;
3514 case AddressFamily.INET6:
3515 result = new Internet6Address;
3516 break;
3518 default:
3519 result = new UnknownAddress;
3521 return result;
3527 /// `TcpSocket` is a shortcut class for a TCP Socket.
3528 class TcpSocket: Socket
3530 /// Constructs a blocking TCP Socket.
3531 this(AddressFamily family)
3533 super(family, SocketType.STREAM, ProtocolType.TCP);
3536 /// Constructs a blocking IPv4 TCP Socket.
3537 this()
3539 this(AddressFamily.INET);
3543 //shortcut
3544 /// Constructs a blocking TCP Socket and connects to an `Address`.
3545 this(Address connectTo)
3547 this(connectTo.addressFamily);
3548 connect(connectTo);
3553 /// `UdpSocket` is a shortcut class for a UDP Socket.
3554 class UdpSocket: Socket
3556 /// Constructs a blocking UDP Socket.
3557 this(AddressFamily family)
3559 super(family, SocketType.DGRAM, ProtocolType.UDP);
3563 /// Constructs a blocking IPv4 UDP Socket.
3564 this()
3566 this(AddressFamily.INET);
3570 @safe unittest
3572 byte[] buf;
3573 buf.length = 1;
3574 Address addr;
3575 auto s = new UdpSocket;
3576 s.blocking = false;
3577 s.bind(new InternetAddress(InternetAddress.PORT_ANY));
3578 s.receiveFrom(buf, addr);
3581 // https://issues.dlang.org/show_bug.cgi?id=16514
3582 @safe unittest
3584 void checkAttributes(string attributes)()
3586 mixin(attributes ~ q{ void function() fun = {};});
3587 fun();
3590 class TestSocket : Socket
3592 override
3594 @property pure nothrow @nogc @safe socket_t handle() const
3596 checkAttributes!q{pure nothrow @nogc @safe}; assert(0);
3598 @property nothrow @nogc @trusted bool blocking() const
3600 checkAttributes!q{nothrow @nogc @trusted}; assert(0);
3602 @property @trusted void blocking(bool byes)
3604 checkAttributes!q{@trusted};
3606 @property @safe AddressFamily addressFamily()
3608 checkAttributes!q{@safe}; assert(0);
3610 @property @trusted bool isAlive() const
3612 checkAttributes!q{@trusted}; assert(0);
3614 @trusted void bind(Address addr)
3616 checkAttributes!q{@trusted};
3618 @trusted void connect(Address to)
3620 checkAttributes!q{@trusted};
3622 @trusted void listen(int backlog)
3624 checkAttributes!q{@trusted};
3626 protected pure nothrow @safe Socket accepting()
3628 checkAttributes!q{pure nothrow @safe}; assert(0);
3630 @trusted Socket accept()
3632 checkAttributes!q{@trusted}; assert(0);
3634 nothrow @nogc @trusted void shutdown(SocketShutdown how)
3636 checkAttributes!q{nothrow @nogc @trusted};
3638 nothrow @nogc @trusted void close()
3640 checkAttributes!q{nothrow @nogc @trusted};
3642 @property @trusted Address remoteAddress()
3644 checkAttributes!q{@trusted}; assert(0);
3646 @property @trusted Address localAddress()
3648 checkAttributes!q{@trusted}; assert(0);
3650 @trusted ptrdiff_t send(const(void)[] buf, SocketFlags flags)
3652 checkAttributes!q{@trusted}; assert(0);
3654 @safe ptrdiff_t send(const(void)[] buf)
3656 checkAttributes!q{@safe}; assert(0);
3658 @trusted ptrdiff_t sendTo(const(void)[] buf, SocketFlags flags, Address to)
3660 checkAttributes!q{@trusted}; assert(0);
3662 @safe ptrdiff_t sendTo(const(void)[] buf, Address to)
3664 checkAttributes!q{@safe}; assert(0);
3666 @trusted ptrdiff_t sendTo(const(void)[] buf, SocketFlags flags)
3668 checkAttributes!q{@trusted}; assert(0);
3670 @safe ptrdiff_t sendTo(const(void)[] buf)
3672 checkAttributes!q{@safe}; assert(0);
3674 @trusted ptrdiff_t receive(void[] buf, SocketFlags flags)
3676 checkAttributes!q{@trusted}; assert(0);
3678 @safe ptrdiff_t receive(void[] buf)
3680 checkAttributes!q{@safe}; assert(0);
3682 @trusted ptrdiff_t receiveFrom(void[] buf, SocketFlags flags, ref Address from)
3684 checkAttributes!q{@trusted}; assert(0);
3686 @safe ptrdiff_t receiveFrom(void[] buf, ref Address from)
3688 checkAttributes!q{@safe}; assert(0);
3690 @trusted ptrdiff_t receiveFrom(void[] buf, SocketFlags flags)
3692 checkAttributes!q{@trusted}; assert(0);
3694 @safe ptrdiff_t receiveFrom(void[] buf)
3696 checkAttributes!q{@safe}; assert(0);
3698 @trusted int getOption(SocketOptionLevel level, SocketOption option, void[] result)
3700 checkAttributes!q{@trusted}; assert(0);
3702 @trusted int getOption(SocketOptionLevel level, SocketOption option, out int32_t result)
3704 checkAttributes!q{@trusted}; assert(0);
3706 @trusted int getOption(SocketOptionLevel level, SocketOption option, out Linger result)
3708 checkAttributes!q{@trusted}; assert(0);
3710 @trusted void getOption(SocketOptionLevel level, SocketOption option, out Duration result)
3712 checkAttributes!q{@trusted};
3714 @trusted void setOption(SocketOptionLevel level, SocketOption option, void[] value)
3716 checkAttributes!q{@trusted};
3718 @trusted void setOption(SocketOptionLevel level, SocketOption option, int32_t value)
3720 checkAttributes!q{@trusted};
3722 @trusted void setOption(SocketOptionLevel level, SocketOption option, Linger value)
3724 checkAttributes!q{@trusted};
3726 @trusted void setOption(SocketOptionLevel level, SocketOption option, Duration value)
3728 checkAttributes!q{@trusted};
3730 @safe string getErrorText()
3732 checkAttributes!q{@safe}; assert(0);
3734 @trusted void setKeepAlive(int time, int interval)
3736 checkAttributes!q{@trusted};
3738 protected pure nothrow @safe Address createAddress()
3740 checkAttributes!q{pure nothrow @safe}; assert(0);
3747 * Creates a pair of connected sockets.
3749 * The two sockets are indistinguishable.
3751 * Throws: `SocketException` if creation of the sockets fails.
3753 Socket[2] socketPair() @trusted
3755 version (Posix)
3757 int[2] socks;
3758 if (socketpair(AF_UNIX, SOCK_STREAM, 0, socks) == -1)
3759 throw new SocketOSException("Unable to create socket pair");
3761 Socket toSocket(size_t id)
3763 auto s = new Socket;
3764 s.setSock(cast(socket_t) socks[id]);
3765 s._family = AddressFamily.UNIX;
3766 return s;
3769 return [toSocket(0), toSocket(1)];
3771 else version (Windows)
3773 // We do not have socketpair() on Windows, just manually create a
3774 // pair of sockets connected over some localhost port.
3775 Socket[2] result;
3777 auto listener = new TcpSocket();
3778 listener.setOption(SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, true);
3779 listener.bind(new InternetAddress(INADDR_LOOPBACK, InternetAddress.PORT_ANY));
3780 auto addr = listener.localAddress;
3781 listener.listen(1);
3783 result[0] = new TcpSocket(addr);
3784 result[1] = listener.accept();
3786 listener.close();
3787 return result;
3789 else
3790 static assert(false);
3794 @safe unittest
3796 immutable ubyte[] data = [1, 2, 3, 4];
3797 auto pair = socketPair();
3798 scope(exit) foreach (s; pair) s.close();
3800 pair[0].send(data);
3802 auto buf = new ubyte[data.length];
3803 pair[1].receive(buf);
3804 assert(buf == data);