OLD | NEW |
1 // Copyright (c) 2013, the Dart project authors. Please see the AUTHORS file | 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 | 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. | 3 // BSD-style license that can be found in the LICENSE file. |
4 | 4 |
5 #if !defined(DART_IO_DISABLED) | 5 #if !defined(DART_IO_DISABLED) |
6 | 6 |
7 #include "platform/globals.h" | 7 #include "platform/globals.h" |
8 #if defined(HOST_OS_WINDOWS) | 8 #if defined(HOST_OS_WINDOWS) |
9 | 9 |
10 #include "bin/socket.h" | |
11 #include "bin/socket_win.h" | |
12 | |
13 #include "bin/builtin.h" | 10 #include "bin/builtin.h" |
14 #include "bin/eventhandler.h" | 11 #include "bin/eventhandler.h" |
15 #include "bin/file.h" | 12 #include "bin/file.h" |
16 #include "bin/lockers.h" | 13 #include "bin/lockers.h" |
17 #include "bin/log.h" | 14 #include "bin/log.h" |
| 15 #include "bin/socket.h" |
| 16 #include "bin/socket_base_win.h" |
18 #include "bin/thread.h" | 17 #include "bin/thread.h" |
19 #include "bin/utils.h" | 18 #include "bin/utils.h" |
20 #include "bin/utils_win.h" | 19 #include "bin/utils_win.h" |
21 | 20 |
22 namespace dart { | 21 namespace dart { |
23 namespace bin { | 22 namespace bin { |
24 | 23 |
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 = Socket::FormatNumericAddress(*raw, as_string_, INET6_ADDRSTRLEN); | |
32 | |
33 if (err != 0) { | |
34 as_string_[0] = 0; | |
35 } | |
36 memmove(reinterpret_cast<void*>(&addr_), sockaddr, | |
37 SocketAddress::GetAddrLength(*raw)); | |
38 } | |
39 | |
40 | |
41 bool Socket::FormatNumericAddress(const RawAddr& addr, char* address, int len) { | |
42 socklen_t salen = SocketAddress::GetAddrLength(addr); | |
43 DWORD l = len; | |
44 RawAddr& raw = const_cast<RawAddr&>(addr); | |
45 return WSAAddressToStringA(&raw.addr, salen, NULL, address, &l) != 0; | |
46 } | |
47 | |
48 | |
49 Socket::Socket(intptr_t fd) : ReferenceCounted(), fd_(fd), port_(ILLEGAL_PORT) { | 24 Socket::Socket(intptr_t fd) : ReferenceCounted(), fd_(fd), port_(ILLEGAL_PORT) { |
50 ASSERT(fd_ != kClosedFd); | 25 ASSERT(fd_ != kClosedFd); |
51 Handle* handle = reinterpret_cast<Handle*>(fd_); | 26 Handle* handle = reinterpret_cast<Handle*>(fd_); |
52 ASSERT(handle != NULL); | 27 ASSERT(handle != NULL); |
53 } | 28 } |
54 | 29 |
55 | 30 |
56 void Socket::SetClosedFd() { | 31 void Socket::SetClosedFd() { |
57 ASSERT(fd_ != kClosedFd); | 32 ASSERT(fd_ != kClosedFd); |
58 Handle* handle = reinterpret_cast<Handle*>(fd_); | 33 Handle* handle = reinterpret_cast<Handle*>(fd_); |
59 ASSERT(handle != NULL); | 34 ASSERT(handle != NULL); |
60 handle->Release(); | 35 handle->Release(); |
61 fd_ = kClosedFd; | 36 fd_ = kClosedFd; |
62 } | 37 } |
63 | 38 |
64 | 39 |
65 static Mutex* init_mutex = new Mutex(); | |
66 static bool socket_initialized = false; | |
67 | |
68 bool Socket::Initialize() { | |
69 MutexLocker lock(init_mutex); | |
70 if (socket_initialized) { | |
71 return true; | |
72 } | |
73 int err; | |
74 WSADATA winsock_data; | |
75 WORD version_requested = MAKEWORD(2, 2); | |
76 err = WSAStartup(version_requested, &winsock_data); | |
77 if (err == 0) { | |
78 socket_initialized = true; | |
79 } else { | |
80 Log::PrintErr("Unable to initialize Winsock: %d\n", WSAGetLastError()); | |
81 } | |
82 return (err == 0); | |
83 } | |
84 | |
85 | |
86 intptr_t Socket::Available(intptr_t fd) { | |
87 ClientSocket* client_socket = reinterpret_cast<ClientSocket*>(fd); | |
88 return client_socket->Available(); | |
89 } | |
90 | |
91 | |
92 intptr_t Socket::Read(intptr_t fd, void* buffer, intptr_t num_bytes) { | |
93 Handle* handle = reinterpret_cast<Handle*>(fd); | |
94 return handle->Read(buffer, num_bytes); | |
95 } | |
96 | |
97 | |
98 intptr_t Socket::RecvFrom(intptr_t fd, | |
99 void* buffer, | |
100 intptr_t num_bytes, | |
101 RawAddr* addr) { | |
102 Handle* handle = reinterpret_cast<Handle*>(fd); | |
103 socklen_t addr_len = sizeof(addr->ss); | |
104 return handle->RecvFrom(buffer, num_bytes, &addr->addr, addr_len); | |
105 } | |
106 | |
107 | |
108 intptr_t Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) { | |
109 Handle* handle = reinterpret_cast<Handle*>(fd); | |
110 return handle->Write(buffer, num_bytes); | |
111 } | |
112 | |
113 | |
114 intptr_t Socket::SendTo(intptr_t fd, | |
115 const void* buffer, | |
116 intptr_t num_bytes, | |
117 const RawAddr& addr) { | |
118 Handle* handle = reinterpret_cast<Handle*>(fd); | |
119 RawAddr& raw = const_cast<RawAddr&>(addr); | |
120 return handle->SendTo(buffer, num_bytes, &raw.addr, | |
121 SocketAddress::GetAddrLength(addr)); | |
122 } | |
123 | |
124 | |
125 intptr_t Socket::GetPort(intptr_t fd) { | |
126 ASSERT(reinterpret_cast<Handle*>(fd)->is_socket()); | |
127 SocketHandle* socket_handle = reinterpret_cast<SocketHandle*>(fd); | |
128 RawAddr raw; | |
129 socklen_t size = sizeof(raw); | |
130 if (getsockname(socket_handle->socket(), &raw.addr, &size) == SOCKET_ERROR) { | |
131 return 0; | |
132 } | |
133 return SocketAddress::GetAddrPort(raw); | |
134 } | |
135 | |
136 | |
137 SocketAddress* Socket::GetRemotePeer(intptr_t fd, intptr_t* port) { | |
138 ASSERT(reinterpret_cast<Handle*>(fd)->is_socket()); | |
139 SocketHandle* socket_handle = reinterpret_cast<SocketHandle*>(fd); | |
140 RawAddr raw; | |
141 socklen_t size = sizeof(raw); | |
142 if (getpeername(socket_handle->socket(), &raw.addr, &size)) { | |
143 return NULL; | |
144 } | |
145 *port = SocketAddress::GetAddrPort(raw); | |
146 // Clear the port before calling WSAAddressToString as WSAAddressToString | |
147 // includes the port in the formatted string. | |
148 SocketAddress::SetAddrPort(&raw, 0); | |
149 return new SocketAddress(&raw.addr); | |
150 } | |
151 | |
152 | |
153 static intptr_t Create(const RawAddr& addr) { | 40 static intptr_t Create(const RawAddr& addr) { |
154 SOCKET s = socket(addr.ss.ss_family, SOCK_STREAM, 0); | 41 SOCKET s = socket(addr.ss.ss_family, SOCK_STREAM, 0); |
155 if (s == INVALID_SOCKET) { | 42 if (s == INVALID_SOCKET) { |
156 return -1; | 43 return -1; |
157 } | 44 } |
158 | 45 |
159 linger l; | 46 linger l; |
160 l.l_onoff = 1; | 47 l.l_onoff = 1; |
161 l.l_linger = 10; | 48 l.l_linger = 10; |
162 int status = setsockopt(s, SOL_SOCKET, SO_LINGER, reinterpret_cast<char*>(&l), | 49 int status = setsockopt(s, SOL_SOCKET, SO_LINGER, reinterpret_cast<char*>(&l), |
(...skipping 84 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
247 const RawAddr& source_addr) { | 134 const RawAddr& source_addr) { |
248 intptr_t fd = Create(addr); | 135 intptr_t fd = Create(addr); |
249 if (fd < 0) { | 136 if (fd < 0) { |
250 return fd; | 137 return fd; |
251 } | 138 } |
252 | 139 |
253 return Connect(fd, addr, source_addr); | 140 return Connect(fd, addr, source_addr); |
254 } | 141 } |
255 | 142 |
256 | 143 |
257 bool Socket::IsBindError(intptr_t error_number) { | |
258 return error_number == WSAEADDRINUSE || error_number == WSAEADDRNOTAVAIL || | |
259 error_number == WSAEINVAL; | |
260 } | |
261 | |
262 | |
263 void Socket::GetError(intptr_t fd, OSError* os_error) { | |
264 Handle* handle = reinterpret_cast<Handle*>(fd); | |
265 os_error->SetCodeAndMessage(OSError::kSystem, handle->last_error()); | |
266 } | |
267 | |
268 | |
269 int Socket::GetType(intptr_t fd) { | |
270 Handle* handle = reinterpret_cast<Handle*>(fd); | |
271 switch (GetFileType(handle->handle())) { | |
272 case FILE_TYPE_CHAR: | |
273 return File::kTerminal; | |
274 case FILE_TYPE_PIPE: | |
275 return File::kPipe; | |
276 case FILE_TYPE_DISK: | |
277 return File::kFile; | |
278 default: | |
279 return GetLastError == NO_ERROR ? File::kOther : -1; | |
280 } | |
281 } | |
282 | |
283 | |
284 intptr_t Socket::GetStdioHandle(intptr_t num) { | |
285 if (num != 0) { | |
286 return -1; | |
287 } | |
288 HANDLE handle = GetStdHandle(STD_INPUT_HANDLE); | |
289 if (handle == INVALID_HANDLE_VALUE) { | |
290 return -1; | |
291 } | |
292 StdHandle* std_handle = StdHandle::Stdin(handle); | |
293 std_handle->Retain(); | |
294 std_handle->MarkDoesNotSupportOverlappedIO(); | |
295 std_handle->EnsureInitialized(EventHandler::delegate()); | |
296 return reinterpret_cast<intptr_t>(std_handle); | |
297 } | |
298 | |
299 | |
300 intptr_t ServerSocket::Accept(intptr_t fd) { | 144 intptr_t ServerSocket::Accept(intptr_t fd) { |
301 ListenSocket* listen_socket = reinterpret_cast<ListenSocket*>(fd); | 145 ListenSocket* listen_socket = reinterpret_cast<ListenSocket*>(fd); |
302 ClientSocket* client_socket = listen_socket->Accept(); | 146 ClientSocket* client_socket = listen_socket->Accept(); |
303 if (client_socket != NULL) { | 147 if (client_socket != NULL) { |
304 return reinterpret_cast<intptr_t>(client_socket); | 148 return reinterpret_cast<intptr_t>(client_socket); |
305 } else { | 149 } else { |
306 return -1; | 150 return -1; |
307 } | 151 } |
308 } | 152 } |
309 | 153 |
310 | 154 |
311 AddressList<SocketAddress>* Socket::LookupAddress(const char* host, | |
312 int type, | |
313 OSError** os_error) { | |
314 Initialize(); | |
315 | |
316 // Perform a name lookup for a host name. | |
317 struct addrinfo hints; | |
318 memset(&hints, 0, sizeof(hints)); | |
319 hints.ai_family = SocketAddress::FromType(type); | |
320 hints.ai_socktype = SOCK_STREAM; | |
321 hints.ai_flags = AI_ADDRCONFIG; | |
322 hints.ai_protocol = IPPROTO_TCP; | |
323 struct addrinfo* info = NULL; | |
324 int status = getaddrinfo(host, 0, &hints, &info); | |
325 if (status != 0) { | |
326 // We failed, try without AI_ADDRCONFIG. This can happen when looking up | |
327 // e.g. '::1', when there are no global IPv6 addresses. | |
328 hints.ai_flags = 0; | |
329 status = getaddrinfo(host, 0, &hints, &info); | |
330 } | |
331 if (status != 0) { | |
332 ASSERT(*os_error == NULL); | |
333 DWORD error_code = WSAGetLastError(); | |
334 SetLastError(error_code); | |
335 *os_error = new OSError(); | |
336 return NULL; | |
337 } | |
338 intptr_t count = 0; | |
339 for (struct addrinfo* c = info; c != NULL; c = c->ai_next) { | |
340 if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) { | |
341 count++; | |
342 } | |
343 } | |
344 AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count); | |
345 intptr_t i = 0; | |
346 for (struct addrinfo* c = info; c != NULL; c = c->ai_next) { | |
347 if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) { | |
348 addresses->SetAt(i, new SocketAddress(c->ai_addr)); | |
349 i++; | |
350 } | |
351 } | |
352 freeaddrinfo(info); | |
353 return addresses; | |
354 } | |
355 | |
356 | |
357 bool Socket::ReverseLookup(const RawAddr& addr, | |
358 char* host, | |
359 intptr_t host_len, | |
360 OSError** os_error) { | |
361 ASSERT(host_len >= NI_MAXHOST); | |
362 int status = getnameinfo(&addr.addr, SocketAddress::GetAddrLength(addr), host, | |
363 host_len, NULL, 0, NI_NAMEREQD); | |
364 if (status != 0) { | |
365 ASSERT(*os_error == NULL); | |
366 DWORD error_code = WSAGetLastError(); | |
367 SetLastError(error_code); | |
368 *os_error = new OSError(); | |
369 return false; | |
370 } | |
371 return true; | |
372 } | |
373 | |
374 | |
375 bool Socket::ParseAddress(int type, const char* address, RawAddr* addr) { | |
376 int result; | |
377 Utf8ToWideScope system_address(address); | |
378 if (type == SocketAddress::TYPE_IPV4) { | |
379 result = InetPton(AF_INET, system_address.wide(), &addr->in.sin_addr); | |
380 } else { | |
381 ASSERT(type == SocketAddress::TYPE_IPV6); | |
382 result = InetPton(AF_INET6, system_address.wide(), &addr->in6.sin6_addr); | |
383 } | |
384 return result == 1; | |
385 } | |
386 | |
387 | |
388 intptr_t Socket::CreateBindDatagram(const RawAddr& addr, bool reuseAddress) { | 155 intptr_t Socket::CreateBindDatagram(const RawAddr& addr, bool reuseAddress) { |
389 SOCKET s = socket(addr.ss.ss_family, SOCK_DGRAM, IPPROTO_UDP); | 156 SOCKET s = socket(addr.ss.ss_family, SOCK_DGRAM, IPPROTO_UDP); |
390 if (s == INVALID_SOCKET) { | 157 if (s == INVALID_SOCKET) { |
391 return -1; | 158 return -1; |
392 } | 159 } |
393 | 160 |
394 int status; | 161 int status; |
395 if (reuseAddress) { | 162 if (reuseAddress) { |
396 BOOL optval = true; | 163 BOOL optval = true; |
397 status = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, | 164 status = setsockopt(s, SOL_SOCKET, SO_REUSEADDR, |
(...skipping 13 matching lines...) Expand all Loading... |
411 SetLastError(rc); | 178 SetLastError(rc); |
412 return -1; | 179 return -1; |
413 } | 180 } |
414 | 181 |
415 DatagramSocket* datagram_socket = new DatagramSocket(s); | 182 DatagramSocket* datagram_socket = new DatagramSocket(s); |
416 datagram_socket->EnsureInitialized(EventHandler::delegate()); | 183 datagram_socket->EnsureInitialized(EventHandler::delegate()); |
417 return reinterpret_cast<intptr_t>(datagram_socket); | 184 return reinterpret_cast<intptr_t>(datagram_socket); |
418 } | 185 } |
419 | 186 |
420 | 187 |
421 bool Socket::ListInterfacesSupported() { | |
422 return true; | |
423 } | |
424 | |
425 | |
426 AddressList<InterfaceSocketAddress>* Socket::ListInterfaces( | |
427 int type, | |
428 OSError** os_error) { | |
429 Initialize(); | |
430 | |
431 ULONG size = 0; | |
432 DWORD flags = GAA_FLAG_SKIP_ANYCAST | GAA_FLAG_SKIP_MULTICAST | | |
433 GAA_FLAG_SKIP_DNS_SERVER; | |
434 // Query the size needed. | |
435 int status = GetAdaptersAddresses(SocketAddress::FromType(type), flags, NULL, | |
436 NULL, &size); | |
437 IP_ADAPTER_ADDRESSES* addrs = NULL; | |
438 if (status == ERROR_BUFFER_OVERFLOW) { | |
439 addrs = reinterpret_cast<IP_ADAPTER_ADDRESSES*>(malloc(size)); | |
440 // Get the addresses now we have the right buffer. | |
441 status = GetAdaptersAddresses(SocketAddress::FromType(type), flags, NULL, | |
442 addrs, &size); | |
443 } | |
444 if (status != NO_ERROR) { | |
445 ASSERT(*os_error == NULL); | |
446 DWORD error_code = WSAGetLastError(); | |
447 SetLastError(error_code); | |
448 *os_error = new OSError(); | |
449 return NULL; | |
450 } | |
451 intptr_t count = 0; | |
452 for (IP_ADAPTER_ADDRESSES* a = addrs; a != NULL; a = a->Next) { | |
453 for (IP_ADAPTER_UNICAST_ADDRESS* u = a->FirstUnicastAddress; u != NULL; | |
454 u = u->Next) { | |
455 count++; | |
456 } | |
457 } | |
458 AddressList<InterfaceSocketAddress>* addresses = | |
459 new AddressList<InterfaceSocketAddress>(count); | |
460 intptr_t i = 0; | |
461 for (IP_ADAPTER_ADDRESSES* a = addrs; a != NULL; a = a->Next) { | |
462 for (IP_ADAPTER_UNICAST_ADDRESS* u = a->FirstUnicastAddress; u != NULL; | |
463 u = u->Next) { | |
464 addresses->SetAt( | |
465 i, new InterfaceSocketAddress( | |
466 u->Address.lpSockaddr, | |
467 StringUtilsWin::WideToUtf8(a->FriendlyName), a->Ipv6IfIndex)); | |
468 i++; | |
469 } | |
470 } | |
471 free(addrs); | |
472 return addresses; | |
473 } | |
474 | |
475 | |
476 intptr_t ServerSocket::CreateBindListen(const RawAddr& addr, | 188 intptr_t ServerSocket::CreateBindListen(const RawAddr& addr, |
477 intptr_t backlog, | 189 intptr_t backlog, |
478 bool v6_only) { | 190 bool v6_only) { |
479 SOCKET s = socket(addr.ss.ss_family, SOCK_STREAM, IPPROTO_TCP); | 191 SOCKET s = socket(addr.ss.ss_family, SOCK_STREAM, IPPROTO_TCP); |
480 if (s == INVALID_SOCKET) { | 192 if (s == INVALID_SOCKET) { |
481 return -1; | 193 return -1; |
482 } | 194 } |
483 | 195 |
484 BOOL optval = true; | 196 BOOL optval = true; |
485 int status = | 197 int status = |
(...skipping 17 matching lines...) Expand all Loading... |
503 DWORD rc = WSAGetLastError(); | 215 DWORD rc = WSAGetLastError(); |
504 closesocket(s); | 216 closesocket(s); |
505 SetLastError(rc); | 217 SetLastError(rc); |
506 return -1; | 218 return -1; |
507 } | 219 } |
508 | 220 |
509 ListenSocket* listen_socket = new ListenSocket(s); | 221 ListenSocket* listen_socket = new ListenSocket(s); |
510 | 222 |
511 // Test for invalid socket port 65535 (some browsers disallow it). | 223 // Test for invalid socket port 65535 (some browsers disallow it). |
512 if ((SocketAddress::GetAddrPort(addr) == 0) && | 224 if ((SocketAddress::GetAddrPort(addr) == 0) && |
513 (Socket::GetPort(reinterpret_cast<intptr_t>(listen_socket)) == 65535)) { | 225 (SocketBase::GetPort(reinterpret_cast<intptr_t>(listen_socket)) == |
| 226 65535)) { |
514 // Don't close fd until we have created new. By doing that we ensure another | 227 // Don't close fd until we have created new. By doing that we ensure another |
515 // port. | 228 // port. |
516 intptr_t new_s = CreateBindListen(addr, backlog, v6_only); | 229 intptr_t new_s = CreateBindListen(addr, backlog, v6_only); |
517 DWORD rc = WSAGetLastError(); | 230 DWORD rc = WSAGetLastError(); |
518 closesocket(s); | 231 closesocket(s); |
519 listen_socket->Release(); | 232 listen_socket->Release(); |
520 SetLastError(rc); | 233 SetLastError(rc); |
521 return new_s; | 234 return new_s; |
522 } | 235 } |
523 | 236 |
(...skipping 23 matching lines...) Expand all Loading... |
547 // the event-handler will take care of deleting it. | 260 // the event-handler will take care of deleting it. |
548 listen_socket->Release(); | 261 listen_socket->Release(); |
549 } | 262 } |
550 SetLastError(rc); | 263 SetLastError(rc); |
551 return false; | 264 return false; |
552 } | 265 } |
553 } | 266 } |
554 return true; | 267 return true; |
555 } | 268 } |
556 | 269 |
557 | |
558 void Socket::Close(intptr_t fd) { | |
559 ClientSocket* client_socket = reinterpret_cast<ClientSocket*>(fd); | |
560 client_socket->Close(); | |
561 } | |
562 | |
563 | |
564 bool Socket::GetNoDelay(intptr_t fd, bool* enabled) { | |
565 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd); | |
566 int on; | |
567 socklen_t len = sizeof(on); | |
568 int err = getsockopt(handle->socket(), IPPROTO_TCP, TCP_NODELAY, | |
569 reinterpret_cast<char*>(&on), &len); | |
570 if (err == 0) { | |
571 *enabled = (on == 1); | |
572 } | |
573 return (err == 0); | |
574 } | |
575 | |
576 | |
577 bool Socket::SetNoDelay(intptr_t fd, bool enabled) { | |
578 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd); | |
579 int on = enabled ? 1 : 0; | |
580 return setsockopt(handle->socket(), IPPROTO_TCP, TCP_NODELAY, | |
581 reinterpret_cast<char*>(&on), sizeof(on)) == 0; | |
582 } | |
583 | |
584 | |
585 bool Socket::GetMulticastLoop(intptr_t fd, intptr_t protocol, bool* enabled) { | |
586 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd); | |
587 uint8_t on; | |
588 socklen_t len = sizeof(on); | |
589 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; | |
590 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_LOOP | |
591 : IPV6_MULTICAST_LOOP; | |
592 if (getsockopt(handle->socket(), level, optname, reinterpret_cast<char*>(&on), | |
593 &len) == 0) { | |
594 *enabled = (on == 1); | |
595 return true; | |
596 } | |
597 return false; | |
598 } | |
599 | |
600 | |
601 bool Socket::SetMulticastLoop(intptr_t fd, intptr_t protocol, bool enabled) { | |
602 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd); | |
603 int on = enabled ? 1 : 0; | |
604 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; | |
605 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_LOOP | |
606 : IPV6_MULTICAST_LOOP; | |
607 return setsockopt(handle->socket(), level, optname, | |
608 reinterpret_cast<char*>(&on), sizeof(on)) == 0; | |
609 } | |
610 | |
611 | |
612 bool Socket::GetMulticastHops(intptr_t fd, intptr_t protocol, int* value) { | |
613 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd); | |
614 uint8_t v; | |
615 socklen_t len = sizeof(v); | |
616 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; | |
617 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_TTL | |
618 : IPV6_MULTICAST_HOPS; | |
619 if (getsockopt(handle->socket(), level, optname, reinterpret_cast<char*>(&v), | |
620 &len) == 0) { | |
621 *value = v; | |
622 return true; | |
623 } | |
624 return false; | |
625 } | |
626 | |
627 | |
628 bool Socket::SetMulticastHops(intptr_t fd, intptr_t protocol, int value) { | |
629 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd); | |
630 int v = value; | |
631 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; | |
632 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_TTL | |
633 : IPV6_MULTICAST_HOPS; | |
634 return setsockopt(handle->socket(), level, optname, | |
635 reinterpret_cast<char*>(&v), sizeof(v)) == 0; | |
636 } | |
637 | |
638 | |
639 bool Socket::GetBroadcast(intptr_t fd, bool* enabled) { | |
640 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd); | |
641 int on; | |
642 socklen_t len = sizeof(on); | |
643 int err = getsockopt(handle->socket(), SOL_SOCKET, SO_BROADCAST, | |
644 reinterpret_cast<char*>(&on), &len); | |
645 if (err == 0) { | |
646 *enabled = (on == 1); | |
647 } | |
648 return (err == 0); | |
649 } | |
650 | |
651 | |
652 bool Socket::SetBroadcast(intptr_t fd, bool enabled) { | |
653 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd); | |
654 int on = enabled ? 1 : 0; | |
655 return setsockopt(handle->socket(), SOL_SOCKET, SO_BROADCAST, | |
656 reinterpret_cast<char*>(&on), sizeof(on)) == 0; | |
657 } | |
658 | |
659 | |
660 bool Socket::JoinMulticast(intptr_t fd, | |
661 const RawAddr& addr, | |
662 const RawAddr&, | |
663 int interfaceIndex) { | |
664 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd); | |
665 int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; | |
666 struct group_req mreq; | |
667 mreq.gr_interface = interfaceIndex; | |
668 memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr)); | |
669 return setsockopt(handle->socket(), proto, MCAST_JOIN_GROUP, | |
670 reinterpret_cast<char*>(&mreq), sizeof(mreq)) == 0; | |
671 } | |
672 | |
673 | |
674 bool Socket::LeaveMulticast(intptr_t fd, | |
675 const RawAddr& addr, | |
676 const RawAddr&, | |
677 int interfaceIndex) { | |
678 SocketHandle* handle = reinterpret_cast<SocketHandle*>(fd); | |
679 int proto = addr.addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; | |
680 struct group_req mreq; | |
681 mreq.gr_interface = interfaceIndex; | |
682 memmove(&mreq.gr_group, &addr.ss, SocketAddress::GetAddrLength(addr)); | |
683 return setsockopt(handle->socket(), proto, MCAST_LEAVE_GROUP, | |
684 reinterpret_cast<char*>(&mreq), sizeof(mreq)) == 0; | |
685 } | |
686 | |
687 } // namespace bin | 270 } // namespace bin |
688 } // namespace dart | 271 } // namespace dart |
689 | 272 |
690 #endif // defined(HOST_OS_WINDOWS) | 273 #endif // defined(HOST_OS_WINDOWS) |
691 | 274 |
692 #endif // !defined(DART_IO_DISABLED) | 275 #endif // !defined(DART_IO_DISABLED) |
OLD | NEW |