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 #include "platform/globals.h" | 5 #include "platform/globals.h" |
6 #if defined(TARGET_OS_MACOS) | 6 #if defined(TARGET_OS_MACOS) |
7 | 7 |
8 #include <errno.h> // NOLINT | 8 #include <errno.h> // NOLINT |
9 #include <stdio.h> // NOLINT | 9 #include <stdio.h> // NOLINT |
10 #include <stdlib.h> // NOLINT | 10 #include <stdlib.h> // NOLINT |
11 #include <string.h> // NOLINT | 11 #include <string.h> // NOLINT |
12 #include <sys/stat.h> // NOLINT | 12 #include <sys/stat.h> // NOLINT |
13 #include <unistd.h> // NOLINT | 13 #include <unistd.h> // NOLINT |
14 #include <net/if.h> // NOLINT | 14 #include <net/if.h> // NOLINT |
15 #include <netinet/tcp.h> // NOLINT | 15 #include <netinet/tcp.h> // NOLINT |
16 #include <ifaddrs.h> // NOLINT | 16 #include <ifaddrs.h> // NOLINT |
17 | 17 |
18 #include "bin/fdutils.h" | 18 #include "bin/fdutils.h" |
19 #include "bin/file.h" | 19 #include "bin/file.h" |
20 #include "bin/log.h" | 20 #include "bin/log.h" |
21 #include "bin/socket.h" | 21 #include "bin/socket.h" |
22 | 22 |
23 | 23 |
24 namespace dart { | 24 namespace dart { |
25 namespace bin { | 25 namespace bin { |
26 | 26 |
27 SocketAddress::SocketAddress(struct sockaddr* sa) { | 27 SocketAddress::SocketAddress(struct sockaddr* sa) { |
28 ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN); | 28 ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN); |
29 socklen_t salen = GetAddrLength(reinterpret_cast<RawAddr*>(sa)); | 29 if (!Socket::FormatNumericAddress( |
30 if (TEMP_FAILURE_RETRY(getnameinfo(sa, | 30 reinterpret_cast<RawAddr*>(sa), as_string_, INET6_ADDRSTRLEN)) { |
31 salen, | |
32 as_string_, | |
33 INET6_ADDRSTRLEN, | |
34 NULL, | |
35 0, | |
36 NI_NUMERICHOST)) != 0) { | |
37 as_string_[0] = 0; | 31 as_string_[0] = 0; |
38 } | 32 } |
| 33 socklen_t salen = GetAddrLength(reinterpret_cast<RawAddr*>(sa)); |
39 memmove(reinterpret_cast<void *>(&addr_), sa, salen); | 34 memmove(reinterpret_cast<void *>(&addr_), sa, salen); |
40 } | 35 } |
41 | 36 |
42 | 37 |
| 38 bool Socket::FormatNumericAddress(RawAddr* addr, char* address, int len) { |
| 39 socklen_t salen = SocketAddress::GetAddrLength(addr); |
| 40 if (TEMP_FAILURE_RETRY(getnameinfo(&addr->addr, |
| 41 salen, |
| 42 address, |
| 43 len, |
| 44 NULL, |
| 45 0, |
| 46 NI_NUMERICHOST)) != 0) { |
| 47 return false; |
| 48 } |
| 49 return true; |
| 50 } |
| 51 |
| 52 |
43 bool Socket::Initialize() { | 53 bool Socket::Initialize() { |
44 // Nothing to do on Mac OS. | 54 // Nothing to do on Mac OS. |
45 return true; | 55 return true; |
46 } | 56 } |
47 | 57 |
48 | 58 |
49 intptr_t Socket::Create(RawAddr addr) { | 59 intptr_t Socket::Create(RawAddr addr) { |
50 intptr_t fd; | 60 intptr_t fd; |
51 | 61 |
52 fd = TEMP_FAILURE_RETRY(socket(addr.ss.ss_family, SOCK_STREAM, 0)); | 62 fd = TEMP_FAILURE_RETRY(socket(addr.ss.ss_family, SOCK_STREAM, 0)); |
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
100 ASSERT(EAGAIN == EWOULDBLOCK); | 110 ASSERT(EAGAIN == EWOULDBLOCK); |
101 if (read_bytes == -1 && errno == EWOULDBLOCK) { | 111 if (read_bytes == -1 && errno == EWOULDBLOCK) { |
102 // If the read would block we need to retry and therefore return 0 | 112 // If the read would block we need to retry and therefore return 0 |
103 // as the number of bytes written. | 113 // as the number of bytes written. |
104 read_bytes = 0; | 114 read_bytes = 0; |
105 } | 115 } |
106 return read_bytes; | 116 return read_bytes; |
107 } | 117 } |
108 | 118 |
109 | 119 |
| 120 int Socket::RecvFrom(intptr_t fd, void* buffer, intptr_t num_bytes, |
| 121 RawAddr* addr) { |
| 122 ASSERT(fd >= 0); |
| 123 socklen_t addr_len = sizeof(addr->ss); |
| 124 ssize_t read_bytes = |
| 125 TEMP_FAILURE_RETRY( |
| 126 recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len)); |
| 127 if (read_bytes == -1 && errno == EWOULDBLOCK) { |
| 128 // If the read would block we need to retry and therefore return 0 |
| 129 // as the number of bytes written. |
| 130 read_bytes = 0; |
| 131 } |
| 132 return read_bytes; |
| 133 } |
| 134 |
| 135 |
110 int Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) { | 136 int Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) { |
111 ASSERT(fd >= 0); | 137 ASSERT(fd >= 0); |
112 ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes)); | 138 ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes)); |
113 ASSERT(EAGAIN == EWOULDBLOCK); | 139 ASSERT(EAGAIN == EWOULDBLOCK); |
114 if (written_bytes == -1 && errno == EWOULDBLOCK) { | 140 if (written_bytes == -1 && errno == EWOULDBLOCK) { |
115 // If the would block we need to retry and therefore return 0 as | 141 // If the would block we need to retry and therefore return 0 as |
116 // the number of bytes written. | 142 // the number of bytes written. |
117 written_bytes = 0; | 143 written_bytes = 0; |
118 } | 144 } |
119 return written_bytes; | 145 return written_bytes; |
120 } | 146 } |
121 | 147 |
122 | 148 |
| 149 int Socket::SendTo(intptr_t fd, const void* buffer, intptr_t num_bytes, |
| 150 RawAddr addr) { |
| 151 ASSERT(fd >= 0); |
| 152 ssize_t written_bytes = |
| 153 TEMP_FAILURE_RETRY( |
| 154 sendto(fd, buffer, num_bytes, 0, |
| 155 &addr.addr, SocketAddress::GetAddrLength(&addr))); |
| 156 ASSERT(EAGAIN == EWOULDBLOCK); |
| 157 if (written_bytes == -1 && errno == EWOULDBLOCK) { |
| 158 // If the would block we need to retry and therefore return 0 as |
| 159 // the number of bytes written. |
| 160 written_bytes = 0; |
| 161 } |
| 162 return written_bytes; |
| 163 } |
| 164 |
| 165 |
123 intptr_t Socket::GetPort(intptr_t fd) { | 166 intptr_t Socket::GetPort(intptr_t fd) { |
124 ASSERT(fd >= 0); | 167 ASSERT(fd >= 0); |
125 RawAddr raw; | 168 RawAddr raw; |
126 socklen_t size = sizeof(raw); | 169 socklen_t size = sizeof(raw); |
127 if (TEMP_FAILURE_RETRY( | 170 if (TEMP_FAILURE_RETRY( |
128 getsockname(fd, | 171 getsockname(fd, |
129 &raw.addr, | 172 &raw.addr, |
130 &size))) { | 173 &size))) { |
131 const int kBufferSize = 1024; | 174 const int kBufferSize = 1024; |
132 char error_message[kBufferSize]; | 175 char error_message[kBufferSize]; |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
250 if (type == SocketAddress::TYPE_IPV4) { | 293 if (type == SocketAddress::TYPE_IPV4) { |
251 result = inet_pton(AF_INET, address, &addr->in.sin_addr); | 294 result = inet_pton(AF_INET, address, &addr->in.sin_addr); |
252 } else { | 295 } else { |
253 ASSERT(type == SocketAddress::TYPE_IPV6); | 296 ASSERT(type == SocketAddress::TYPE_IPV6); |
254 result = inet_pton(AF_INET6, address, &addr->in6.sin6_addr); | 297 result = inet_pton(AF_INET6, address, &addr->in6.sin6_addr); |
255 } | 298 } |
256 return result == 1; | 299 return result == 1; |
257 } | 300 } |
258 | 301 |
259 | 302 |
| 303 intptr_t Socket::CreateBindDatagram( |
| 304 RawAddr* addr, intptr_t port, bool reuseAddress) { |
| 305 intptr_t fd; |
| 306 |
| 307 fd = TEMP_FAILURE_RETRY( |
| 308 socket(addr->addr.sa_family, SOCK_DGRAM, IPPROTO_UDP)); |
| 309 if (fd < 0) return -1; |
| 310 |
| 311 FDUtils::SetCloseOnExec(fd); |
| 312 |
| 313 if (reuseAddress) { |
| 314 int optval = 1; |
| 315 TEMP_FAILURE_RETRY( |
| 316 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))); |
| 317 } |
| 318 |
| 319 SocketAddress::SetAddrPort(addr, port); |
| 320 if (TEMP_FAILURE_RETRY( |
| 321 bind(fd, |
| 322 &addr->addr, |
| 323 SocketAddress::GetAddrLength(addr))) < 0) { |
| 324 TEMP_FAILURE_RETRY(close(fd)); |
| 325 return -1; |
| 326 } |
| 327 |
| 328 Socket::SetNonBlocking(fd); |
| 329 return fd; |
| 330 } |
| 331 |
| 332 |
260 static bool ShouldIncludeIfaAddrs(struct ifaddrs* ifa, int lookup_family) { | 333 static bool ShouldIncludeIfaAddrs(struct ifaddrs* ifa, int lookup_family) { |
261 if (ifa->ifa_addr == NULL) { | 334 if (ifa->ifa_addr == NULL) { |
262 // OpenVPN's virtual device tun0. | 335 // OpenVPN's virtual device tun0. |
263 return false; | 336 return false; |
264 } | 337 } |
265 int family = ifa->ifa_addr->sa_family; | 338 int family = ifa->ifa_addr->sa_family; |
266 if (lookup_family == family) return true; | 339 if (lookup_family == family) return true; |
267 if (lookup_family == AF_UNSPEC && | 340 if (lookup_family == AF_UNSPEC && |
268 (family == AF_INET || family == AF_INET6)) { | 341 (family == AF_INET || family == AF_INET6)) { |
269 return true; | 342 return true; |
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
394 bool Socket::SetNonBlocking(intptr_t fd) { | 467 bool Socket::SetNonBlocking(intptr_t fd) { |
395 return FDUtils::SetNonBlocking(fd); | 468 return FDUtils::SetNonBlocking(fd); |
396 } | 469 } |
397 | 470 |
398 | 471 |
399 bool Socket::SetBlocking(intptr_t fd) { | 472 bool Socket::SetBlocking(intptr_t fd) { |
400 return FDUtils::SetBlocking(fd); | 473 return FDUtils::SetBlocking(fd); |
401 } | 474 } |
402 | 475 |
403 | 476 |
| 477 bool Socket::GetNoDelay(intptr_t fd, bool* enabled) { |
| 478 int on; |
| 479 socklen_t len = sizeof(on); |
| 480 int err = TEMP_FAILURE_RETRY(getsockopt(fd, |
| 481 IPPROTO_TCP, |
| 482 TCP_NODELAY, |
| 483 reinterpret_cast<void *>(&on), |
| 484 &len)); |
| 485 if (err == 0) { |
| 486 *enabled = on == 1; |
| 487 } |
| 488 return err == 0; |
| 489 } |
| 490 |
| 491 |
404 bool Socket::SetNoDelay(intptr_t fd, bool enabled) { | 492 bool Socket::SetNoDelay(intptr_t fd, bool enabled) { |
405 int on = enabled ? 1 : 0; | 493 int on = enabled ? 1 : 0; |
406 return TEMP_FAILURE_RETRY(setsockopt(fd, | 494 return TEMP_FAILURE_RETRY(setsockopt(fd, |
407 IPPROTO_TCP, | 495 IPPROTO_TCP, |
408 TCP_NODELAY, | 496 TCP_NODELAY, |
409 reinterpret_cast<char *>(&on), | 497 reinterpret_cast<char *>(&on), |
410 sizeof(on))) == 0; | 498 sizeof(on))) == 0; |
411 } | 499 } |
412 | 500 |
| 501 |
| 502 bool Socket::GetMulticastLoop(intptr_t fd, intptr_t protocol, bool* enabled) { |
| 503 uint8_t on; |
| 504 socklen_t len = sizeof(on); |
| 505 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; |
| 506 int optname = protocol == SocketAddress::TYPE_IPV4 |
| 507 ? IP_MULTICAST_LOOP : IPV6_MULTICAST_LOOP; |
| 508 if (TEMP_FAILURE_RETRY(getsockopt(fd, |
| 509 level, |
| 510 optname, |
| 511 reinterpret_cast<char *>(&on), |
| 512 &len)) == 0) { |
| 513 *enabled = (on == 1); |
| 514 return true; |
| 515 } |
| 516 return false; |
| 517 } |
| 518 |
| 519 |
| 520 bool Socket::SetMulticastLoop(intptr_t fd, intptr_t protocol, bool enabled) { |
| 521 u_int on = enabled ? 1 : 0; |
| 522 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; |
| 523 int optname = protocol == SocketAddress::TYPE_IPV4 |
| 524 ? IP_MULTICAST_LOOP : IPV6_MULTICAST_LOOP; |
| 525 return TEMP_FAILURE_RETRY(setsockopt(fd, |
| 526 level, |
| 527 optname, |
| 528 reinterpret_cast<char *>(&on), |
| 529 sizeof(on))) == 0; |
| 530 } |
| 531 |
| 532 |
| 533 bool Socket::GetMulticastHops(intptr_t fd, intptr_t protocol, int* value) { |
| 534 uint8_t v; |
| 535 socklen_t len = sizeof(v); |
| 536 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; |
| 537 int optname = protocol == SocketAddress::TYPE_IPV4 |
| 538 ? IP_MULTICAST_TTL : IPV6_MULTICAST_HOPS; |
| 539 if (TEMP_FAILURE_RETRY(getsockopt(fd, |
| 540 level, |
| 541 optname, |
| 542 reinterpret_cast<char *>(&v), |
| 543 &len)) == 0) { |
| 544 *value = v; |
| 545 return true; |
| 546 } |
| 547 return false; |
| 548 } |
| 549 |
| 550 |
| 551 bool Socket::SetMulticastHops(intptr_t fd, intptr_t protocol, int value) { |
| 552 int v = value; |
| 553 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; |
| 554 int optname = protocol == SocketAddress::TYPE_IPV4 |
| 555 ? IP_MULTICAST_TTL : IPV6_MULTICAST_HOPS; |
| 556 return TEMP_FAILURE_RETRY(setsockopt(fd, |
| 557 level, |
| 558 optname, |
| 559 reinterpret_cast<char *>(&v), |
| 560 sizeof(v))) == 0; |
| 561 } |
| 562 |
| 563 |
| 564 bool Socket::GetBroadcast(intptr_t fd, bool* enabled) { |
| 565 int on; |
| 566 socklen_t len = sizeof(on); |
| 567 int err = TEMP_FAILURE_RETRY(getsockopt(fd, |
| 568 SOL_SOCKET, |
| 569 SO_BROADCAST, |
| 570 reinterpret_cast<char *>(&on), |
| 571 &len)); |
| 572 if (err == 0) { |
| 573 *enabled = on == 1; |
| 574 } |
| 575 return err == 0; |
| 576 } |
| 577 |
| 578 |
| 579 bool Socket::SetBroadcast(intptr_t fd, bool enabled) { |
| 580 int on = enabled ? 1 : 0; |
| 581 return TEMP_FAILURE_RETRY(setsockopt(fd, |
| 582 SOL_SOCKET, |
| 583 SO_BROADCAST, |
| 584 reinterpret_cast<char *>(&on), |
| 585 sizeof(on))) == 0; |
| 586 } |
| 587 |
| 588 |
| 589 static bool JoinOrLeaveMulticast(intptr_t fd, |
| 590 RawAddr* addr, |
| 591 RawAddr* interface, |
| 592 int interfaceIndex, |
| 593 bool join) { |
| 594 if (addr->addr.sa_family == AF_INET) { |
| 595 ASSERT(interface->addr.sa_family == AF_INET); |
| 596 struct ip_mreq mreq; |
| 597 memmove(&mreq.imr_multiaddr, |
| 598 &addr->in.sin_addr, |
| 599 SocketAddress::GetAddrLength(addr)); |
| 600 memmove(&mreq.imr_interface, |
| 601 &interface->in.sin_addr, |
| 602 SocketAddress::GetAddrLength(interface)); |
| 603 if (join) { |
| 604 return TEMP_FAILURE_RETRY(setsockopt( |
| 605 fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq))) == 0; |
| 606 } else { |
| 607 return TEMP_FAILURE_RETRY(setsockopt( |
| 608 fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq))) == 0; |
| 609 } |
| 610 } else { |
| 611 ASSERT(addr->addr.sa_family == AF_INET6); |
| 612 struct ipv6_mreq mreq; |
| 613 memmove(&mreq.ipv6mr_multiaddr, |
| 614 &addr->in6.sin6_addr, |
| 615 SocketAddress::GetAddrLength(addr)); |
| 616 mreq.ipv6mr_interface = interfaceIndex; |
| 617 if (join) { |
| 618 return TEMP_FAILURE_RETRY(setsockopt( |
| 619 fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq))) == 0; |
| 620 } else { |
| 621 return TEMP_FAILURE_RETRY(setsockopt( |
| 622 fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq, sizeof(mreq))) == 0; |
| 623 } |
| 624 } |
| 625 } |
| 626 |
| 627 bool Socket::JoinMulticast( |
| 628 intptr_t fd, RawAddr* addr, RawAddr* interface, int interfaceIndex) { |
| 629 return JoinOrLeaveMulticast(fd, addr, interface, interfaceIndex, true); |
| 630 if (addr->addr.sa_family == AF_INET) { |
| 631 ASSERT(interface->addr.sa_family == AF_INET); |
| 632 struct ip_mreq mreq; |
| 633 memmove(&mreq.imr_multiaddr, |
| 634 &addr->in.sin_addr, |
| 635 SocketAddress::GetAddrLength(addr)); |
| 636 memmove(&mreq.imr_interface, |
| 637 &interface->in.sin_addr, |
| 638 SocketAddress::GetAddrLength(interface)); |
| 639 return TEMP_FAILURE_RETRY(setsockopt( |
| 640 fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq))) == 0; |
| 641 } else { |
| 642 ASSERT(addr->addr.sa_family == AF_INET6); |
| 643 ASSERT(interface->addr.sa_family == AF_INET6); |
| 644 struct ipv6_mreq mreq; |
| 645 memmove(&mreq.ipv6mr_multiaddr, |
| 646 &addr->in6.sin6_addr, |
| 647 SocketAddress::GetAddrLength(addr)); |
| 648 mreq.ipv6mr_interface = interfaceIndex; |
| 649 return TEMP_FAILURE_RETRY(setsockopt( |
| 650 fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq))) == 0; |
| 651 } |
| 652 } |
| 653 |
| 654 |
| 655 bool Socket::LeaveMulticast( |
| 656 intptr_t fd, RawAddr* addr, RawAddr* interface, int interfaceIndex) { |
| 657 return JoinOrLeaveMulticast(fd, addr, interface, interfaceIndex, false); |
| 658 } |
| 659 |
413 } // namespace bin | 660 } // namespace bin |
414 } // namespace dart | 661 } // namespace dart |
415 | 662 |
416 #endif // defined(TARGET_OS_MACOS) | 663 #endif // defined(TARGET_OS_MACOS) |
OLD | NEW |