Fix build on sparc64-linux-gnu.
[official-gcc.git] / libphobos / src / std / socket.d
blobc008d62c9a4eb427faa14934575b88e1f97966ba
1 // Written in the D programming language
3 /*
4 Copyright (C) 2004-2011 Christopher E. Miller
6 Boost Software License - Version 1.0 - August 17th, 2003
8 Permission is hereby granted, free of charge, to any person or organization
9 obtaining a copy of the software and accompanying documentation covered by
10 this license (the "Software") to use, reproduce, display, distribute,
11 execute, and transmit the Software, and to prepare derivative works of the
12 Software, and to permit third-parties to whom the Software is furnished to
13 do so, all subject to the following:
15 The copyright notices in the Software and this entire statement, including
16 the above license grant, this restriction and the following disclaimer,
17 must be included in all copies of the Software, in whole or in part, and
18 all derivative works of the Software, unless such copies or derivative
19 works are solely in the form of machine-executable object code generated by
20 a source language processor.
22 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
23 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
24 FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT
25 SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE
26 FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE,
27 ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
28 DEALINGS IN THE SOFTWARE.
30 socket.d 1.4
31 Jan 2011
33 Thanks to Benjamin Herr for his assistance.
36 /**
37 * Socket primitives.
38 * Example: See $(SAMPLESRC listener.d) and $(SAMPLESRC htmlget.d)
39 * License: $(HTTP www.boost.org/LICENSE_1_0.txt, Boost License 1.0).
40 * Authors: Christopher E. Miller, $(HTTP klickverbot.at, David Nadlinger),
41 * $(HTTP thecybershadow.net, Vladimir Panteleev)
42 * Source: $(PHOBOSSRC std/_socket.d)
45 module std.socket;
47 import core.stdc.stdint, core.stdc.stdlib, core.stdc.string, std.conv, std.string;
49 import core.stdc.config;
50 import core.time : dur, Duration;
51 import std.exception;
53 import std.internal.cstring;
56 @safe:
58 version (Windows)
60 version (GNU) {}
61 else
63 pragma (lib, "ws2_32.lib");
64 pragma (lib, "wsock32.lib");
67 import core.sys.windows.windows, std.windows.syserror;
68 public import core.sys.windows.winsock2;
69 private alias _ctimeval = core.sys.windows.winsock2.timeval;
70 private alias _clinger = core.sys.windows.winsock2.linger;
72 enum socket_t : SOCKET { INVALID_SOCKET }
73 private const int _SOCKET_ERROR = SOCKET_ERROR;
76 private int _lasterr() nothrow @nogc
78 return WSAGetLastError();
81 else version (Posix)
83 version (linux)
85 enum : int
87 TCP_KEEPIDLE = 4,
88 TCP_KEEPINTVL = 5
92 import core.sys.posix.arpa.inet;
93 import core.sys.posix.fcntl;
94 import core.sys.posix.netdb;
95 import core.sys.posix.netinet.in_;
96 import core.sys.posix.netinet.tcp;
97 import core.sys.posix.sys.select;
98 import core.sys.posix.sys.socket;
99 import core.sys.posix.sys.time;
100 import core.sys.posix.sys.un : sockaddr_un;
101 import core.sys.posix.unistd;
102 private alias _ctimeval = core.sys.posix.sys.time.timeval;
103 private alias _clinger = core.sys.posix.sys.socket.linger;
105 import core.stdc.errno;
107 enum socket_t : int32_t { init = -1 }
108 private const int _SOCKET_ERROR = -1;
110 private enum : int
112 SD_RECEIVE = SHUT_RD,
113 SD_SEND = SHUT_WR,
114 SD_BOTH = SHUT_RDWR
117 private int _lasterr() nothrow @nogc
119 return errno;
122 else
124 static assert(0); // No socket support yet.
127 version (unittest)
129 static assert(is(uint32_t == uint));
130 static assert(is(uint16_t == ushort));
132 import std.stdio : writefln;
134 // Print a message on exception instead of failing the unittest.
135 private void softUnittest(void delegate() @safe test, int line = __LINE__) @trusted
138 test();
139 catch (Throwable e)
141 writefln(" --- std.socket(%d) test fails depending on environment ---", line);
142 writefln(" (%s)", e);
147 /// Base exception thrown by $(D std.socket).
148 class SocketException: Exception
150 mixin basicExceptionCtors;
155 * Needs to be public so that SocketOSException can be thrown outside of
156 * std.socket (since it uses it as a default argument), but it probably doesn't
157 * need to actually show up in the docs, since there's not really any public
158 * need for it outside of being a default argument.
160 string formatSocketError(int err) @trusted
162 version (Posix)
164 char[80] buf;
165 const(char)* cs;
166 version (CRuntime_Glibc)
168 cs = strerror_r(err, buf.ptr, buf.length);
170 else version (OSX)
172 auto errs = strerror_r(err, buf.ptr, buf.length);
173 if (errs == 0)
174 cs = buf.ptr;
175 else
176 return "Socket error " ~ to!string(err);
178 else version (FreeBSD)
180 auto errs = strerror_r(err, buf.ptr, buf.length);
181 if (errs == 0)
182 cs = buf.ptr;
183 else
184 return "Socket error " ~ to!string(err);
186 else version (NetBSD)
188 auto errs = strerror_r(err, buf.ptr, buf.length);
189 if (errs == 0)
190 cs = buf.ptr;
191 else
192 return "Socket error " ~ to!string(err);
194 else version (Solaris)
196 auto errs = strerror_r(err, buf.ptr, buf.length);
197 if (errs == 0)
198 cs = buf.ptr;
199 else
200 return "Socket error " ~ to!string(err);
202 else version (CRuntime_Bionic)
204 auto errs = strerror_r(err, buf.ptr, buf.length);
205 if (errs == 0)
206 cs = buf.ptr;
207 else
208 return "Socket error " ~ to!string(err);
210 else
211 static assert(0);
213 auto len = strlen(cs);
215 if (cs[len - 1] == '\n')
216 len--;
217 if (cs[len - 1] == '\r')
218 len--;
219 return cs[0 .. len].idup;
221 else
222 version (Windows)
224 return sysErrorString(err);
226 else
227 return "Socket error " ~ to!string(err);
230 /// Retrieve the error message for the most recently encountered network error.
231 @property string lastSocketError()
233 return formatSocketError(_lasterr());
237 * Socket exceptions representing network errors reported by the operating
238 * system.
240 class SocketOSException: SocketException
242 int errorCode; /// Platform-specific error code.
245 this(string msg,
246 string file = __FILE__,
247 size_t line = __LINE__,
248 Throwable next = null,
249 int err = _lasterr(),
250 string function(int) @trusted errorFormatter = &formatSocketError)
252 errorCode = err;
254 if (msg.length)
255 super(msg ~ ": " ~ errorFormatter(err), file, line, next);
256 else
257 super(errorFormatter(err), file, line, next);
261 this(string msg,
262 Throwable next,
263 string file = __FILE__,
264 size_t line = __LINE__,
265 int err = _lasterr(),
266 string function(int) @trusted errorFormatter = &formatSocketError)
268 this(msg, file, line, next, err, errorFormatter);
272 this(string msg,
273 int err,
274 string function(int) @trusted errorFormatter = &formatSocketError,
275 string file = __FILE__,
276 size_t line = __LINE__,
277 Throwable next = null)
279 this(msg, file, line, next, err, errorFormatter);
283 /// Socket exceptions representing invalid parameters specified by user code.
284 class SocketParameterException: SocketException
286 mixin basicExceptionCtors;
290 * Socket exceptions representing attempts to use network capabilities not
291 * available on the current system.
293 class SocketFeatureException: SocketException
295 mixin basicExceptionCtors;
300 * Returns:
301 * $(D true) if the last socket operation failed because the socket
302 * was in non-blocking mode and the operation would have blocked.
304 bool wouldHaveBlocked() nothrow @nogc
306 version (Windows)
307 return _lasterr() == WSAEWOULDBLOCK;
308 else version (Posix)
309 return _lasterr() == EAGAIN;
310 else
311 static assert(0);
315 private immutable
317 typeof(&getnameinfo) getnameinfoPointer;
318 typeof(&getaddrinfo) getaddrinfoPointer;
319 typeof(&freeaddrinfo) freeaddrinfoPointer;
322 shared static this() @system
324 version (Windows)
326 WSADATA wd;
328 // Winsock will still load if an older version is present.
329 // The version is just a request.
330 int val;
331 val = WSAStartup(0x2020, &wd);
332 if (val) // Request Winsock 2.2 for IPv6.
333 throw new SocketOSException("Unable to initialize socket library", val);
335 // These functions may not be present on older Windows versions.
336 // See the comment in InternetAddress.toHostNameString() for details.
337 auto ws2Lib = GetModuleHandleA("ws2_32.dll");
338 if (ws2Lib)
340 getnameinfoPointer = cast(typeof(getnameinfoPointer))
341 GetProcAddress(ws2Lib, "getnameinfo");
342 getaddrinfoPointer = cast(typeof(getaddrinfoPointer))
343 GetProcAddress(ws2Lib, "getaddrinfo");
344 freeaddrinfoPointer = cast(typeof(freeaddrinfoPointer))
345 GetProcAddress(ws2Lib, "freeaddrinfo");
348 else version (Posix)
350 getnameinfoPointer = &getnameinfo;
351 getaddrinfoPointer = &getaddrinfo;
352 freeaddrinfoPointer = &freeaddrinfo;
357 shared static ~this() @system nothrow @nogc
359 version (Windows)
361 WSACleanup();
366 * The communication domain used to resolve an address.
368 enum AddressFamily: int
370 UNSPEC = AF_UNSPEC, /// Unspecified address family
371 UNIX = AF_UNIX, /// Local communication
372 INET = AF_INET, /// Internet Protocol version 4
373 IPX = AF_IPX, /// Novell IPX
374 APPLETALK = AF_APPLETALK, /// AppleTalk
375 INET6 = AF_INET6, /// Internet Protocol version 6
380 * Communication semantics
382 enum SocketType: int
384 STREAM = SOCK_STREAM, /// Sequenced, reliable, two-way communication-based byte streams
385 DGRAM = SOCK_DGRAM, /// Connectionless, unreliable datagrams with a fixed maximum length; data may be lost or arrive out of order
386 RAW = SOCK_RAW, /// Raw protocol access
387 RDM = SOCK_RDM, /// Reliably-delivered message datagrams
388 SEQPACKET = SOCK_SEQPACKET, /// Sequenced, reliable, two-way connection-based datagrams with a fixed maximum length
393 * Protocol
395 enum ProtocolType: int
397 IP = IPPROTO_IP, /// Internet Protocol version 4
398 ICMP = IPPROTO_ICMP, /// Internet Control Message Protocol
399 IGMP = IPPROTO_IGMP, /// Internet Group Management Protocol
400 GGP = IPPROTO_GGP, /// Gateway to Gateway Protocol
401 TCP = IPPROTO_TCP, /// Transmission Control Protocol
402 PUP = IPPROTO_PUP, /// PARC Universal Packet Protocol
403 UDP = IPPROTO_UDP, /// User Datagram Protocol
404 IDP = IPPROTO_IDP, /// Xerox NS protocol
405 RAW = IPPROTO_RAW, /// Raw IP packets
406 IPV6 = IPPROTO_IPV6, /// Internet Protocol version 6
411 * $(D Protocol) is a class for retrieving protocol information.
413 * Example:
414 * ---
415 * auto proto = new Protocol;
416 * writeln("About protocol TCP:");
417 * if (proto.getProtocolByType(ProtocolType.TCP))
419 * writefln(" Name: %s", proto.name);
420 * foreach (string s; proto.aliases)
421 * writefln(" Alias: %s", s);
423 * else
424 * writeln(" No information found");
425 * ---
427 class Protocol
429 /// These members are populated when one of the following functions are called successfully:
430 ProtocolType type;
431 string name; /// ditto
432 string[] aliases; /// ditto
435 void populate(protoent* proto) @system pure nothrow
437 type = cast(ProtocolType) proto.p_proto;
438 name = to!string(proto.p_name);
440 int i;
441 for (i = 0;; i++)
443 if (!proto.p_aliases[i])
444 break;
447 if (i)
449 aliases = new string[i];
450 for (i = 0; i != aliases.length; i++)
452 aliases[i] =
453 to!string(proto.p_aliases[i]);
456 else
458 aliases = null;
462 /** Returns: false on failure */
463 bool getProtocolByName(in char[] name) @trusted nothrow
465 protoent* proto;
466 proto = getprotobyname(name.tempCString());
467 if (!proto)
468 return false;
469 populate(proto);
470 return true;
474 /** Returns: false on failure */
475 // Same as getprotobynumber().
476 bool getProtocolByType(ProtocolType type) @trusted nothrow
478 protoent* proto;
479 proto = getprotobynumber(type);
480 if (!proto)
481 return false;
482 populate(proto);
483 return true;
488 // Skip this test on Android because getprotobyname/number are
489 // unimplemented in bionic.
490 version (CRuntime_Bionic) {} else
491 @safe unittest
493 softUnittest({
494 Protocol proto = new Protocol;
495 assert(proto.getProtocolByType(ProtocolType.TCP));
496 //writeln("About protocol TCP:");
497 //writefln("\tName: %s", proto.name);
498 // foreach (string s; proto.aliases)
499 // {
500 // writefln("\tAlias: %s", s);
501 // }
502 assert(proto.name == "tcp");
503 assert(proto.aliases.length == 1 && proto.aliases[0] == "TCP");
509 * $(D Service) is a class for retrieving service information.
511 * Example:
512 * ---
513 * auto serv = new Service;
514 * writeln("About service epmap:");
515 * if (serv.getServiceByName("epmap", "tcp"))
517 * writefln(" Service: %s", serv.name);
518 * writefln(" Port: %d", serv.port);
519 * writefln(" Protocol: %s", serv.protocolName);
520 * foreach (string s; serv.aliases)
521 * writefln(" Alias: %s", s);
523 * else
524 * writefln(" No service for epmap.");
525 * ---
527 class Service
529 /// These members are populated when one of the following functions are called successfully:
530 string name;
531 string[] aliases; /// ditto
532 ushort port; /// ditto
533 string protocolName; /// ditto
536 void populate(servent* serv) @system pure nothrow
538 name = to!string(serv.s_name);
539 port = ntohs(cast(ushort) serv.s_port);
540 protocolName = to!string(serv.s_proto);
542 int i;
543 for (i = 0;; i++)
545 if (!serv.s_aliases[i])
546 break;
549 if (i)
551 aliases = new string[i];
552 for (i = 0; i != aliases.length; i++)
554 aliases[i] =
555 to!string(serv.s_aliases[i]);
558 else
560 aliases = null;
565 * If a protocol name is omitted, any protocol will be matched.
566 * Returns: false on failure.
568 bool getServiceByName(in char[] name, in char[] protocolName = null) @trusted nothrow
570 servent* serv;
571 serv = getservbyname(name.tempCString(), protocolName.tempCString());
572 if (!serv)
573 return false;
574 populate(serv);
575 return true;
579 /// ditto
580 bool getServiceByPort(ushort port, in char[] protocolName = null) @trusted nothrow
582 servent* serv;
583 serv = getservbyport(port, protocolName.tempCString());
584 if (!serv)
585 return false;
586 populate(serv);
587 return true;
592 @safe unittest
594 softUnittest({
595 Service serv = new Service;
596 if (serv.getServiceByName("epmap", "tcp"))
598 // writefln("About service epmap:");
599 // writefln("\tService: %s", serv.name);
600 // writefln("\tPort: %d", serv.port);
601 // writefln("\tProtocol: %s", serv.protocolName);
602 // foreach (string s; serv.aliases)
603 // {
604 // writefln("\tAlias: %s", s);
605 // }
606 // For reasons unknown this is loc-srv on Wine and epmap on Windows
607 assert(serv.name == "loc-srv" || serv.name == "epmap", serv.name);
608 assert(serv.port == 135);
609 assert(serv.protocolName == "tcp");
611 else
613 writefln("No service for epmap.");
619 private mixin template socketOSExceptionCtors()
622 this(string msg, string file = __FILE__, size_t line = __LINE__,
623 Throwable next = null, int err = _lasterr())
625 super(msg, file, line, next, err);
629 this(string msg, Throwable next, string file = __FILE__,
630 size_t line = __LINE__, int err = _lasterr())
632 super(msg, next, file, line, err);
636 this(string msg, int err, string file = __FILE__, size_t line = __LINE__,
637 Throwable next = null)
639 super(msg, next, file, line, err);
645 * Class for exceptions thrown from an `InternetHost`.
647 class HostException: SocketOSException
649 mixin socketOSExceptionCtors;
653 * `InternetHost` is a class for resolving IPv4 addresses.
655 * Consider using `getAddress`, `parseAddress` and `Address` methods
656 * instead of using this class directly.
658 class InternetHost
660 /// These members are populated when one of the following functions are called successfully:
661 string name;
662 string[] aliases; /// ditto
663 uint[] addrList; /// ditto
666 void validHostent(in hostent* he)
668 if (he.h_addrtype != cast(int) AddressFamily.INET || he.h_length != 4)
669 throw new HostException("Address family mismatch");
673 void populate(hostent* he) @system pure nothrow
675 int i;
676 char* p;
678 name = to!string(he.h_name);
680 for (i = 0;; i++)
682 p = he.h_aliases[i];
683 if (!p)
684 break;
687 if (i)
689 aliases = new string[i];
690 for (i = 0; i != aliases.length; i++)
692 aliases[i] =
693 to!string(he.h_aliases[i]);
696 else
698 aliases = null;
701 for (i = 0;; i++)
703 p = he.h_addr_list[i];
704 if (!p)
705 break;
708 if (i)
710 addrList = new uint[i];
711 for (i = 0; i != addrList.length; i++)
713 addrList[i] = ntohl(*(cast(uint*) he.h_addr_list[i]));
716 else
718 addrList = null;
722 private bool getHostNoSync(string opMixin, T)(T param) @system
724 mixin(opMixin);
725 if (!he)
726 return false;
727 validHostent(he);
728 populate(he);
729 return true;
732 version (Windows)
733 alias getHost = getHostNoSync;
734 else
736 // posix systems use global state for return value, so we
737 // must synchronize across all threads
738 private bool getHost(string opMixin, T)(T param) @system
740 synchronized(this.classinfo)
741 return getHostNoSync!(opMixin, T)(param);
746 * Resolve host name.
747 * Returns: false if unable to resolve.
749 bool getHostByName(in char[] name) @trusted
751 static if (is(typeof(gethostbyname_r)))
753 return getHostNoSync!q{
754 hostent he_v;
755 hostent* he;
756 ubyte[256] buffer_v = void;
757 auto buffer = buffer_v[];
758 auto param_zTmp = param.tempCString();
759 while (true)
761 he = &he_v;
762 int errno;
763 if (gethostbyname_r(param_zTmp, he, buffer.ptr, buffer.length, &he, &errno) == ERANGE)
764 buffer.length = buffer.length * 2;
765 else
766 break;
768 }(name);
770 else
772 return getHost!q{
773 auto he = gethostbyname(param.tempCString());
774 }(name);
779 * Resolve IPv4 address number.
781 * Params:
782 * addr = The IPv4 address to resolve, in host byte order.
783 * Returns:
784 * false if unable to resolve.
786 bool getHostByAddr(uint addr) @trusted
788 return getHost!q{
789 auto x = htonl(param);
790 auto he = gethostbyaddr(&x, 4, cast(int) AddressFamily.INET);
791 }(addr);
795 * Same as previous, but addr is an IPv4 address string in the
796 * dotted-decimal form $(I a.b.c.d).
797 * Returns: false if unable to resolve.
799 bool getHostByAddr(in char[] addr) @trusted
801 return getHost!q{
802 auto x = inet_addr(param.tempCString());
803 enforce(x != INADDR_NONE,
804 new SocketParameterException("Invalid IPv4 address"));
805 auto he = gethostbyaddr(&x, 4, cast(int) AddressFamily.INET);
806 }(addr);
811 @safe unittest
813 InternetHost ih = new InternetHost;
815 ih.getHostByAddr(0x7F_00_00_01);
816 assert(ih.addrList[0] == 0x7F_00_00_01);
817 ih.getHostByAddr("127.0.0.1");
818 assert(ih.addrList[0] == 0x7F_00_00_01);
820 if (!ih.getHostByName("www.digitalmars.com"))
821 return; // don't fail if not connected to internet
823 assert(ih.addrList.length);
824 InternetAddress ia = new InternetAddress(ih.addrList[0], InternetAddress.PORT_ANY);
825 assert(ih.name == "www.digitalmars.com" || ih.name == "digitalmars.com",
826 ih.name);
828 assert(ih.getHostByAddr(ih.addrList[0]));
829 string getHostNameFromInt = ih.name.dup;
831 assert(ih.getHostByAddr(ia.toAddrString()));
832 string getHostNameFromStr = ih.name.dup;
834 assert(getHostNameFromInt == getHostNameFromStr);
838 /// Holds information about a socket _address retrieved by $(D getAddressInfo).
839 struct AddressInfo
841 AddressFamily family; /// Address _family
842 SocketType type; /// Socket _type
843 ProtocolType protocol; /// Protocol
844 Address address; /// Socket _address
845 string canonicalName; /// Canonical name, when $(D AddressInfoFlags.CANONNAME) is used.
849 * A subset of flags supported on all platforms with getaddrinfo.
850 * Specifies option flags for $(D getAddressInfo).
852 enum AddressInfoFlags: int
854 /// The resulting addresses will be used in a call to $(D Socket.bind).
855 PASSIVE = AI_PASSIVE,
857 /// The canonical name is returned in $(D canonicalName) member in the first $(D AddressInfo).
858 CANONNAME = AI_CANONNAME,
861 * The $(D node) parameter passed to $(D getAddressInfo) must be a numeric string.
862 * This will suppress any potentially lengthy network host address lookups.
864 NUMERICHOST = AI_NUMERICHOST,
869 * On POSIX, getaddrinfo uses its own error codes, and thus has its own
870 * formatting function.
872 private string formatGaiError(int err) @trusted
874 version (Windows)
876 return sysErrorString(err);
878 else
880 synchronized
881 return to!string(gai_strerror(err));
886 * Provides _protocol-independent translation from host names to socket
887 * addresses. If advanced functionality is not required, consider using
888 * $(D getAddress) for compatibility with older systems.
890 * Returns: Array with one $(D AddressInfo) per socket address.
892 * Throws: $(D SocketOSException) on failure, or $(D SocketFeatureException)
893 * if this functionality is not available on the current system.
895 * Params:
896 * node = string containing host name or numeric address
897 * options = optional additional parameters, identified by type:
898 * $(UL $(LI $(D string) - service name or port number)
899 * $(LI $(D AddressInfoFlags) - option flags)
900 * $(LI $(D AddressFamily) - address family to filter by)
901 * $(LI $(D SocketType) - socket type to filter by)
902 * $(LI $(D ProtocolType) - protocol to filter by))
904 * Example:
905 * ---
906 * // Roundtrip DNS resolution
907 * auto results = getAddressInfo("www.digitalmars.com");
908 * assert(results[0].address.toHostNameString() ==
909 * "digitalmars.com");
911 * // Canonical name
912 * results = getAddressInfo("www.digitalmars.com",
913 * AddressInfoFlags.CANONNAME);
914 * assert(results[0].canonicalName == "digitalmars.com");
916 * // IPv6 resolution
917 * results = getAddressInfo("ipv6.google.com");
918 * assert(results[0].family == AddressFamily.INET6);
920 * // Multihomed resolution
921 * results = getAddressInfo("google.com");
922 * assert(results.length > 1);
924 * // Parsing IPv4
925 * results = getAddressInfo("127.0.0.1",
926 * AddressInfoFlags.NUMERICHOST);
927 * assert(results.length && results[0].family ==
928 * AddressFamily.INET);
930 * // Parsing IPv6
931 * results = getAddressInfo("::1",
932 * AddressInfoFlags.NUMERICHOST);
933 * assert(results.length && results[0].family ==
934 * AddressFamily.INET6);
935 * ---
937 AddressInfo[] getAddressInfo(T...)(in char[] node, T options)
939 const(char)[] service = null;
940 addrinfo hints;
941 hints.ai_family = AF_UNSPEC;
943 foreach (option; options)
945 static if (is(typeof(option) : const(char)[]))
946 service = option;
947 else
948 static if (is(typeof(option) == AddressInfoFlags))
949 hints.ai_flags |= option;
950 else
951 static if (is(typeof(option) == AddressFamily))
952 hints.ai_family = option;
953 else
954 static if (is(typeof(option) == SocketType))
955 hints.ai_socktype = option;
956 else
957 static if (is(typeof(option) == ProtocolType))
958 hints.ai_protocol = option;
959 else
960 static assert(0, "Unknown getAddressInfo option type: " ~ typeof(option).stringof);
963 return () @trusted { return getAddressInfoImpl(node, service, &hints); }();
966 @system unittest
968 struct Oops
970 const(char[]) breakSafety()
972 *cast(int*) 0xcafebabe = 0xdeadbeef;
973 return null;
975 alias breakSafety this;
977 assert(!__traits(compiles, () {
978 getAddressInfo("", Oops.init);
979 }), "getAddressInfo breaks @safe");
982 private AddressInfo[] getAddressInfoImpl(in char[] node, in char[] service, addrinfo* hints) @system
984 import std.array : appender;
986 if (getaddrinfoPointer && freeaddrinfoPointer)
988 addrinfo* ai_res;
990 int ret = getaddrinfoPointer(
991 node.tempCString(),
992 service.tempCString(),
993 hints, &ai_res);
994 enforce(ret == 0, new SocketOSException("getaddrinfo error", ret, &formatGaiError));
995 scope(exit) freeaddrinfoPointer(ai_res);
997 auto result = appender!(AddressInfo[])();
999 // Use const to force UnknownAddressReference to copy the sockaddr.
1000 for (const(addrinfo)* ai = ai_res; ai; ai = ai.ai_next)
1001 result ~= AddressInfo(
1002 cast(AddressFamily) ai.ai_family,
1003 cast(SocketType ) ai.ai_socktype,
1004 cast(ProtocolType ) ai.ai_protocol,
1005 new UnknownAddressReference(ai.ai_addr, cast(socklen_t) ai.ai_addrlen),
1006 ai.ai_canonname ? to!string(ai.ai_canonname) : null);
1008 assert(result.data.length > 0);
1009 return result.data;
1012 throw new SocketFeatureException("Address info lookup is not available " ~
1013 "on this system.");
1017 @safe unittest
1019 softUnittest({
1020 if (getaddrinfoPointer)
1022 // Roundtrip DNS resolution
1023 auto results = getAddressInfo("www.digitalmars.com");
1024 assert(results[0].address.toHostNameString() == "digitalmars.com");
1026 // Canonical name
1027 results = getAddressInfo("www.digitalmars.com",
1028 AddressInfoFlags.CANONNAME);
1029 assert(results[0].canonicalName == "digitalmars.com");
1031 // IPv6 resolution
1032 //results = getAddressInfo("ipv6.google.com");
1033 //assert(results[0].family == AddressFamily.INET6);
1035 // Multihomed resolution
1036 //results = getAddressInfo("google.com");
1037 //assert(results.length > 1);
1039 // Parsing IPv4
1040 results = getAddressInfo("127.0.0.1", AddressInfoFlags.NUMERICHOST);
1041 assert(results.length && results[0].family == AddressFamily.INET);
1043 // Parsing IPv6
1044 results = getAddressInfo("::1", AddressInfoFlags.NUMERICHOST);
1045 assert(results.length && results[0].family == AddressFamily.INET6);
1049 if (getaddrinfoPointer)
1051 auto results = getAddressInfo(null, "1234", AddressInfoFlags.PASSIVE,
1052 SocketType.STREAM, ProtocolType.TCP, AddressFamily.INET);
1053 assert(results.length == 1 && results[0].address.toString() == "0.0.0.0:1234");
1058 private ushort serviceToPort(in char[] service)
1060 if (service == "")
1061 return InternetAddress.PORT_ANY;
1062 else
1063 if (isNumeric(service))
1064 return to!ushort(service);
1065 else
1067 auto s = new Service();
1068 s.getServiceByName(service);
1069 return s.port;
1074 * Provides _protocol-independent translation from host names to socket
1075 * addresses. Uses $(D getAddressInfo) if the current system supports it,
1076 * and $(D InternetHost) otherwise.
1078 * Returns: Array with one $(D Address) instance per socket address.
1080 * Throws: $(D SocketOSException) on failure.
1082 * Example:
1083 * ---
1084 * writeln("Resolving www.digitalmars.com:");
1085 * try
1087 * auto addresses = getAddress("www.digitalmars.com");
1088 * foreach (address; addresses)
1089 * writefln(" IP: %s", address.toAddrString());
1091 * catch (SocketException e)
1092 * writefln(" Lookup failed: %s", e.msg);
1093 * ---
1095 Address[] getAddress(in char[] hostname, in char[] service = null)
1097 if (getaddrinfoPointer && freeaddrinfoPointer)
1099 // use getAddressInfo
1100 auto infos = getAddressInfo(hostname, service);
1101 Address[] results;
1102 results.length = infos.length;
1103 foreach (i, ref result; results)
1104 result = infos[i].address;
1105 return results;
1107 else
1108 return getAddress(hostname, serviceToPort(service));
1111 /// ditto
1112 Address[] getAddress(in char[] hostname, ushort port)
1114 if (getaddrinfoPointer && freeaddrinfoPointer)
1115 return getAddress(hostname, to!string(port));
1116 else
1118 // use getHostByName
1119 auto ih = new InternetHost;
1120 if (!ih.getHostByName(hostname))
1121 throw new AddressException(
1122 text("Unable to resolve host '", hostname, "'"));
1124 Address[] results;
1125 foreach (uint addr; ih.addrList)
1126 results ~= new InternetAddress(addr, port);
1127 return results;
1132 @safe unittest
1134 softUnittest({
1135 auto addresses = getAddress("63.105.9.61");
1136 assert(addresses.length && addresses[0].toAddrString() == "63.105.9.61");
1138 if (getaddrinfoPointer)
1140 // test via gethostbyname
1141 auto getaddrinfoPointerBackup = getaddrinfoPointer;
1142 cast() getaddrinfoPointer = null;
1143 scope(exit) cast() getaddrinfoPointer = getaddrinfoPointerBackup;
1145 addresses = getAddress("63.105.9.61");
1146 assert(addresses.length && addresses[0].toAddrString() == "63.105.9.61");
1153 * Provides _protocol-independent parsing of network addresses. Does not
1154 * attempt name resolution. Uses $(D getAddressInfo) with
1155 * $(D AddressInfoFlags.NUMERICHOST) if the current system supports it, and
1156 * $(D InternetAddress) otherwise.
1158 * Returns: An $(D Address) instance representing specified address.
1160 * Throws: $(D SocketException) on failure.
1162 * Example:
1163 * ---
1164 * writeln("Enter IP address:");
1165 * string ip = readln().chomp();
1166 * try
1168 * Address address = parseAddress(ip);
1169 * writefln("Looking up reverse of %s:",
1170 * address.toAddrString());
1171 * try
1173 * string reverse = address.toHostNameString();
1174 * if (reverse)
1175 * writefln(" Reverse name: %s", reverse);
1176 * else
1177 * writeln(" Reverse hostname not found.");
1179 * catch (SocketException e)
1180 * writefln(" Lookup error: %s", e.msg);
1182 * catch (SocketException e)
1184 * writefln(" %s is not a valid IP address: %s",
1185 * ip, e.msg);
1187 * ---
1189 Address parseAddress(in char[] hostaddr, in char[] service = null)
1191 if (getaddrinfoPointer && freeaddrinfoPointer)
1192 return getAddressInfo(hostaddr, service, AddressInfoFlags.NUMERICHOST)[0].address;
1193 else
1194 return parseAddress(hostaddr, serviceToPort(service));
1197 /// ditto
1198 Address parseAddress(in char[] hostaddr, ushort port)
1200 if (getaddrinfoPointer && freeaddrinfoPointer)
1201 return parseAddress(hostaddr, to!string(port));
1202 else
1204 auto in4_addr = InternetAddress.parse(hostaddr);
1205 enforce(in4_addr != InternetAddress.ADDR_NONE,
1206 new SocketParameterException("Invalid IP address"));
1207 return new InternetAddress(in4_addr, port);
1212 @safe unittest
1214 softUnittest({
1215 auto address = parseAddress("63.105.9.61");
1216 assert(address.toAddrString() == "63.105.9.61");
1218 if (getaddrinfoPointer)
1220 // test via inet_addr
1221 auto getaddrinfoPointerBackup = getaddrinfoPointer;
1222 cast() getaddrinfoPointer = null;
1223 scope(exit) cast() getaddrinfoPointer = getaddrinfoPointerBackup;
1225 address = parseAddress("63.105.9.61");
1226 assert(address.toAddrString() == "63.105.9.61");
1229 assert(collectException!SocketException(parseAddress("Invalid IP address")));
1235 * Class for exceptions thrown from an $(D Address).
1237 class AddressException: SocketOSException
1239 mixin socketOSExceptionCtors;
1244 * $(D Address) is an abstract class for representing a socket addresses.
1246 * Example:
1247 * ---
1248 * writeln("About www.google.com port 80:");
1249 * try
1251 * Address[] addresses = getAddress("www.google.com", 80);
1252 * writefln(" %d addresses found.", addresses.length);
1253 * foreach (int i, Address a; addresses)
1255 * writefln(" Address %d:", i+1);
1256 * writefln(" IP address: %s", a.toAddrString());
1257 * writefln(" Hostname: %s", a.toHostNameString());
1258 * writefln(" Port: %s", a.toPortString());
1259 * writefln(" Service name: %s",
1260 * a.toServiceNameString());
1263 * catch (SocketException e)
1264 * writefln(" Lookup error: %s", e.msg);
1265 * ---
1267 abstract class Address
1269 /// Returns pointer to underlying $(D sockaddr) structure.
1270 abstract @property sockaddr* name() pure nothrow @nogc;
1271 abstract @property const(sockaddr)* name() const pure nothrow @nogc; /// ditto
1273 /// Returns actual size of underlying $(D sockaddr) structure.
1274 abstract @property socklen_t nameLen() const pure nothrow @nogc;
1276 // Socket.remoteAddress, Socket.localAddress, and Socket.receiveFrom
1277 // use setNameLen to set the actual size of the address as returned by
1278 // getsockname, getpeername, and recvfrom, respectively.
1279 // The following implementation is sufficient for fixed-length addresses,
1280 // and ensures that the length is not changed.
1281 // Must be overridden for variable-length addresses.
1282 protected void setNameLen(socklen_t len)
1284 if (len != this.nameLen)
1285 throw new AddressException(
1286 format("%s expects address of length %d, not %d", typeid(this),
1287 this.nameLen, len), 0);
1290 /// Family of this address.
1291 @property AddressFamily addressFamily() const pure nothrow @nogc
1293 return cast(AddressFamily) name.sa_family;
1296 // Common code for toAddrString and toHostNameString
1297 private string toHostString(bool numeric) @trusted const
1299 // getnameinfo() is the recommended way to perform a reverse (name)
1300 // lookup on both Posix and Windows. However, it is only available
1301 // on Windows XP and above, and not included with the WinSock import
1302 // libraries shipped with DMD. Thus, we check for getnameinfo at
1303 // runtime in the shared module constructor, and use it if it's
1304 // available in the base class method. Classes for specific network
1305 // families (e.g. InternetHost) override this method and use a
1306 // deprecated, albeit commonly-available method when getnameinfo()
1307 // is not available.
1308 // http://technet.microsoft.com/en-us/library/aa450403.aspx
1309 if (getnameinfoPointer)
1311 auto buf = new char[NI_MAXHOST];
1312 auto ret = getnameinfoPointer(
1313 name, nameLen,
1314 buf.ptr, cast(uint) buf.length,
1315 null, 0,
1316 numeric ? NI_NUMERICHOST : NI_NAMEREQD);
1318 if (!numeric)
1320 if (ret == EAI_NONAME)
1321 return null;
1322 version (Windows)
1323 if (ret == WSANO_DATA)
1324 return null;
1327 enforce(ret == 0, new AddressException("Could not get " ~
1328 (numeric ? "host address" : "host name")));
1329 return assumeUnique(buf[0 .. strlen(buf.ptr)]);
1332 throw new SocketFeatureException((numeric ? "Host address" : "Host name") ~
1333 " lookup for this address family is not available on this system.");
1336 // Common code for toPortString and toServiceNameString
1337 private string toServiceString(bool numeric) @trusted const
1339 // See toHostNameString() for details about getnameinfo().
1340 if (getnameinfoPointer)
1342 auto buf = new char[NI_MAXSERV];
1343 enforce(getnameinfoPointer(
1344 name, nameLen,
1345 null, 0,
1346 buf.ptr, cast(uint) buf.length,
1347 numeric ? NI_NUMERICSERV : NI_NAMEREQD
1348 ) == 0, new AddressException("Could not get " ~
1349 (numeric ? "port number" : "service name")));
1350 return assumeUnique(buf[0 .. strlen(buf.ptr)]);
1353 throw new SocketFeatureException((numeric ? "Port number" : "Service name") ~
1354 " lookup for this address family is not available on this system.");
1358 * Attempts to retrieve the host address as a human-readable string.
1360 * Throws: $(D AddressException) on failure, or $(D SocketFeatureException)
1361 * if address retrieval for this address family is not available on the
1362 * current system.
1364 string toAddrString() const
1366 return toHostString(true);
1370 * Attempts to retrieve the host name as a fully qualified domain name.
1372 * Returns: The FQDN corresponding to this $(D Address), or $(D null) if
1373 * the host name did not resolve.
1375 * Throws: $(D AddressException) on error, or $(D SocketFeatureException)
1376 * if host name lookup for this address family is not available on the
1377 * current system.
1379 string toHostNameString() const
1381 return toHostString(false);
1385 * Attempts to retrieve the numeric port number as a string.
1387 * Throws: $(D AddressException) on failure, or $(D SocketFeatureException)
1388 * if port number retrieval for this address family is not available on the
1389 * current system.
1391 string toPortString() const
1393 return toServiceString(true);
1397 * Attempts to retrieve the service name as a string.
1399 * Throws: $(D AddressException) on failure, or $(D SocketFeatureException)
1400 * if service name lookup for this address family is not available on the
1401 * current system.
1403 string toServiceNameString() const
1405 return toServiceString(false);
1408 /// Human readable string representing this address.
1409 override string toString() const
1413 string host = toAddrString();
1414 string port = toPortString();
1415 if (host.indexOf(':') >= 0)
1416 return "[" ~ host ~ "]:" ~ port;
1417 else
1418 return host ~ ":" ~ port;
1420 catch (SocketException)
1421 return "Unknown";
1426 * $(D UnknownAddress) encapsulates an unknown socket address.
1428 class UnknownAddress: Address
1430 protected:
1431 sockaddr sa;
1434 public:
1435 override @property sockaddr* name()
1437 return &sa;
1440 override @property const(sockaddr)* name() const
1442 return &sa;
1446 override @property socklen_t nameLen() const
1448 return cast(socklen_t) sa.sizeof;
1455 * $(D UnknownAddressReference) encapsulates a reference to an arbitrary
1456 * socket address.
1458 class UnknownAddressReference: Address
1460 protected:
1461 sockaddr* sa;
1462 socklen_t len;
1464 public:
1465 /// Constructs an $(D Address) with a reference to the specified $(D sockaddr).
1466 this(sockaddr* sa, socklen_t len) pure nothrow @nogc
1468 this.sa = sa;
1469 this.len = len;
1472 /// Constructs an $(D Address) with a copy of the specified $(D sockaddr).
1473 this(const(sockaddr)* sa, socklen_t len) @system pure nothrow
1475 this.sa = cast(sockaddr*) (cast(ubyte*) sa)[0 .. len].dup.ptr;
1476 this.len = len;
1479 override @property sockaddr* name()
1481 return sa;
1484 override @property const(sockaddr)* name() const
1486 return sa;
1490 override @property socklen_t nameLen() const
1492 return cast(socklen_t) len;
1498 * $(D InternetAddress) encapsulates an IPv4 (Internet Protocol version 4)
1499 * socket address.
1501 * Consider using $(D getAddress), $(D parseAddress) and $(D Address) methods
1502 * instead of using this class directly.
1504 class InternetAddress: Address
1506 protected:
1507 sockaddr_in sin;
1510 this() pure nothrow @nogc
1515 public:
1516 override @property sockaddr* name()
1518 return cast(sockaddr*)&sin;
1521 override @property const(sockaddr)* name() const
1523 return cast(const(sockaddr)*)&sin;
1527 override @property socklen_t nameLen() const
1529 return cast(socklen_t) sin.sizeof;
1533 enum uint ADDR_ANY = INADDR_ANY; /// Any IPv4 host address.
1534 enum uint ADDR_NONE = INADDR_NONE; /// An invalid IPv4 host address.
1535 enum ushort PORT_ANY = 0; /// Any IPv4 port number.
1537 /// Returns the IPv4 _port number (in host byte order).
1538 @property ushort port() const pure nothrow @nogc
1540 return ntohs(sin.sin_port);
1543 /// Returns the IPv4 address number (in host byte order).
1544 @property uint addr() const pure nothrow @nogc
1546 return ntohl(sin.sin_addr.s_addr);
1550 * Construct a new $(D InternetAddress).
1551 * Params:
1552 * addr = an IPv4 address string in the dotted-decimal form a.b.c.d,
1553 * or a host name which will be resolved using an $(D InternetHost)
1554 * object.
1555 * port = port number, may be $(D PORT_ANY).
1557 this(in char[] addr, ushort port)
1559 uint uiaddr = parse(addr);
1560 if (ADDR_NONE == uiaddr)
1562 InternetHost ih = new InternetHost;
1563 if (!ih.getHostByName(addr))
1564 //throw new AddressException("Invalid internet address");
1565 throw new AddressException(
1566 text("Unable to resolve host '", addr, "'"));
1567 uiaddr = ih.addrList[0];
1569 sin.sin_family = AddressFamily.INET;
1570 sin.sin_addr.s_addr = htonl(uiaddr);
1571 sin.sin_port = htons(port);
1575 * Construct a new $(D InternetAddress).
1576 * Params:
1577 * addr = (optional) an IPv4 address in host byte order, may be $(D ADDR_ANY).
1578 * port = port number, may be $(D PORT_ANY).
1580 this(uint addr, ushort port) pure nothrow @nogc
1582 sin.sin_family = AddressFamily.INET;
1583 sin.sin_addr.s_addr = htonl(addr);
1584 sin.sin_port = htons(port);
1587 /// ditto
1588 this(ushort port) pure nothrow @nogc
1590 sin.sin_family = AddressFamily.INET;
1591 sin.sin_addr.s_addr = ADDR_ANY;
1592 sin.sin_port = htons(port);
1596 * Construct a new $(D InternetAddress).
1597 * Params:
1598 * addr = A sockaddr_in as obtained from lower-level API calls such as getifaddrs.
1600 this(sockaddr_in addr) pure nothrow @nogc
1602 assert(addr.sin_family == AddressFamily.INET);
1603 sin = addr;
1606 /// Human readable string representing the IPv4 address in dotted-decimal form.
1607 override string toAddrString() @trusted const
1609 return to!string(inet_ntoa(sin.sin_addr));
1612 /// Human readable string representing the IPv4 port.
1613 override string toPortString() const
1615 return std.conv.to!string(port);
1619 * Attempts to retrieve the host name as a fully qualified domain name.
1621 * Returns: The FQDN corresponding to this $(D InternetAddress), or
1622 * $(D null) if the host name did not resolve.
1624 * Throws: $(D AddressException) on error.
1626 override string toHostNameString() const
1628 // getnameinfo() is the recommended way to perform a reverse (name)
1629 // lookup on both Posix and Windows. However, it is only available
1630 // on Windows XP and above, and not included with the WinSock import
1631 // libraries shipped with DMD. Thus, we check for getnameinfo at
1632 // runtime in the shared module constructor, and fall back to the
1633 // deprecated getHostByAddr() if it could not be found. See also:
1634 // http://technet.microsoft.com/en-us/library/aa450403.aspx
1636 if (getnameinfoPointer)
1637 return super.toHostNameString();
1638 else
1640 auto host = new InternetHost();
1641 if (!host.getHostByAddr(ntohl(sin.sin_addr.s_addr)))
1642 return null;
1643 return host.name;
1648 * Compares with another InternetAddress of same type for equality
1649 * Returns: true if the InternetAddresses share the same address and
1650 * port number.
1652 override bool opEquals(Object o) const
1654 auto other = cast(InternetAddress) o;
1655 return other && this.sin.sin_addr.s_addr == other.sin.sin_addr.s_addr &&
1656 this.sin.sin_port == other.sin.sin_port;
1660 @system unittest
1662 auto addr1 = new InternetAddress("127.0.0.1", 80);
1663 auto addr2 = new InternetAddress("127.0.0.2", 80);
1665 assert(addr1 == addr1);
1666 assert(addr1 != addr2);
1670 * Parse an IPv4 address string in the dotted-decimal form $(I a.b.c.d)
1671 * and return the number.
1672 * Returns: If the string is not a legitimate IPv4 address,
1673 * $(D ADDR_NONE) is returned.
1675 static uint parse(in char[] addr) @trusted nothrow
1677 return ntohl(inet_addr(addr.tempCString()));
1681 * Convert an IPv4 address number in host byte order to a human readable
1682 * string representing the IPv4 address in dotted-decimal form.
1684 static string addrToString(uint addr) @trusted nothrow
1686 in_addr sin_addr;
1687 sin_addr.s_addr = htonl(addr);
1688 return to!string(inet_ntoa(sin_addr));
1693 @safe unittest
1695 softUnittest({
1696 const InternetAddress ia = new InternetAddress("63.105.9.61", 80);
1697 assert(ia.toString() == "63.105.9.61:80");
1700 softUnittest({
1701 // test construction from a sockaddr_in
1702 sockaddr_in sin;
1704 sin.sin_addr.s_addr = htonl(0x7F_00_00_01); // 127.0.0.1
1705 sin.sin_family = AddressFamily.INET;
1706 sin.sin_port = htons(80);
1708 const InternetAddress ia = new InternetAddress(sin);
1709 assert(ia.toString() == "127.0.0.1:80");
1712 softUnittest({
1713 // test reverse lookup
1714 auto ih = new InternetHost;
1715 if (ih.getHostByName("digitalmars.com"))
1717 const ia = new InternetAddress(ih.addrList[0], 80);
1718 assert(ia.toHostNameString() == "digitalmars.com");
1720 if (getnameinfoPointer)
1722 // test reverse lookup, via gethostbyaddr
1723 auto getnameinfoPointerBackup = getnameinfoPointer;
1724 cast() getnameinfoPointer = null;
1725 scope(exit) cast() getnameinfoPointer = getnameinfoPointerBackup;
1727 assert(ia.toHostNameString() == "digitalmars.com");
1732 version (SlowTests)
1733 softUnittest({
1734 // test failing reverse lookup
1735 const InternetAddress ia = new InternetAddress("127.114.111.120", 80);
1736 assert(ia.toHostNameString() is null);
1738 if (getnameinfoPointer)
1740 // test failing reverse lookup, via gethostbyaddr
1741 auto getnameinfoPointerBackup = getnameinfoPointer;
1742 getnameinfoPointer = null;
1743 scope(exit) getnameinfoPointer = getnameinfoPointerBackup;
1745 assert(ia.toHostNameString() is null);
1752 * $(D Internet6Address) encapsulates an IPv6 (Internet Protocol version 6)
1753 * socket address.
1755 * Consider using $(D getAddress), $(D parseAddress) and $(D Address) methods
1756 * instead of using this class directly.
1758 class Internet6Address: Address
1760 protected:
1761 sockaddr_in6 sin6;
1764 this() pure nothrow @nogc
1769 public:
1770 override @property sockaddr* name()
1772 return cast(sockaddr*)&sin6;
1775 override @property const(sockaddr)* name() const
1777 return cast(const(sockaddr)*)&sin6;
1781 override @property socklen_t nameLen() const
1783 return cast(socklen_t) sin6.sizeof;
1787 /// Any IPv6 host address.
1788 static @property ref const(ubyte)[16] ADDR_ANY() pure nothrow @nogc
1790 const(ubyte)[16]* addr;
1791 static if (is(typeof(IN6ADDR_ANY)))
1793 addr = &IN6ADDR_ANY.s6_addr;
1794 return *addr;
1796 else static if (is(typeof(in6addr_any)))
1798 addr = &in6addr_any.s6_addr;
1799 return *addr;
1801 else
1802 static assert(0);
1805 /// Any IPv6 port number.
1806 enum ushort PORT_ANY = 0;
1808 /// Returns the IPv6 port number.
1809 @property ushort port() const pure nothrow @nogc
1811 return ntohs(sin6.sin6_port);
1814 /// Returns the IPv6 address.
1815 @property ubyte[16] addr() const pure nothrow @nogc
1817 return sin6.sin6_addr.s6_addr;
1821 * Construct a new $(D Internet6Address).
1822 * Params:
1823 * addr = an IPv6 host address string in the form described in RFC 2373,
1824 * or a host name which will be resolved using $(D getAddressInfo).
1825 * service = (optional) service name.
1827 this(in char[] addr, in char[] service = null) @trusted
1829 auto results = getAddressInfo(addr, service, AddressFamily.INET6);
1830 assert(results.length && results[0].family == AddressFamily.INET6);
1831 sin6 = *cast(sockaddr_in6*) results[0].address.name;
1835 * Construct a new $(D Internet6Address).
1836 * Params:
1837 * addr = an IPv6 host address string in the form described in RFC 2373,
1838 * or a host name which will be resolved using $(D getAddressInfo).
1839 * port = port number, may be $(D PORT_ANY).
1841 this(in char[] addr, ushort port)
1843 if (port == PORT_ANY)
1844 this(addr);
1845 else
1846 this(addr, to!string(port));
1850 * Construct a new $(D Internet6Address).
1851 * Params:
1852 * addr = (optional) an IPv6 host address in host byte order, or
1853 * $(D ADDR_ANY).
1854 * port = port number, may be $(D PORT_ANY).
1856 this(ubyte[16] addr, ushort port) pure nothrow @nogc
1858 sin6.sin6_family = AddressFamily.INET6;
1859 sin6.sin6_addr.s6_addr = addr;
1860 sin6.sin6_port = htons(port);
1863 /// ditto
1864 this(ushort port) pure nothrow @nogc
1866 sin6.sin6_family = AddressFamily.INET6;
1867 sin6.sin6_addr.s6_addr = ADDR_ANY;
1868 sin6.sin6_port = htons(port);
1872 * Construct a new $(D Internet6Address).
1873 * Params:
1874 * addr = A sockaddr_in6 as obtained from lower-level API calls such as getifaddrs.
1876 this(sockaddr_in6 addr) pure nothrow @nogc
1878 assert(addr.sin6_family == AddressFamily.INET6);
1879 sin6 = addr;
1883 * Parse an IPv6 host address string as described in RFC 2373, and return the
1884 * address.
1885 * Throws: $(D SocketException) on error.
1887 static ubyte[16] parse(in char[] addr) @trusted
1889 // Although we could use inet_pton here, it's only available on Windows
1890 // versions starting with Vista, so use getAddressInfo with NUMERICHOST
1891 // instead.
1892 auto results = getAddressInfo(addr, AddressInfoFlags.NUMERICHOST);
1893 if (results.length && results[0].family == AddressFamily.INET6)
1894 return (cast(sockaddr_in6*) results[0].address.name).sin6_addr.s6_addr;
1895 throw new AddressException("Not an IPv6 address", 0);
1900 @safe unittest
1902 softUnittest({
1903 const Internet6Address ia = new Internet6Address("::1", 80);
1904 assert(ia.toString() == "[::1]:80");
1907 softUnittest({
1908 // test construction from a sockaddr_in6
1909 sockaddr_in6 sin;
1911 sin.sin6_addr.s6_addr = [ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1]; // [::1]
1912 sin.sin6_family = AddressFamily.INET6;
1913 sin.sin6_port = htons(80);
1915 const Internet6Address ia = new Internet6Address(sin);
1916 assert(ia.toString() == "[::1]:80");
1921 version (StdDdoc)
1923 static if (!is(sockaddr_un))
1925 // This exists only to allow the constructor taking
1926 // a sockaddr_un to be compilable for documentation
1927 // on platforms that don't supply a sockaddr_un.
1928 struct sockaddr_un
1934 * $(D UnixAddress) encapsulates an address for a Unix domain socket
1935 * ($(D AF_UNIX)), i.e. a socket bound to a path name in the file system.
1936 * Available only on supported systems.
1938 * Linux also supports an abstract address namespace, in which addresses
1939 * are independent of the file system. A socket address is abstract
1940 * iff `path` starts with a _null byte (`'\0'`). Null bytes in other
1941 * positions of an abstract address are allowed and have no special
1942 * meaning.
1944 * Example:
1945 * ---
1946 * auto addr = new UnixAddress("/var/run/dbus/system_bus_socket");
1947 * auto abstractAddr = new UnixAddress("\0/tmp/dbus-OtHLWmCLPR");
1948 * ---
1950 * See_Also: $(HTTP http://man7.org/linux/man-pages/man7/unix.7.html, UNIX(7))
1952 class UnixAddress: Address
1954 private this() pure nothrow @nogc {}
1956 /// Construct a new $(D UnixAddress) from the specified path.
1957 this(in char[] path) { }
1960 * Construct a new $(D UnixAddress).
1961 * Params:
1962 * addr = A sockaddr_un as obtained from lower-level API calls.
1964 this(sockaddr_un addr) pure nothrow @nogc { }
1966 /// Get the underlying _path.
1967 @property string path() const { return null; }
1969 /// ditto
1970 override string toString() const { return null; }
1972 override @property sockaddr* name() { return null; }
1973 override @property const(sockaddr)* name() const { return null; }
1974 override @property socklen_t nameLen() const { return 0; }
1977 else
1978 static if (is(sockaddr_un))
1980 class UnixAddress: Address
1982 protected:
1983 socklen_t _nameLen;
1985 struct
1987 align (1):
1988 sockaddr_un sun;
1989 char unused = '\0'; // placeholder for a terminating '\0'
1992 this() pure nothrow @nogc
1994 sun.sun_family = AddressFamily.UNIX;
1995 sun.sun_path = '?';
1996 _nameLen = sun.sizeof;
1999 override void setNameLen(socklen_t len) @trusted
2001 if (len > sun.sizeof)
2002 throw new SocketParameterException("Not enough socket address storage");
2003 _nameLen = len;
2006 public:
2007 override @property sockaddr* name()
2009 return cast(sockaddr*)&sun;
2012 override @property const(sockaddr)* name() const
2014 return cast(const(sockaddr)*)&sun;
2017 override @property socklen_t nameLen() @trusted const
2019 return _nameLen;
2022 this(in char[] path) @trusted pure
2024 enforce(path.length <= sun.sun_path.sizeof, new SocketParameterException("Path too long"));
2025 sun.sun_family = AddressFamily.UNIX;
2026 sun.sun_path.ptr[0 .. path.length] = (cast(byte[]) path)[];
2027 _nameLen = cast(socklen_t)
2029 auto len = sockaddr_un.init.sun_path.offsetof + path.length;
2030 // Pathname socket address must be terminated with '\0'
2031 // which must be included in the address length.
2032 if (sun.sun_path.ptr[0])
2034 sun.sun_path.ptr[path.length] = 0;
2035 ++len;
2037 return len;
2038 }();
2041 this(sockaddr_un addr) pure nothrow @nogc
2043 assert(addr.sun_family == AddressFamily.UNIX);
2044 sun = addr;
2047 @property string path() @trusted const pure
2049 auto len = _nameLen - sockaddr_un.init.sun_path.offsetof;
2050 // For pathname socket address we need to strip off the terminating '\0'
2051 if (sun.sun_path.ptr[0])
2052 --len;
2053 return (cast(const(char)*) sun.sun_path.ptr)[0 .. len].idup;
2056 override string toString() const pure
2058 return path;
2062 @safe unittest
2064 import core.stdc.stdio : remove;
2065 import std.file : deleteme;
2067 immutable ubyte[] data = [1, 2, 3, 4];
2068 Socket[2] pair;
2070 auto names = [ deleteme ~ "-unix-socket" ];
2071 version (linux)
2072 names ~= "\0" ~ deleteme ~ "-abstract\0unix\0socket";
2073 foreach (name; names)
2075 auto address = new UnixAddress(name);
2077 auto listener = new Socket(AddressFamily.UNIX, SocketType.STREAM);
2078 scope(exit) listener.close();
2079 listener.bind(address);
2080 scope(exit) () @trusted { if (name[0]) remove(name.tempCString()); } ();
2081 assert(listener.localAddress.toString == name);
2083 listener.listen(1);
2085 pair[0] = new Socket(AddressFamily.UNIX, SocketType.STREAM);
2086 scope(exit) listener.close();
2088 pair[0].connect(address);
2089 scope(exit) pair[0].close();
2091 pair[1] = listener.accept();
2092 scope(exit) pair[1].close();
2094 pair[0].send(data);
2096 auto buf = new ubyte[data.length];
2097 pair[1].receive(buf);
2098 assert(buf == data);
2105 * Class for exceptions thrown by $(D Socket.accept).
2107 class SocketAcceptException: SocketOSException
2109 mixin socketOSExceptionCtors;
2112 /// How a socket is shutdown:
2113 enum SocketShutdown: int
2115 RECEIVE = SD_RECEIVE, /// socket receives are disallowed
2116 SEND = SD_SEND, /// socket sends are disallowed
2117 BOTH = SD_BOTH, /// both RECEIVE and SEND
2121 /// Flags may be OR'ed together:
2122 enum SocketFlags: int
2124 NONE = 0, /// no flags specified
2126 OOB = MSG_OOB, /// out-of-band stream data
2127 PEEK = MSG_PEEK, /// peek at incoming data without removing it from the queue, only for receiving
2128 DONTROUTE = MSG_DONTROUTE, /// data should not be subject to routing; this flag may be ignored. Only for sending
2132 private mixin template FieldProxy(string target, string field)
2134 mixin(`
2135 @property typeof(`~target~`) `~field~`() const pure nothrow @nogc
2137 return `~target~`;
2140 /// ditto
2141 @property typeof(`~target~`) `~field~`(typeof(`~target~`) value) pure nothrow @nogc
2143 return `~target~` = value;
2149 /// Duration timeout value.
2150 struct TimeVal
2152 _ctimeval ctimeval;
2153 alias tv_sec_t = typeof(ctimeval.tv_sec);
2154 alias tv_usec_t = typeof(ctimeval.tv_usec);
2156 version (StdDdoc) // no DDoc for string mixins, can't forward individual fields
2158 tv_sec_t seconds; /// Number of _seconds.
2159 tv_usec_t microseconds; /// Number of additional _microseconds.
2161 else
2163 // D interface
2164 mixin FieldProxy!(`ctimeval.tv_sec`, `seconds`);
2165 mixin FieldProxy!(`ctimeval.tv_usec`, `microseconds`);
2171 * A collection of sockets for use with $(D Socket.select).
2173 * $(D SocketSet) wraps the platform $(D fd_set) type. However, unlike
2174 * $(D fd_set), $(D SocketSet) is not statically limited to $(D FD_SETSIZE)
2175 * or any other limit, and grows as needed.
2177 class SocketSet
2179 private:
2180 version (Windows)
2182 // On Windows, fd_set is an array of socket handles,
2183 // following a word containing the fd_set instance size.
2184 // We use one dynamic array for everything, and use its first
2185 // element(s) for the count.
2187 alias fd_set_count_type = typeof(fd_set.init.fd_count);
2188 alias fd_set_type = typeof(fd_set.init.fd_array[0]);
2189 static assert(fd_set_type.sizeof == socket_t.sizeof);
2191 // Number of fd_set_type elements at the start of our array that are
2192 // used for the socket count and alignment
2194 enum FD_SET_OFFSET = fd_set.fd_array.offsetof / fd_set_type.sizeof;
2195 static assert(FD_SET_OFFSET);
2196 static assert(fd_set.fd_count.offsetof % fd_set_type.sizeof == 0);
2198 fd_set_type[] set;
2200 void resize(size_t size) pure nothrow
2202 set.length = FD_SET_OFFSET + size;
2205 ref inout(fd_set_count_type) count() @trusted @property inout pure nothrow @nogc
2207 assert(set.length);
2208 return *cast(inout(fd_set_count_type)*)set.ptr;
2211 size_t capacity() @property const pure nothrow @nogc
2213 return set.length - FD_SET_OFFSET;
2216 inout(socket_t)[] fds() @trusted inout @property pure nothrow @nogc
2218 return cast(inout(socket_t)[])set[FD_SET_OFFSET .. FD_SET_OFFSET+count];
2221 else
2222 version (Posix)
2224 // On Posix, fd_set is a bit array. We assume that the fd_set
2225 // type (declared in core.sys.posix.sys.select) is a structure
2226 // containing a single field, a static array.
2228 static assert(fd_set.tupleof.length == 1);
2230 // This is the type used in the fd_set array.
2231 // Using the type of the correct size is important for big-endian
2232 // architectures.
2234 alias fd_set_type = typeof(fd_set.init.tupleof[0][0]);
2236 // Number of file descriptors represented by one fd_set_type
2238 enum FD_NFDBITS = 8 * fd_set_type.sizeof;
2240 static fd_set_type mask(uint n) pure nothrow @nogc
2242 return (cast(fd_set_type) 1) << (n % FD_NFDBITS);
2245 // Array size to fit that many sockets
2247 static size_t lengthFor(size_t size) pure nothrow @nogc
2249 return (size + (FD_NFDBITS-1)) / FD_NFDBITS;
2252 fd_set_type[] set;
2254 void resize(size_t size) pure nothrow
2256 set.length = lengthFor(size);
2259 // Make sure we can fit that many sockets
2261 void setMinCapacity(size_t size) pure nothrow
2263 auto length = lengthFor(size);
2264 if (set.length < length)
2265 set.length = length;
2268 size_t capacity() @property const pure nothrow @nogc
2270 return set.length * FD_NFDBITS;
2273 int maxfd;
2275 else
2276 static assert(false, "Unknown platform");
2278 public:
2281 * Create a SocketSet with a specific initial capacity (defaults to
2282 * $(D FD_SETSIZE), the system's default capacity).
2284 this(size_t size = FD_SETSIZE) pure nothrow
2286 resize(size);
2287 reset();
2290 /// Reset the $(D SocketSet) so that there are 0 $(D Socket)s in the collection.
2291 void reset() pure nothrow @nogc
2293 version (Windows)
2294 count = 0;
2295 else
2297 set[] = 0;
2298 maxfd = -1;
2303 void add(socket_t s) @trusted pure nothrow
2305 version (Windows)
2307 if (count == capacity)
2309 set.length *= 2;
2310 set.length = set.capacity;
2312 ++count;
2313 fds[$-1] = s;
2315 else
2317 auto index = s / FD_NFDBITS;
2318 auto length = set.length;
2319 if (index >= length)
2321 while (index >= length)
2322 length *= 2;
2323 set.length = length;
2324 set.length = set.capacity;
2326 set[index] |= mask(s);
2327 if (maxfd < s)
2328 maxfd = s;
2333 * Add a $(D Socket) to the collection.
2334 * The socket must not already be in the collection.
2336 void add(Socket s) pure nothrow
2338 add(s.sock);
2341 void remove(socket_t s) pure nothrow
2343 version (Windows)
2345 import std.algorithm.searching : countUntil;
2346 auto fds = fds;
2347 auto p = fds.countUntil(s);
2348 if (p >= 0)
2349 fds[p] = fds[--count];
2351 else
2353 auto index = s / FD_NFDBITS;
2354 if (index >= set.length)
2355 return;
2356 set[index] &= ~mask(s);
2357 // note: adjusting maxfd would require scanning the set, not worth it
2363 * Remove this $(D Socket) from the collection.
2364 * Does nothing if the socket is not in the collection already.
2366 void remove(Socket s) pure nothrow
2368 remove(s.sock);
2371 int isSet(socket_t s) const pure nothrow @nogc
2373 version (Windows)
2375 import std.algorithm.searching : canFind;
2376 return fds.canFind(s) ? 1 : 0;
2378 else
2380 if (s > maxfd)
2381 return 0;
2382 auto index = s / FD_NFDBITS;
2383 return (set[index] & mask(s)) ? 1 : 0;
2388 /// Return nonzero if this $(D Socket) is in the collection.
2389 int isSet(Socket s) const pure nothrow @nogc
2391 return isSet(s.sock);
2396 * Returns:
2397 * The current capacity of this $(D SocketSet). The exact
2398 * meaning of the return value varies from platform to platform.
2400 * Note:
2401 * Since D 2.065, this value does not indicate a
2402 * restriction, and $(D SocketSet) will grow its capacity as
2403 * needed automatically.
2405 @property uint max() const pure nothrow @nogc
2407 return cast(uint) capacity;
2411 fd_set* toFd_set() @trusted pure nothrow @nogc
2413 return cast(fd_set*) set.ptr;
2417 int selectn() const pure nothrow @nogc
2419 version (Windows)
2421 return count;
2423 else version (Posix)
2425 return maxfd + 1;
2430 @safe unittest
2432 auto fds = cast(socket_t[])
2433 [cast(socket_t) 1, 2, 0, 1024, 17, 42, 1234, 77, 77+32, 77+64];
2434 auto set = new SocketSet();
2435 foreach (fd; fds) assert(!set.isSet(fd));
2436 foreach (fd; fds) set.add(fd);
2437 foreach (fd; fds) assert(set.isSet(fd));
2439 // Make sure SocketSet reimplements fd_set correctly
2440 auto fdset = set.toFd_set();
2441 foreach (fd; fds[0]..cast(socket_t)(fds[$-1]+1))
2442 assert(cast(bool) set.isSet(fd) == cast(bool)(() @trusted => FD_ISSET(fd, fdset))());
2444 foreach (fd; fds)
2446 assert(set.isSet(fd));
2447 set.remove(fd);
2448 assert(!set.isSet(fd));
2452 @safe unittest
2454 softUnittest({
2455 enum PAIRS = 768;
2456 version (Posix)
2457 () @trusted
2459 enum LIMIT = 2048;
2460 static assert(LIMIT > PAIRS*2);
2461 import core.sys.posix.sys.resource;
2462 rlimit fileLimit;
2463 getrlimit(RLIMIT_NOFILE, &fileLimit);
2464 assert(fileLimit.rlim_max > LIMIT, "Open file hard limit too low");
2465 fileLimit.rlim_cur = LIMIT;
2466 setrlimit(RLIMIT_NOFILE, &fileLimit);
2467 } ();
2469 Socket[2][PAIRS] pairs;
2470 foreach (ref pair; pairs)
2471 pair = socketPair();
2472 scope(exit)
2474 foreach (pair; pairs)
2476 pair[0].close();
2477 pair[1].close();
2481 import std.random;
2482 auto rng = Xorshift(42);
2483 pairs[].randomShuffle(rng);
2485 auto readSet = new SocketSet();
2486 auto writeSet = new SocketSet();
2487 auto errorSet = new SocketSet();
2489 foreach (testPair; pairs)
2491 void fillSets()
2493 readSet.reset();
2494 writeSet.reset();
2495 errorSet.reset();
2496 foreach (ref pair; pairs)
2497 foreach (s; pair[])
2499 readSet.add(s);
2500 writeSet.add(s);
2501 errorSet.add(s);
2505 fillSets();
2506 auto n = Socket.select(readSet, writeSet, errorSet);
2507 assert(n == PAIRS*2); // All in writeSet
2508 assert(writeSet.isSet(testPair[0]));
2509 assert(writeSet.isSet(testPair[1]));
2510 assert(!readSet.isSet(testPair[0]));
2511 assert(!readSet.isSet(testPair[1]));
2512 assert(!errorSet.isSet(testPair[0]));
2513 assert(!errorSet.isSet(testPair[1]));
2515 ubyte[1] b;
2516 testPair[0].send(b[]);
2517 fillSets();
2518 n = Socket.select(readSet, null, null);
2519 assert(n == 1); // testPair[1]
2520 assert(readSet.isSet(testPair[1]));
2521 assert(!readSet.isSet(testPair[0]));
2522 testPair[1].receive(b[]);
2527 @safe unittest // Issue 14012, 14013
2529 auto set = new SocketSet(1);
2530 assert(set.max >= 0);
2532 enum LIMIT = 4096;
2533 foreach (n; 0 .. LIMIT)
2534 set.add(cast(socket_t) n);
2535 assert(set.max >= LIMIT);
2538 /// The level at which a socket option is defined:
2539 enum SocketOptionLevel: int
2541 SOCKET = SOL_SOCKET, /// Socket level
2542 IP = ProtocolType.IP, /// Internet Protocol version 4 level
2543 ICMP = ProtocolType.ICMP, /// Internet Control Message Protocol level
2544 IGMP = ProtocolType.IGMP, /// Internet Group Management Protocol level
2545 GGP = ProtocolType.GGP, /// Gateway to Gateway Protocol level
2546 TCP = ProtocolType.TCP, /// Transmission Control Protocol level
2547 PUP = ProtocolType.PUP, /// PARC Universal Packet Protocol level
2548 UDP = ProtocolType.UDP, /// User Datagram Protocol level
2549 IDP = ProtocolType.IDP, /// Xerox NS protocol level
2550 RAW = ProtocolType.RAW, /// Raw IP packet level
2551 IPV6 = ProtocolType.IPV6, /// Internet Protocol version 6 level
2554 /// _Linger information for use with SocketOption.LINGER.
2555 struct Linger
2557 _clinger clinger;
2559 version (StdDdoc) // no DDoc for string mixins, can't forward individual fields
2561 private alias l_onoff_t = typeof(_clinger.init.l_onoff );
2562 private alias l_linger_t = typeof(_clinger.init.l_linger);
2563 l_onoff_t on; /// Nonzero for _on.
2564 l_linger_t time; /// Linger _time.
2566 else
2568 // D interface
2569 mixin FieldProxy!(`clinger.l_onoff`, `on`);
2570 mixin FieldProxy!(`clinger.l_linger`, `time`);
2574 /// Specifies a socket option:
2575 enum SocketOption: int
2577 DEBUG = SO_DEBUG, /// Record debugging information
2578 BROADCAST = SO_BROADCAST, /// Allow transmission of broadcast messages
2579 REUSEADDR = SO_REUSEADDR, /// Allow local reuse of address
2580 LINGER = SO_LINGER, /// Linger on close if unsent data is present
2581 OOBINLINE = SO_OOBINLINE, /// Receive out-of-band data in band
2582 SNDBUF = SO_SNDBUF, /// Send buffer size
2583 RCVBUF = SO_RCVBUF, /// Receive buffer size
2584 DONTROUTE = SO_DONTROUTE, /// Do not route
2585 SNDTIMEO = SO_SNDTIMEO, /// Send timeout
2586 RCVTIMEO = SO_RCVTIMEO, /// Receive timeout
2587 ERROR = SO_ERROR, /// Retrieve and clear error status
2588 KEEPALIVE = SO_KEEPALIVE, /// Enable keep-alive packets
2589 ACCEPTCONN = SO_ACCEPTCONN, /// Listen
2590 RCVLOWAT = SO_RCVLOWAT, /// Minimum number of input bytes to process
2591 SNDLOWAT = SO_SNDLOWAT, /// Minimum number of output bytes to process
2592 TYPE = SO_TYPE, /// Socket type
2594 // SocketOptionLevel.TCP:
2595 TCP_NODELAY = .TCP_NODELAY, /// Disable the Nagle algorithm for send coalescing
2597 // SocketOptionLevel.IPV6:
2598 IPV6_UNICAST_HOPS = .IPV6_UNICAST_HOPS, /// IP unicast hop limit
2599 IPV6_MULTICAST_IF = .IPV6_MULTICAST_IF, /// IP multicast interface
2600 IPV6_MULTICAST_LOOP = .IPV6_MULTICAST_LOOP, /// IP multicast loopback
2601 IPV6_MULTICAST_HOPS = .IPV6_MULTICAST_HOPS, /// IP multicast hops
2602 IPV6_JOIN_GROUP = .IPV6_JOIN_GROUP, /// Add an IP group membership
2603 IPV6_LEAVE_GROUP = .IPV6_LEAVE_GROUP, /// Drop an IP group membership
2604 IPV6_V6ONLY = .IPV6_V6ONLY, /// Treat wildcard bind as AF_INET6-only
2609 * $(D Socket) is a class that creates a network communication endpoint using
2610 * the Berkeley sockets interface.
2612 class Socket
2614 private:
2615 socket_t sock;
2616 AddressFamily _family;
2618 version (Windows)
2619 bool _blocking = false; /// Property to get or set whether the socket is blocking or nonblocking.
2621 // The WinSock timeouts seem to be effectively skewed by a constant
2622 // offset of about half a second (value in milliseconds). This has
2623 // been confirmed on updated (as of Jun 2011) Windows XP, Windows 7
2624 // and Windows Server 2008 R2 boxes. The unittest below tests this
2625 // behavior.
2626 enum WINSOCK_TIMEOUT_SKEW = 500;
2628 @safe unittest
2630 version (SlowTests)
2631 softUnittest({
2632 import std.datetime;
2633 import std.typecons;
2635 enum msecs = 1000;
2636 auto pair = socketPair();
2637 auto sock = pair[0];
2638 sock.setOption(SocketOptionLevel.SOCKET,
2639 SocketOption.RCVTIMEO, dur!"msecs"(msecs));
2641 auto sw = StopWatch(Yes.autoStart);
2642 ubyte[1] buf;
2643 sock.receive(buf);
2644 sw.stop();
2646 Duration readBack = void;
2647 sock.getOption(SocketOptionLevel.SOCKET, SocketOption.RCVTIMEO, readBack);
2649 assert(readBack.total!"msecs" == msecs);
2650 assert(sw.peek().msecs > msecs-100 && sw.peek().msecs < msecs+100);
2654 void setSock(socket_t handle)
2656 assert(handle != socket_t.init);
2657 sock = handle;
2659 // Set the option to disable SIGPIPE on send() if the platform
2660 // has it (e.g. on OS X).
2661 static if (is(typeof(SO_NOSIGPIPE)))
2663 setOption(SocketOptionLevel.SOCKET, cast(SocketOption) SO_NOSIGPIPE, true);
2668 // For use with accepting().
2669 protected this() pure nothrow @nogc
2674 public:
2677 * Create a blocking socket. If a single protocol type exists to support
2678 * this socket type within the address family, the $(D ProtocolType) may be
2679 * omitted.
2681 this(AddressFamily af, SocketType type, ProtocolType protocol) @trusted
2683 _family = af;
2684 auto handle = cast(socket_t) socket(af, type, protocol);
2685 if (handle == socket_t.init)
2686 throw new SocketOSException("Unable to create socket");
2687 setSock(handle);
2690 /// ditto
2691 this(AddressFamily af, SocketType type)
2693 /* A single protocol exists to support this socket type within the
2694 * protocol family, so the ProtocolType is assumed.
2696 this(af, type, cast(ProtocolType) 0); // Pseudo protocol number.
2700 /// ditto
2701 this(AddressFamily af, SocketType type, in char[] protocolName) @trusted
2703 protoent* proto;
2704 proto = getprotobyname(protocolName.tempCString());
2705 if (!proto)
2706 throw new SocketOSException("Unable to find the protocol");
2707 this(af, type, cast(ProtocolType) proto.p_proto);
2712 * Create a blocking socket using the parameters from the specified
2713 * $(D AddressInfo) structure.
2715 this(in AddressInfo info)
2717 this(info.family, info.type, info.protocol);
2720 /// Use an existing socket handle.
2721 this(socket_t sock, AddressFamily af) pure nothrow @nogc
2723 assert(sock != socket_t.init);
2724 this.sock = sock;
2725 this._family = af;
2729 ~this() nothrow @nogc
2731 close();
2735 /// Get underlying socket handle.
2736 @property socket_t handle() const pure nothrow @nogc
2738 return sock;
2742 * Get/set socket's blocking flag.
2744 * When a socket is blocking, calls to receive(), accept(), and send()
2745 * will block and wait for data/action.
2746 * A non-blocking socket will immediately return instead of blocking.
2748 @property bool blocking() @trusted const nothrow @nogc
2750 version (Windows)
2752 return _blocking;
2754 else version (Posix)
2756 return !(fcntl(handle, F_GETFL, 0) & O_NONBLOCK);
2760 /// ditto
2761 @property void blocking(bool byes) @trusted
2763 version (Windows)
2765 uint num = !byes;
2766 if (_SOCKET_ERROR == ioctlsocket(sock, FIONBIO, &num))
2767 goto err;
2768 _blocking = byes;
2770 else version (Posix)
2772 int x = fcntl(sock, F_GETFL, 0);
2773 if (-1 == x)
2774 goto err;
2775 if (byes)
2776 x &= ~O_NONBLOCK;
2777 else
2778 x |= O_NONBLOCK;
2779 if (-1 == fcntl(sock, F_SETFL, x))
2780 goto err;
2782 return; // Success.
2784 err:
2785 throw new SocketOSException("Unable to set socket blocking");
2789 /// Get the socket's address family.
2790 @property AddressFamily addressFamily()
2792 return _family;
2795 /// Property that indicates if this is a valid, alive socket.
2796 @property bool isAlive() @trusted const
2798 int type;
2799 socklen_t typesize = cast(socklen_t) type.sizeof;
2800 return !getsockopt(sock, SOL_SOCKET, SO_TYPE, cast(char*)&type, &typesize);
2803 /// Associate a local address with this socket.
2804 void bind(Address addr) @trusted
2806 if (_SOCKET_ERROR == .bind(sock, addr.name, addr.nameLen))
2807 throw new SocketOSException("Unable to bind socket");
2811 * Establish a connection. If the socket is blocking, connect waits for
2812 * the connection to be made. If the socket is nonblocking, connect
2813 * returns immediately and the connection attempt is still in progress.
2815 void connect(Address to) @trusted
2817 if (_SOCKET_ERROR == .connect(sock, to.name, to.nameLen))
2819 int err;
2820 err = _lasterr();
2822 if (!blocking)
2824 version (Windows)
2826 if (WSAEWOULDBLOCK == err)
2827 return;
2829 else version (Posix)
2831 if (EINPROGRESS == err)
2832 return;
2834 else
2836 static assert(0);
2839 throw new SocketOSException("Unable to connect socket", err);
2844 * Listen for an incoming connection. $(D bind) must be called before you
2845 * can $(D listen). The $(D backlog) is a request of how many pending
2846 * incoming connections are queued until $(D accept)ed.
2848 void listen(int backlog) @trusted
2850 if (_SOCKET_ERROR == .listen(sock, backlog))
2851 throw new SocketOSException("Unable to listen on socket");
2855 * Called by $(D accept) when a new $(D Socket) must be created for a new
2856 * connection. To use a derived class, override this method and return an
2857 * instance of your class. The returned $(D Socket)'s handle must not be
2858 * set; $(D Socket) has a protected constructor $(D this()) to use in this
2859 * situation.
2861 * Override to use a derived class.
2862 * The returned socket's handle must not be set.
2864 protected Socket accepting() pure nothrow
2866 return new Socket;
2870 * Accept an incoming connection. If the socket is blocking, $(D accept)
2871 * waits for a connection request. Throws $(D SocketAcceptException) if
2872 * unable to _accept. See $(D accepting) for use with derived classes.
2874 Socket accept() @trusted
2876 auto newsock = cast(socket_t).accept(sock, null, null);
2877 if (socket_t.init == newsock)
2878 throw new SocketAcceptException("Unable to accept socket connection");
2880 Socket newSocket;
2883 newSocket = accepting();
2884 assert(newSocket.sock == socket_t.init);
2886 newSocket.setSock(newsock);
2887 version (Windows)
2888 newSocket._blocking = _blocking; //inherits blocking mode
2889 newSocket._family = _family; //same family
2891 catch (Throwable o)
2893 _close(newsock);
2894 throw o;
2897 return newSocket;
2900 /// Disables sends and/or receives.
2901 void shutdown(SocketShutdown how) @trusted nothrow @nogc
2903 .shutdown(sock, cast(int) how);
2907 private static void _close(socket_t sock) @system nothrow @nogc
2909 version (Windows)
2911 .closesocket(sock);
2913 else version (Posix)
2915 .close(sock);
2921 * Immediately drop any connections and release socket resources.
2922 * Calling $(D shutdown) before $(D close) is recommended for
2923 * connection-oriented sockets. The $(D Socket) object is no longer
2924 * usable after $(D close).
2925 * Calling shutdown() before this is recommended
2926 * for connection-oriented sockets.
2928 void close() @trusted nothrow @nogc
2930 _close(sock);
2931 sock = socket_t.init;
2936 * Returns: the local machine's host name
2938 static @property string hostName() @trusted // getter
2940 char[256] result; // Host names are limited to 255 chars.
2941 if (_SOCKET_ERROR == .gethostname(result.ptr, result.length))
2942 throw new SocketOSException("Unable to obtain host name");
2943 return to!string(result.ptr);
2946 /// Remote endpoint $(D Address).
2947 @property Address remoteAddress() @trusted
2949 Address addr = createAddress();
2950 socklen_t nameLen = addr.nameLen;
2951 if (_SOCKET_ERROR == .getpeername(sock, addr.name, &nameLen))
2952 throw new SocketOSException("Unable to obtain remote socket address");
2953 addr.setNameLen(nameLen);
2954 assert(addr.addressFamily == _family);
2955 return addr;
2958 /// Local endpoint $(D Address).
2959 @property Address localAddress() @trusted
2961 Address addr = createAddress();
2962 socklen_t nameLen = addr.nameLen;
2963 if (_SOCKET_ERROR == .getsockname(sock, addr.name, &nameLen))
2964 throw new SocketOSException("Unable to obtain local socket address");
2965 addr.setNameLen(nameLen);
2966 assert(addr.addressFamily == _family);
2967 return addr;
2971 * Send or receive error code. See $(D wouldHaveBlocked),
2972 * $(D lastSocketError) and $(D Socket.getErrorText) for obtaining more
2973 * information about the error.
2975 enum int ERROR = _SOCKET_ERROR;
2977 private static int capToInt(size_t size) nothrow @nogc
2979 // Windows uses int instead of size_t for length arguments.
2980 // Luckily, the send/recv functions make no guarantee that
2981 // all the data is sent, so we use that to send at most
2982 // int.max bytes.
2983 return size > size_t(int.max) ? int.max : cast(int) size;
2987 * Send data on the connection. If the socket is blocking and there is no
2988 * buffer space left, $(D send) waits.
2989 * Returns: The number of bytes actually sent, or $(D Socket.ERROR) on
2990 * failure.
2992 ptrdiff_t send(const(void)[] buf, SocketFlags flags) @trusted
2994 static if (is(typeof(MSG_NOSIGNAL)))
2996 flags = cast(SocketFlags)(flags | MSG_NOSIGNAL);
2998 version (Windows)
2999 auto sent = .send(sock, buf.ptr, capToInt(buf.length), cast(int) flags);
3000 else
3001 auto sent = .send(sock, buf.ptr, buf.length, cast(int) flags);
3002 return sent;
3005 /// ditto
3006 ptrdiff_t send(const(void)[] buf)
3008 return send(buf, SocketFlags.NONE);
3012 * Send data to a specific destination Address. If the destination address is
3013 * not specified, a connection must have been made and that address is used.
3014 * If the socket is blocking and there is no buffer space left, $(D sendTo) waits.
3015 * Returns: The number of bytes actually sent, or $(D Socket.ERROR) on
3016 * failure.
3018 ptrdiff_t sendTo(const(void)[] buf, SocketFlags flags, Address to) @trusted
3020 static if (is(typeof(MSG_NOSIGNAL)))
3022 flags = cast(SocketFlags)(flags | MSG_NOSIGNAL);
3024 version (Windows)
3025 return .sendto(
3026 sock, buf.ptr, capToInt(buf.length),
3027 cast(int) flags, to.name, to.nameLen
3029 else
3030 return .sendto(sock, buf.ptr, buf.length, cast(int) flags, to.name, to.nameLen);
3033 /// ditto
3034 ptrdiff_t sendTo(const(void)[] buf, Address to)
3036 return sendTo(buf, SocketFlags.NONE, to);
3040 //assumes you connect()ed
3041 /// ditto
3042 ptrdiff_t sendTo(const(void)[] buf, SocketFlags flags) @trusted
3044 static if (is(typeof(MSG_NOSIGNAL)))
3046 flags = cast(SocketFlags)(flags | MSG_NOSIGNAL);
3048 version (Windows)
3049 return .sendto(sock, buf.ptr, capToInt(buf.length), cast(int) flags, null, 0);
3050 else
3051 return .sendto(sock, buf.ptr, buf.length, cast(int) flags, null, 0);
3055 //assumes you connect()ed
3056 /// ditto
3057 ptrdiff_t sendTo(const(void)[] buf)
3059 return sendTo(buf, SocketFlags.NONE);
3064 * Receive data on the connection. If the socket is blocking, $(D receive)
3065 * waits until there is data to be received.
3066 * Returns: The number of bytes actually received, $(D 0) if the remote side
3067 * has closed the connection, or $(D Socket.ERROR) on failure.
3069 ptrdiff_t receive(void[] buf, SocketFlags flags) @trusted
3071 version (Windows) // Does not use size_t
3073 return buf.length
3074 ? .recv(sock, buf.ptr, capToInt(buf.length), cast(int) flags)
3075 : 0;
3077 else
3079 return buf.length
3080 ? .recv(sock, buf.ptr, buf.length, cast(int) flags)
3081 : 0;
3085 /// ditto
3086 ptrdiff_t receive(void[] buf)
3088 return receive(buf, SocketFlags.NONE);
3092 * Receive data and get the remote endpoint $(D Address).
3093 * If the socket is blocking, $(D receiveFrom) waits until there is data to
3094 * be received.
3095 * Returns: The number of bytes actually received, $(D 0) if the remote side
3096 * has closed the connection, or $(D Socket.ERROR) on failure.
3098 ptrdiff_t receiveFrom(void[] buf, SocketFlags flags, ref Address from) @trusted
3100 if (!buf.length) //return 0 and don't think the connection closed
3101 return 0;
3102 if (from is null || from.addressFamily != _family)
3103 from = createAddress();
3104 socklen_t nameLen = from.nameLen;
3105 version (Windows)
3107 auto read = .recvfrom(sock, buf.ptr, capToInt(buf.length), cast(int) flags, from.name, &nameLen);
3108 from.setNameLen(nameLen);
3109 assert(from.addressFamily == _family);
3110 // if (!read) //connection closed
3111 return read;
3113 else
3115 auto read = .recvfrom(sock, buf.ptr, buf.length, cast(int) flags, from.name, &nameLen);
3116 from.setNameLen(nameLen);
3117 assert(from.addressFamily == _family);
3118 // if (!read) //connection closed
3119 return read;
3124 /// ditto
3125 ptrdiff_t receiveFrom(void[] buf, ref Address from)
3127 return receiveFrom(buf, SocketFlags.NONE, from);
3131 //assumes you connect()ed
3132 /// ditto
3133 ptrdiff_t receiveFrom(void[] buf, SocketFlags flags) @trusted
3135 if (!buf.length) //return 0 and don't think the connection closed
3136 return 0;
3137 version (Windows)
3139 auto read = .recvfrom(sock, buf.ptr, capToInt(buf.length), cast(int) flags, null, null);
3140 // if (!read) //connection closed
3141 return read;
3143 else
3145 auto read = .recvfrom(sock, buf.ptr, buf.length, cast(int) flags, null, null);
3146 // if (!read) //connection closed
3147 return read;
3152 //assumes you connect()ed
3153 /// ditto
3154 ptrdiff_t receiveFrom(void[] buf)
3156 return receiveFrom(buf, SocketFlags.NONE);
3161 * Get a socket option.
3162 * Returns: The number of bytes written to $(D result).
3163 * The length, in bytes, of the actual result - very different from getsockopt()
3165 int getOption(SocketOptionLevel level, SocketOption option, void[] result) @trusted
3167 socklen_t len = cast(socklen_t) result.length;
3168 if (_SOCKET_ERROR == .getsockopt(sock, cast(int) level, cast(int) option, result.ptr, &len))
3169 throw new SocketOSException("Unable to get socket option");
3170 return len;
3174 /// Common case of getting integer and boolean options.
3175 int getOption(SocketOptionLevel level, SocketOption option, out int32_t result) @trusted
3177 return getOption(level, option, (&result)[0 .. 1]);
3181 /// Get the linger option.
3182 int getOption(SocketOptionLevel level, SocketOption option, out Linger result) @trusted
3184 //return getOption(cast(SocketOptionLevel) SocketOptionLevel.SOCKET, SocketOption.LINGER, (&result)[0 .. 1]);
3185 return getOption(level, option, (&result.clinger)[0 .. 1]);
3188 /// Get a timeout (duration) option.
3189 void getOption(SocketOptionLevel level, SocketOption option, out Duration result) @trusted
3191 enforce(option == SocketOption.SNDTIMEO || option == SocketOption.RCVTIMEO,
3192 new SocketParameterException("Not a valid timeout option: " ~ to!string(option)));
3193 // WinSock returns the timeout values as a milliseconds DWORD,
3194 // while Linux and BSD return a timeval struct.
3195 version (Windows)
3197 int msecs;
3198 getOption(level, option, (&msecs)[0 .. 1]);
3199 if (option == SocketOption.RCVTIMEO)
3200 msecs += WINSOCK_TIMEOUT_SKEW;
3201 result = dur!"msecs"(msecs);
3203 else version (Posix)
3205 TimeVal tv;
3206 getOption(level, option, (&tv.ctimeval)[0 .. 1]);
3207 result = dur!"seconds"(tv.seconds) + dur!"usecs"(tv.microseconds);
3209 else static assert(false);
3212 /// Set a socket option.
3213 void setOption(SocketOptionLevel level, SocketOption option, void[] value) @trusted
3215 if (_SOCKET_ERROR == .setsockopt(sock, cast(int) level,
3216 cast(int) option, value.ptr, cast(uint) value.length))
3217 throw new SocketOSException("Unable to set socket option");
3221 /// Common case for setting integer and boolean options.
3222 void setOption(SocketOptionLevel level, SocketOption option, int32_t value) @trusted
3224 setOption(level, option, (&value)[0 .. 1]);
3228 /// Set the linger option.
3229 void setOption(SocketOptionLevel level, SocketOption option, Linger value) @trusted
3231 //setOption(cast(SocketOptionLevel) SocketOptionLevel.SOCKET, SocketOption.LINGER, (&value)[0 .. 1]);
3232 setOption(level, option, (&value.clinger)[0 .. 1]);
3236 * Sets a timeout (duration) option, i.e. $(D SocketOption.SNDTIMEO) or
3237 * $(D RCVTIMEO). Zero indicates no timeout.
3239 * In a typical application, you might also want to consider using
3240 * a non-blocking socket instead of setting a timeout on a blocking one.
3242 * Note: While the receive timeout setting is generally quite accurate
3243 * on *nix systems even for smaller durations, there are two issues to
3244 * be aware of on Windows: First, although undocumented, the effective
3245 * timeout duration seems to be the one set on the socket plus half
3246 * a second. $(D setOption()) tries to compensate for that, but still,
3247 * timeouts under 500ms are not possible on Windows. Second, be aware
3248 * that the actual amount of time spent until a blocking call returns
3249 * randomly varies on the order of 10ms.
3251 * Params:
3252 * level = The level at which a socket option is defined.
3253 * option = Either $(D SocketOption.SNDTIMEO) or $(D SocketOption.RCVTIMEO).
3254 * value = The timeout duration to set. Must not be negative.
3256 * Throws: $(D SocketException) if setting the options fails.
3258 * Example:
3259 * ---
3260 * import std.datetime;
3261 * import std.typecons;
3262 * auto pair = socketPair();
3263 * scope(exit) foreach (s; pair) s.close();
3265 * // Set a receive timeout, and then wait at one end of
3266 * // the socket pair, knowing that no data will arrive.
3267 * pair[0].setOption(SocketOptionLevel.SOCKET,
3268 * SocketOption.RCVTIMEO, dur!"seconds"(1));
3270 * auto sw = StopWatch(Yes.autoStart);
3271 * ubyte[1] buffer;
3272 * pair[0].receive(buffer);
3273 * writefln("Waited %s ms until the socket timed out.",
3274 * sw.peek.msecs);
3275 * ---
3277 void setOption(SocketOptionLevel level, SocketOption option, Duration value) @trusted
3279 enforce(option == SocketOption.SNDTIMEO || option == SocketOption.RCVTIMEO,
3280 new SocketParameterException("Not a valid timeout option: " ~ to!string(option)));
3282 enforce(value >= dur!"hnsecs"(0), new SocketParameterException(
3283 "Timeout duration must not be negative."));
3285 version (Windows)
3287 import std.algorithm.comparison : max;
3289 auto msecs = to!int(value.total!"msecs");
3290 if (msecs != 0 && option == SocketOption.RCVTIMEO)
3291 msecs = max(1, msecs - WINSOCK_TIMEOUT_SKEW);
3292 setOption(level, option, msecs);
3294 else version (Posix)
3296 _ctimeval tv;
3297 value.split!("seconds", "usecs")(tv.tv_sec, tv.tv_usec);
3298 setOption(level, option, (&tv)[0 .. 1]);
3300 else static assert(false);
3304 * Get a text description of this socket's error status, and clear the
3305 * socket's error status.
3307 string getErrorText()
3309 int32_t error;
3310 getOption(SocketOptionLevel.SOCKET, SocketOption.ERROR, error);
3311 return formatSocketError(error);
3315 * Enables TCP keep-alive with the specified parameters.
3317 * Params:
3318 * time = Number of seconds with no activity until the first
3319 * keep-alive packet is sent.
3320 * interval = Number of seconds between when successive keep-alive
3321 * packets are sent if no acknowledgement is received.
3323 * Throws: $(D SocketOSException) if setting the options fails, or
3324 * $(D SocketFeatureException) if setting keep-alive parameters is
3325 * unsupported on the current platform.
3327 void setKeepAlive(int time, int interval) @trusted
3329 version (Windows)
3331 tcp_keepalive options;
3332 options.onoff = 1;
3333 options.keepalivetime = time * 1000;
3334 options.keepaliveinterval = interval * 1000;
3335 uint cbBytesReturned;
3336 enforce(WSAIoctl(sock, SIO_KEEPALIVE_VALS,
3337 &options, options.sizeof,
3338 null, 0,
3339 &cbBytesReturned, null, null) == 0,
3340 new SocketOSException("Error setting keep-alive"));
3342 else
3343 static if (is(typeof(TCP_KEEPIDLE)) && is(typeof(TCP_KEEPINTVL)))
3345 setOption(SocketOptionLevel.TCP, cast(SocketOption) TCP_KEEPIDLE, time);
3346 setOption(SocketOptionLevel.TCP, cast(SocketOption) TCP_KEEPINTVL, interval);
3347 setOption(SocketOptionLevel.SOCKET, SocketOption.KEEPALIVE, true);
3349 else
3350 throw new SocketFeatureException("Setting keep-alive options " ~
3351 "is not supported on this platform");
3355 * Wait for a socket to change status. A wait timeout of $(REF Duration, core, time) or
3356 * $(D TimeVal), may be specified; if a timeout is not specified or the
3357 * $(D TimeVal) is $(D null), the maximum timeout is used. The $(D TimeVal)
3358 * timeout has an unspecified value when $(D select) returns.
3359 * Returns: The number of sockets with status changes, $(D 0) on timeout,
3360 * or $(D -1) on interruption. If the return value is greater than $(D 0),
3361 * the $(D SocketSets) are updated to only contain the sockets having status
3362 * changes. For a connecting socket, a write status change means the
3363 * connection is established and it's able to send. For a listening socket,
3364 * a read status change means there is an incoming connection request and
3365 * it's able to accept.
3367 * `SocketSet`'s updated to include only those sockets which an event occured.
3368 * For a `connect()`ing socket, writeability means connected.
3369 * For a `listen()`ing socket, readability means listening
3370 * `Winsock`; possibly internally limited to 64 sockets per set.
3372 * Returns:
3373 * the number of events, 0 on timeout, or -1 on interruption
3375 static int select(SocketSet checkRead, SocketSet checkWrite, SocketSet checkError, Duration timeout) @trusted
3377 auto vals = timeout.split!("seconds", "usecs")();
3378 TimeVal tv;
3379 tv.seconds = cast(tv.tv_sec_t ) vals.seconds;
3380 tv.microseconds = cast(tv.tv_usec_t) vals.usecs;
3381 return select(checkRead, checkWrite, checkError, &tv);
3384 /// ditto
3385 //maximum timeout
3386 static int select(SocketSet checkRead, SocketSet checkWrite, SocketSet checkError)
3388 return select(checkRead, checkWrite, checkError, null);
3391 /// Ditto
3392 static int select(SocketSet checkRead, SocketSet checkWrite, SocketSet checkError, TimeVal* timeout) @trusted
3395 //make sure none of the SocketSet's are the same object
3396 if (checkRead)
3398 assert(checkRead !is checkWrite);
3399 assert(checkRead !is checkError);
3401 if (checkWrite)
3403 assert(checkWrite !is checkError);
3406 body
3408 fd_set* fr, fw, fe;
3409 int n = 0;
3411 version (Windows)
3413 // Windows has a problem with empty fd_set`s that aren't null.
3414 fr = checkRead && checkRead.count ? checkRead.toFd_set() : null;
3415 fw = checkWrite && checkWrite.count ? checkWrite.toFd_set() : null;
3416 fe = checkError && checkError.count ? checkError.toFd_set() : null;
3418 else
3420 if (checkRead)
3422 fr = checkRead.toFd_set();
3423 n = checkRead.selectn();
3425 else
3427 fr = null;
3430 if (checkWrite)
3432 fw = checkWrite.toFd_set();
3433 int _n;
3434 _n = checkWrite.selectn();
3435 if (_n > n)
3436 n = _n;
3438 else
3440 fw = null;
3443 if (checkError)
3445 fe = checkError.toFd_set();
3446 int _n;
3447 _n = checkError.selectn();
3448 if (_n > n)
3449 n = _n;
3451 else
3453 fe = null;
3456 // Make sure the sets' capacity matches, to avoid select reading
3457 // out of bounds just because one set was bigger than another
3458 if (checkRead ) checkRead .setMinCapacity(n);
3459 if (checkWrite) checkWrite.setMinCapacity(n);
3460 if (checkError) checkError.setMinCapacity(n);
3463 int result = .select(n, fr, fw, fe, &timeout.ctimeval);
3465 version (Windows)
3467 if (_SOCKET_ERROR == result && WSAGetLastError() == WSAEINTR)
3468 return -1;
3470 else version (Posix)
3472 if (_SOCKET_ERROR == result && errno == EINTR)
3473 return -1;
3475 else
3477 static assert(0);
3480 if (_SOCKET_ERROR == result)
3481 throw new SocketOSException("Socket select error");
3483 return result;
3488 * Can be overridden to support other addresses.
3489 * Returns: a new `Address` object for the current address family.
3491 protected Address createAddress() pure nothrow
3493 Address result;
3494 switch (_family)
3496 static if (is(sockaddr_un))
3498 case AddressFamily.UNIX:
3499 result = new UnixAddress;
3500 break;
3503 case AddressFamily.INET:
3504 result = new InternetAddress;
3505 break;
3507 case AddressFamily.INET6:
3508 result = new Internet6Address;
3509 break;
3511 default:
3512 result = new UnknownAddress;
3514 return result;
3520 /// $(D TcpSocket) is a shortcut class for a TCP Socket.
3521 class TcpSocket: Socket
3523 /// Constructs a blocking TCP Socket.
3524 this(AddressFamily family)
3526 super(family, SocketType.STREAM, ProtocolType.TCP);
3529 /// Constructs a blocking IPv4 TCP Socket.
3530 this()
3532 this(AddressFamily.INET);
3536 //shortcut
3537 /// Constructs a blocking TCP Socket and connects to an $(D Address).
3538 this(Address connectTo)
3540 this(connectTo.addressFamily);
3541 connect(connectTo);
3546 /// $(D UdpSocket) is a shortcut class for a UDP Socket.
3547 class UdpSocket: Socket
3549 /// Constructs a blocking UDP Socket.
3550 this(AddressFamily family)
3552 super(family, SocketType.DGRAM, ProtocolType.UDP);
3556 /// Constructs a blocking IPv4 UDP Socket.
3557 this()
3559 this(AddressFamily.INET);
3563 // Issue 16514
3564 @safe unittest
3566 class TestSocket : Socket
3568 override
3570 const pure nothrow @nogc @property @safe socket_t handle() { assert(0); }
3571 const nothrow @nogc @property @trusted bool blocking() { assert(0); }
3572 @property @trusted void blocking(bool byes) { assert(0); }
3573 @property @safe AddressFamily addressFamily() { assert(0); }
3574 const @property @trusted bool isAlive() { assert(0); }
3575 @trusted void bind(Address addr) { assert(0); }
3576 @trusted void connect(Address to) { assert(0); }
3577 @trusted void listen(int backlog) { assert(0); }
3578 protected pure nothrow @safe Socket accepting() { assert(0); }
3579 @trusted Socket accept() { assert(0); }
3580 nothrow @nogc @trusted void shutdown(SocketShutdown how) { assert(0); }
3581 nothrow @nogc @trusted void close() { assert(0); }
3582 @property @trusted Address remoteAddress() { assert(0); }
3583 @property @trusted Address localAddress() { assert(0); }
3584 @trusted ptrdiff_t send(const(void)[] buf, SocketFlags flags) { assert(0); }
3585 @safe ptrdiff_t send(const(void)[] buf) { assert(0); }
3586 @trusted ptrdiff_t sendTo(const(void)[] buf, SocketFlags flags, Address to) { assert(0); }
3587 @safe ptrdiff_t sendTo(const(void)[] buf, Address to) { assert(0); }
3588 @trusted ptrdiff_t sendTo(const(void)[] buf, SocketFlags flags) { assert(0); }
3589 @safe ptrdiff_t sendTo(const(void)[] buf) { assert(0); }
3590 @trusted ptrdiff_t receive(void[] buf, SocketFlags flags) { assert(0); }
3591 @safe ptrdiff_t receive(void[] buf) { assert(0); }
3592 @trusted ptrdiff_t receiveFrom(void[] buf, SocketFlags flags, ref Address from) { assert(0); }
3593 @safe ptrdiff_t receiveFrom(void[] buf, ref Address from) { assert(0); }
3594 @trusted ptrdiff_t receiveFrom(void[] buf, SocketFlags flags) { assert(0); }
3595 @safe ptrdiff_t receiveFrom(void[] buf) { assert(0); }
3596 @trusted int getOption(SocketOptionLevel level, SocketOption option, void[] result) { assert(0); }
3597 @trusted int getOption(SocketOptionLevel level, SocketOption option, out int32_t result) { assert(0); }
3598 @trusted int getOption(SocketOptionLevel level, SocketOption option, out Linger result) { assert(0); }
3599 @trusted void getOption(SocketOptionLevel level, SocketOption option, out Duration result) { assert(0); }
3600 @trusted void setOption(SocketOptionLevel level, SocketOption option, void[] value) { assert(0); }
3601 @trusted void setOption(SocketOptionLevel level, SocketOption option, int32_t value) { assert(0); }
3602 @trusted void setOption(SocketOptionLevel level, SocketOption option, Linger value) { assert(0); }
3603 @trusted void setOption(SocketOptionLevel level, SocketOption option, Duration value) { assert(0); }
3604 @safe string getErrorText() { assert(0); }
3605 @trusted void setKeepAlive(int time, int interval) { assert(0); }
3606 protected pure nothrow @safe Address createAddress() { assert(0); }
3612 * Creates a pair of connected sockets.
3614 * The two sockets are indistinguishable.
3616 * Throws: $(D SocketException) if creation of the sockets fails.
3618 Socket[2] socketPair() @trusted
3620 version (Posix)
3622 int[2] socks;
3623 if (socketpair(AF_UNIX, SOCK_STREAM, 0, socks) == -1)
3624 throw new SocketOSException("Unable to create socket pair");
3626 Socket toSocket(size_t id)
3628 auto s = new Socket;
3629 s.setSock(cast(socket_t) socks[id]);
3630 s._family = AddressFamily.UNIX;
3631 return s;
3634 return [toSocket(0), toSocket(1)];
3636 else version (Windows)
3638 // We do not have socketpair() on Windows, just manually create a
3639 // pair of sockets connected over some localhost port.
3640 Socket[2] result;
3642 auto listener = new TcpSocket();
3643 listener.setOption(SocketOptionLevel.SOCKET, SocketOption.REUSEADDR, true);
3644 listener.bind(new InternetAddress(INADDR_LOOPBACK, InternetAddress.PORT_ANY));
3645 auto addr = listener.localAddress;
3646 listener.listen(1);
3648 result[0] = new TcpSocket(addr);
3649 result[1] = listener.accept();
3651 listener.close();
3652 return result;
3654 else
3655 static assert(false);
3659 @safe unittest
3661 immutable ubyte[] data = [1, 2, 3, 4];
3662 auto pair = socketPair();
3663 scope(exit) foreach (s; pair) s.close();
3665 pair[0].send(data);
3667 auto buf = new ubyte[data.length];
3668 pair[1].receive(buf);
3669 assert(buf == data);