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