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