OLD | NEW |
| (Empty) |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | |
2 // for details. All rights reserved. Use of this source code is governed by a | |
3 // BSD-style license that can be found in the LICENSE file. | |
4 | |
5 #if !defined(DART_IO_DISABLED) | |
6 | |
7 #include "platform/globals.h" | |
8 #if defined(HOST_OS_WINDOWS) | |
9 | |
10 #include "bin/socket_base.h" | |
11 | |
12 #include "bin/builtin.h" | |
13 #include "bin/eventhandler.h" | |
14 #include "bin/file.h" | |
15 #include "bin/lockers.h" | |
16 #include "bin/log.h" | |
17 #include "bin/socket_base_win.h" | |
18 #include "bin/thread.h" | |
19 #include "bin/utils.h" | |
20 #include "bin/utils_win.h" | |
21 | |
22 namespace dart { | |
23 namespace bin { | |
24 | |
25 SocketAddress::SocketAddress(struct sockaddr* sockaddr) { | |
26 ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN); | |
27 RawAddr* raw = reinterpret_cast<RawAddr*>(sockaddr); | |
28 | |
29 // Clear the port before calling WSAAddressToString as WSAAddressToString | |
30 // includes the port in the formatted string. | |
31 int err = | |
32 SocketBase::FormatNumericAddress(*raw, as_string_, INET6_ADDRSTRLEN); | |
33 | |
34 if (err != 0) { | |
35 as_string_[0] = 0; | |
36 } | |
37 memmove(reinterpret_cast<void*>(&addr_), sockaddr, | |
38 SocketAddress::GetAddrLength(*raw)); | |
39 } | |
40 | |
41 | |
42 bool SocketBase::FormatNumericAddress(const RawAddr& addr, | |
43 char* address, | |
44 int len) { | |
45 socklen_t salen = SocketAddress::GetAddrLength(addr); | |
46 DWORD l = len; | |
47 RawAddr& raw = const_cast<RawAddr&>(addr); | |
48 return WSAAddressToStringA(&raw.addr, salen, NULL, address, &l) != 0; | |
49 } | |
50 | |
51 | |
52 intptr_t SocketBase::Available(intptr_t fd) { | |
53 ClientSocket* client_socket = reinterpret_cast<ClientSocket*>(fd); | |
54 return client_socket->Available(); | |
55 } | |
56 | |
57 | |
58 intptr_t SocketBase::Read(intptr_t fd, void* buffer, intptr_t num_bytes) { | |
59 Handle* handle = reinterpret_cast<Handle*>(fd); | |
60 return handle->Read(buffer, num_bytes); | |
61 } | |
62 | |
63 | |
64 intptr_t SocketBase::RecvFrom(intptr_t fd, | |
65 void* buffer, | |
66 intptr_t num_bytes, | |
67 RawAddr* addr) { | |
68 Handle* handle = reinterpret_cast<Handle*>(fd); | |
69 socklen_t addr_len = sizeof(addr->ss); | |
70 return handle->RecvFrom(buffer, num_bytes, &addr->addr, addr_len); | |
71 } | |
72 | |
73 | |
74 intptr_t SocketBase::Write(intptr_t fd, | |
75 const void* buffer, | |
76 intptr_t num_bytes) { | |
77 Handle* handle = reinterpret_cast<Handle*>(fd); | |
78 return handle->Write(buffer, num_bytes); | |
79 } | |
80 | |
81 | |
82 intptr_t SocketBase::SendTo(intptr_t fd, | |
83 const void* buffer, | |
84 intptr_t num_bytes, | |
85 const RawAddr& addr) { | |
86 Handle* handle = reinterpret_cast<Handle*>(fd); | |
87 RawAddr& raw = const_cast<RawAddr&>(addr); | |
88 return handle->SendTo(buffer, num_bytes, &raw.addr, | |
89 SocketAddress::GetAddrLength(addr)); | |
90 } | |
91 | |
92 | |
93 intptr_t SocketBase::GetPort(intptr_t fd) { | |
94 ASSERT(reinterpret_cast<Handle*>(fd)->is_socket()); | |
95 SocketHandle* socket_handle = reinterpret_cast<SocketHandle*>(fd); | |
96 RawAddr raw; | |
97 socklen_t size = sizeof(raw); | |
98 if (getsockname(socket_handle->socket(), &raw.addr, &size) == SOCKET_ERROR) { | |
99 return 0; | |
100 } | |
101 return SocketAddress::GetAddrPort(raw); | |
102 } | |
103 | |
104 | |
105 SocketAddress* SocketBase::GetRemotePeer(intptr_t fd, intptr_t* port) { | |
106 ASSERT(reinterpret_cast<Handle*>(fd)->is_socket()); | |
107 SocketHandle* socket_handle = reinterpret_cast<SocketHandle*>(fd); | |
108 RawAddr raw; | |
109 socklen_t size = sizeof(raw); | |
110 if (getpeername(socket_handle->socket(), &raw.addr, &size)) { | |
111 return NULL; | |
112 } | |
113 *port = SocketAddress::GetAddrPort(raw); | |
114 // Clear the port before calling WSAAddressToString as WSAAddressToString | |
115 // includes the port in the formatted string. | |
116 SocketAddress::SetAddrPort(&raw, 0); | |
117 return new SocketAddress(&raw.addr); | |
118 } | |
119 | |
120 | |
121 bool SocketBase::IsBindError(intptr_t error_number) { | |
122 return error_number == WSAEADDRINUSE || error_number == WSAEADDRNOTAVAIL || | |
123 error_number == WSAEINVAL; | |
124 } | |
125 | |
126 | |
127 void SocketBase::GetError(intptr_t fd, OSError* os_error) { | |
128 Handle* handle = reinterpret_cast<Handle*>(fd); | |
129 os_error->SetCodeAndMessage(OSError::kSystem, handle->last_error()); | |
130 } | |
131 | |
132 | |
133 int SocketBase::GetType(intptr_t fd) { | |
134 Handle* handle = reinterpret_cast<Handle*>(fd); | |
135 switch (GetFileType(handle->handle())) { | |
136 case FILE_TYPE_CHAR: | |
137 return File::kTerminal; | |
138 case FILE_TYPE_PIPE: | |
139 return File::kPipe; | |
140 case FILE_TYPE_DISK: | |
141 return File::kFile; | |
142 default: | |
143 return GetLastError == NO_ERROR ? File::kOther : -1; | |
144 } | |
145 } | |
146 | |
147 | |
148 intptr_t SocketBase::GetStdioHandle(intptr_t num) { | |
149 if (num != 0) { | |
150 return -1; | |
151 } | |
152 HANDLE handle = GetStdHandle(STD_INPUT_HANDLE); | |
153 if (handle == INVALID_HANDLE_VALUE) { | |
154 return -1; | |
155 } | |
156 StdHandle* std_handle = new StdHandle(handle); | |
157 std_handle->MarkDoesNotSupportOverlappedIO(); | |
158 std_handle->EnsureInitialized(EventHandler::delegate()); | |
159 return reinterpret_cast<intptr_t>(std_handle); | |
160 } | |
161 | |
162 | |
163 intptr_t ServerSocket::Accept(intptr_t fd) { | |
164 ListenSocket* listen_socket = reinterpret_cast<ListenSocket*>(fd); | |
165 ClientSocket* client_socket = listen_socket->Accept(); | |
166 if (client_socket != NULL) { | |
167 return reinterpret_cast<intptr_t>(client_socket); | |
168 } else { | |
169 return -1; | |
170 } | |
171 } | |
172 | |
173 | |
174 AddressList<SocketAddress>* SocketBase::LookupAddress(const char* host, | |
175 int type, | |
176 OSError** os_error) { | |
177 Initialize(); | |
178 | |
179 // Perform a name lookup for a host name. | |
180 struct addrinfo hints; | |
181 memset(&hints, 0, sizeof(hints)); | |
182 hints.ai_family = SocketAddress::FromType(type); | |
183 hints.ai_socktype = SOCK_STREAM; | |
184 hints.ai_flags = AI_ADDRCONFIG; | |
185 hints.ai_protocol = IPPROTO_TCP; | |
186 struct addrinfo* info = NULL; | |
187 int status = getaddrinfo(host, 0, &hints, &info); | |
188 if (status != 0) { | |
189 // We failed, try without AI_ADDRCONFIG. This can happen when looking up | |
190 // e.g. '::1', when there are no global IPv6 addresses. | |
191 hints.ai_flags = 0; | |
192 status = getaddrinfo(host, 0, &hints, &info); | |
193 } | |
194 if (status != 0) { | |
195 ASSERT(*os_error == NULL); | |
196 DWORD error_code = WSAGetLastError(); | |
197 SetLastError(error_code); | |
198 *os_error = new OSError(); | |
199 return NULL; | |
200 } | |
201 intptr_t count = 0; | |
202 for (struct addrinfo* c = info; c != NULL; c = c->ai_next) { | |
203 if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) { | |
204 count++; | |
205 } | |
206 } | |
207 AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count); | |
208 intptr_t i = 0; | |
209 for (struct addrinfo* c = info; c != NULL; c = c->ai_next) { | |
210 if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) { | |
211 addresses->SetAt(i, new SocketAddress(c->ai_addr)); | |
212 i++; | |
213 } | |
214 } | |
215 freeaddrinfo(info); | |
216 return addresses; | |
217 } | |
218 | |
219 | |
220 bool SocketBase::ReverseLookup(const RawAddr& addr, | |
221 char* host, | |
222 intptr_t host_len, | |
223 OSError** os_error) { | |
224 ASSERT(host_len >= NI_MAXHOST); | |
225 int status = getnameinfo(&addr.addr, SocketAddress::GetAddrLength(addr), host, | |
226 host_len, NULL, 0, NI_NAMEREQD); | |
227 if (status != 0) { | |
228 ASSERT(*os_error == NULL); | |
229 DWORD error_code = WSAGetLastError(); | |
230 SetLastError(error_code); | |
231 *os_error = new OSError(); | |
232 return false; | |
233 } | |
234 return true; | |
235 } | |
236 | |
237 | |
238 bool SocketBase::ParseAddress(int type, const char* address, RawAddr* addr) { | |
239 int result; | |
240 Utf8ToWideScope system_address(address); | |
241 if (type == SocketAddress::TYPE_IPV4) { | |
242 result = InetPton(AF_INET, system_address.wide(), &addr->in.sin_addr); | |
243 } else { | |
244 ASSERT(type == SocketAddress::TYPE_IPV6); | |
245 result = InetPton(AF_INET6, system_address.wide(), &addr->in6.sin6_addr); | |
246 } | |
247 return result == 1; | |
248 } | |
249 | |
250 | |
251 bool SocketBase::ListInterfacesSupported() { | |
252 return true; | |
253 } | |
254 | |
255 | |
256 AddressList<InterfaceSocketAddress>* SocketBase::ListInterfaces( | |
257 int type, | |
258 OSError** os_error) { | |
259 Initialize(); | |
260 | |
261 ULONG size = 0; | |
262 DWORD flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | | |
263 GAA_FLAG_SKIP_DNS_SERVER; | |
264 // Query the size needed. | |
265 int status = GetAdaptersAddresses(SocketAddress::FromType(type), flags, NULL, | |
266 NULL, &size); | |
267 IP_ADAPTER_ADDRESSES* addrs = NULL; | |
268 if (status == ERROR_BUFFER_OVERFLOW) { | |
269 addrs = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(malloc(size)); | |
270 // Get the addresses now we have the right buffer. | |
271 status = GetAdaptersAddresses(SocketAddress::FromType(type), flags, NULL, | |
272 addrs, &size); | |
273 } | |
274 if (status != NO_ERROR) { | |
275 ASSERT(*os_error == NULL); | |
276 DWORD error_code = WSAGetLastError(); | |
277 SetLastError(error_code); | |
278 *os_error = new OSError(); | |
279 return NULL; | |
280 } | |
281 intptr_t count = 0; | |
282 for (IP_ADAPTER_ADDRESSES* a = addrs; a != NULL; a = a->Next) { | |
283 for (IP_ADAPTER_UNICAST_ADDRESS* u = a->FirstUnicastAddress; u != NULL; | |
284 u = u->Next) { | |
285 count++; | |
286 } | |
287 } | |
288 AddressList<InterfaceSocketAddress>* addresses = | |
289 new AddressList<InterfaceSocketAddress>(count); | |
290 intptr_t i = 0; | |
291 for (IP_ADAPTER_ADDRESSES* a = addrs; a != NULL; a = a->Next) { | |
292 for (IP_ADAPTER_UNICAST_ADDRESS* u = a->FirstUnicastAddress; u != NULL; | |
293 u = u->Next) { | |
294 addresses->SetAt( | |
295 i, new InterfaceSocketAddress( | |
296 u->Address.lpSockaddr, | |
297 StringUtilsWin::WideToUtf8(a->FriendlyName), a->Ipv6IfIndex)); | |
298 i++; | |
299 } | |
300 } | |
301 free(addrs); | |
302 return addresses; | |
303 } | |
304 | |
305 | |
306 void SocketBase::Close(intptr_t fd) { | |
307 ClientSocket* client_socket = reinterpret_cast<ClientSocket*>(fd); | |
308 client_socket->Close(); | |
309 } | |
310 | |
311 | |
312 bool SocketBase::GetNoDelay(intptr_t fd, bool* enabled) { | |
313 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd); | |
314 int on; | |
315 socklen_t len = sizeof(on); | |
316 int err = getsockopt(handle->socket(), IPPROTO_TCP, TCP_NODELAY, | |
317 reinterpret_cast<char*>(&on), &len); | |
318 if (err == 0) { | |
319 *enabled = (on == 1); | |
320 } | |
321 return (err == 0); | |
322 } | |
323 | |
324 | |
325 bool SocketBase::SetNoDelay(intptr_t fd, bool enabled) { | |
326 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd); | |
327 int on = enabled ? 1 : 0; | |
328 return setsockopt(handle->socket(), IPPROTO_TCP, TCP_NODELAY, | |
329 reinterpret_cast<char*>(&on), sizeof(on)) == 0; | |
330 } | |
331 | |
332 | |
333 bool SocketBase::GetMulticastLoop(intptr_t fd, | |
334 intptr_t protocol, | |
335 bool* enabled) { | |
336 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd); | |
337 uint8_t on; | |
338 socklen_t len = sizeof(on); | |
339 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; | |
340 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_LOOP | |
341 : IPV6_MULTICAST_LOOP; | |
342 if (getsockopt(handle->socket(), level, optname, reinterpret_cast<char*>(&on), | |
343 &len) == 0) { | |
344 *enabled = (on == 1); | |
345 return true; | |
346 } | |
347 return false; | |
348 } | |
349 | |
350 | |
351 bool SocketBase::SetMulticastLoop(intptr_t fd, | |
352 intptr_t protocol, | |
353 bool enabled) { | |
354 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd); | |
355 int on = enabled ? 1 : 0; | |
356 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; | |
357 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_LOOP | |
358 : IPV6_MULTICAST_LOOP; | |
359 return setsockopt(handle->socket(), level, optname, | |
360 reinterpret_cast<char*>(&on), sizeof(on)) == 0; | |
361 } | |
362 | |
363 | |
364 bool SocketBase::GetMulticastHops(intptr_t fd, intptr_t protocol, int* value) { | |
365 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd); | |
366 uint8_t v; | |
367 socklen_t len = sizeof(v); | |
368 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; | |
369 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_TTL | |
370 : IPV6_MULTICAST_HOPS; | |
371 if (getsockopt(handle->socket(), level, optname, reinterpret_cast<char*>(&v), | |
372 &len) == 0) { | |
373 *value = v; | |
374 return true; | |
375 } | |
376 return false; | |
377 } | |
378 | |
379 | |
380 bool SocketBase::SetMulticastHops(intptr_t fd, intptr_t protocol, int value) { | |
381 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd); | |
382 int v = value; | |
383 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; | |
384 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_TTL | |
385 : IPV6_MULTICAST_HOPS; | |
386 return setsockopt(handle->socket(), level, optname, | |
387 reinterpret_cast<char*>(&v), sizeof(v)) == 0; | |
388 } | |
389 | |
390 | |
391 bool SocketBase::GetBroadcast(intptr_t fd, bool* enabled) { | |
392 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd); | |
393 int on; | |
394 socklen_t len = sizeof(on); | |
395 int err = getsockopt(handle->socket(), SOL_SOCKET, SO_BROADCAST, | |
396 reinterpret_cast<char*>(&on), &len); | |
397 if (err == 0) { | |
398 *enabled = (on == 1); | |
399 } | |
400 return (err == 0); | |
401 } | |
402 | |
403 | |
404 bool SocketBase::SetBroadcast(intptr_t fd, bool enabled) { | |
405 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd); | |
406 int on = enabled ? 1 : 0; | |
407 return setsockopt(handle->socket(), SOL_SOCKET, SO_BROADCAST, | |
408 reinterpret_cast<char*>(&on), sizeof(on)) == 0; | |
409 } | |
410 | |
411 | |
412 bool SocketBase::JoinMulticast(intptr_t fd, | |
413 const RawAddr& addr, | |
414 const RawAddr&, | |
415 int interfaceIndex) { | |
416 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd); | |
417 int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; | |
418 struct group_req mreq; | |
419 mreq.gr_interface = interfaceIndex; | |
420 memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr)); | |
421 return setsockopt(handle->socket(), proto, MCAST_JOIN_GROUP, | |
422 reinterpret_cast<char*>(&mreq), sizeof(mreq)) == 0; | |
423 } | |
424 | |
425 | |
426 bool SocketBase::LeaveMulticast(intptr_t fd, | |
427 const RawAddr& addr, | |
428 const RawAddr&, | |
429 int interfaceIndex) { | |
430 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd); | |
431 int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; | |
432 struct group_req mreq; | |
433 mreq.gr_interface = interfaceIndex; | |
434 memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr)); | |
435 return setsockopt(handle->socket(), proto, MCAST_LEAVE_GROUP, | |
436 reinterpret_cast<char*>(&mreq), sizeof(mreq)) == 0; | |
437 } | |
438 | |
439 } // namespace bin | |
440 } // namespace dart | |
441 | |
442 #endif // defined(HOST_OS_WINDOWS) | |
443 | |
444 #endif // !defined(DART_IO_DISABLED) | |
OLD | NEW |