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