annotate libphobos/src/std/socket.d @ 158:494b0b89df80 default tip

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