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