| 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 |
| (...skipping 21 matching lines...) Expand all Loading... |
| 32 INET6_ADDRSTRLEN, | 32 INET6_ADDRSTRLEN, |
| 33 NULL, | 33 NULL, |
| 34 0, | 34 0, |
| 35 NI_NUMERICHOST)) != 0) { | 35 NI_NUMERICHOST)) != 0) { |
| 36 as_string_[0] = 0; | 36 as_string_[0] = 0; |
| 37 } | 37 } |
| 38 memmove(reinterpret_cast<void *>(&addr_), sa, salen); | 38 memmove(reinterpret_cast<void *>(&addr_), sa, salen); |
| 39 } | 39 } |
| 40 | 40 |
| 41 | 41 |
| 42 bool Socket::FormatNumericAddress(RawAddr* addr, char* address, int len) { |
| 43 socklen_t salen = SocketAddress::GetAddrLength(addr); |
| 44 if (TEMP_FAILURE_RETRY(getnameinfo(&addr->addr, |
| 45 salen, |
| 46 address, |
| 47 len, |
| 48 NULL, |
| 49 0, |
| 50 NI_NUMERICHOST)) != 0) { |
| 51 return false; |
| 52 } |
| 53 return true; |
| 54 } |
| 55 |
| 56 |
| 42 bool Socket::Initialize() { | 57 bool Socket::Initialize() { |
| 43 // Nothing to do on Linux. | 58 // Nothing to do on Linux. |
| 44 return true; | 59 return true; |
| 45 } | 60 } |
| 46 | 61 |
| 47 | 62 |
| 48 intptr_t Socket::Create(RawAddr addr) { | 63 intptr_t Socket::Create(RawAddr addr) { |
| 49 intptr_t fd; | 64 intptr_t fd; |
| 50 | 65 |
| 51 fd = TEMP_FAILURE_RETRY(socket(addr.ss.ss_family, SOCK_STREAM, 0)); | 66 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); | 114 ASSERT(EAGAIN == EWOULDBLOCK); |
| 100 if (read_bytes == -1 && errno == EWOULDBLOCK) { | 115 if (read_bytes == -1 && errno == EWOULDBLOCK) { |
| 101 // If the read would block we need to retry and therefore return 0 | 116 // If the read would block we need to retry and therefore return 0 |
| 102 // as the number of bytes written. | 117 // as the number of bytes written. |
| 103 read_bytes = 0; | 118 read_bytes = 0; |
| 104 } | 119 } |
| 105 return read_bytes; | 120 return read_bytes; |
| 106 } | 121 } |
| 107 | 122 |
| 108 | 123 |
| 124 int Socket::RecvFrom(intptr_t fd, void* buffer, intptr_t num_bytes, |
| 125 RawAddr* addr) { |
| 126 ASSERT(fd >= 0); |
| 127 socklen_t addr_len = sizeof(addr->addr); |
| 128 ssize_t read_bytes = |
| 129 recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len); |
| 130 if (read_bytes == -1 && errno == EWOULDBLOCK) { |
| 131 // If the read would block we need to retry and therefore return 0 |
| 132 // as the number of bytes written. |
| 133 read_bytes = 0; |
| 134 } |
| 135 return read_bytes; |
| 136 } |
| 137 |
| 138 |
| 109 int Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) { | 139 int Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) { |
| 110 ASSERT(fd >= 0); | 140 ASSERT(fd >= 0); |
| 111 ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes)); | 141 ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes)); |
| 112 ASSERT(EAGAIN == EWOULDBLOCK); | 142 ASSERT(EAGAIN == EWOULDBLOCK); |
| 113 if (written_bytes == -1 && errno == EWOULDBLOCK) { | 143 if (written_bytes == -1 && errno == EWOULDBLOCK) { |
| 114 // If the would block we need to retry and therefore return 0 as | 144 // If the would block we need to retry and therefore return 0 as |
| 115 // the number of bytes written. | 145 // the number of bytes written. |
| 116 written_bytes = 0; | 146 written_bytes = 0; |
| 117 } | 147 } |
| 118 return written_bytes; | 148 return written_bytes; |
| 119 } | 149 } |
| 120 | 150 |
| 121 | 151 |
| 152 int Socket::SendTo(intptr_t fd, const void* buffer, intptr_t num_bytes, |
| 153 RawAddr addr) { |
| 154 ASSERT(fd >= 0); |
| 155 ssize_t written_bytes = |
| 156 TEMP_FAILURE_RETRY( |
| 157 sendto(fd, buffer, num_bytes, 0, |
| 158 &addr.addr, SocketAddress::GetAddrLength(&addr))); |
| 159 ASSERT(EAGAIN == EWOULDBLOCK); |
| 160 if (written_bytes == -1 && errno == EWOULDBLOCK) { |
| 161 // If the would block we need to retry and therefore return 0 as |
| 162 // the number of bytes written. |
| 163 written_bytes = 0; |
| 164 } |
| 165 return written_bytes; |
| 166 } |
| 167 |
| 168 |
| 122 intptr_t Socket::GetPort(intptr_t fd) { | 169 intptr_t Socket::GetPort(intptr_t fd) { |
| 123 ASSERT(fd >= 0); | 170 ASSERT(fd >= 0); |
| 124 RawAddr raw; | 171 RawAddr raw; |
| 125 socklen_t size = sizeof(raw); | 172 socklen_t size = sizeof(raw); |
| 126 if (TEMP_FAILURE_RETRY( | 173 if (TEMP_FAILURE_RETRY( |
| 127 getsockname(fd, | 174 getsockname(fd, |
| 128 &raw.addr, | 175 &raw.addr, |
| 129 &size))) { | 176 &size))) { |
| 130 const int kBufferSize = 1024; | 177 const int kBufferSize = 1024; |
| 131 char error_buf[kBufferSize]; | 178 char error_buf[kBufferSize]; |
| (...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 249 if (type == SocketAddress::TYPE_IPV4) { | 296 if (type == SocketAddress::TYPE_IPV4) { |
| 250 result = inet_pton(AF_INET, address, &addr->in.sin_addr); | 297 result = inet_pton(AF_INET, address, &addr->in.sin_addr); |
| 251 } else { | 298 } else { |
| 252 ASSERT(type == SocketAddress::TYPE_IPV6); | 299 ASSERT(type == SocketAddress::TYPE_IPV6); |
| 253 result = inet_pton(AF_INET6, address, &addr->in6.sin6_addr); | 300 result = inet_pton(AF_INET6, address, &addr->in6.sin6_addr); |
| 254 } | 301 } |
| 255 return result == 1; | 302 return result == 1; |
| 256 } | 303 } |
| 257 | 304 |
| 258 | 305 |
| 306 intptr_t Socket::CreateBindDatagram(RawAddr* addr, intptr_t port) { |
| 307 intptr_t fd; |
| 308 |
| 309 fd = TEMP_FAILURE_RETRY(socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)); |
| 310 if (fd < 0) return -1; |
| 311 |
| 312 FDUtils::SetCloseOnExec(fd); |
| 313 |
| 314 if (addr != NULL) { |
| 315 SocketAddress::SetAddrPort(addr, port); |
| 316 if (TEMP_FAILURE_RETRY( |
| 317 bind(fd, |
| 318 &addr->addr, |
| 319 SocketAddress::GetAddrLength(addr))) < 0) { |
| 320 TEMP_FAILURE_RETRY(close(fd)); |
| 321 return -1; |
| 322 } |
| 323 } |
| 324 |
| 325 Socket::SetNonBlocking(fd); |
| 326 return fd; |
| 327 } |
| 328 |
| 329 |
| 259 static bool ShouldIncludeIfaAddrs(struct ifaddrs* ifa, int lookup_family) { | 330 static bool ShouldIncludeIfaAddrs(struct ifaddrs* ifa, int lookup_family) { |
| 260 if (ifa->ifa_addr == NULL) { | 331 if (ifa->ifa_addr == NULL) { |
| 261 // OpenVPN's virtual device tun0. | 332 // OpenVPN's virtual device tun0. |
| 262 return false; | 333 return false; |
| 263 } | 334 } |
| 264 int family = ifa->ifa_addr->sa_family; | 335 int family = ifa->ifa_addr->sa_family; |
| 265 if (lookup_family == family) return true; | 336 if (lookup_family == family) return true; |
| 266 if (lookup_family == AF_UNSPEC && | 337 if (lookup_family == AF_UNSPEC && |
| 267 (family == AF_INET || family == AF_INET6)) { | 338 (family == AF_INET || family == AF_INET6)) { |
| 268 return true; | 339 return true; |
| (...skipping 133 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 402 bool Socket::SetNonBlocking(intptr_t fd) { | 473 bool Socket::SetNonBlocking(intptr_t fd) { |
| 403 return FDUtils::SetNonBlocking(fd); | 474 return FDUtils::SetNonBlocking(fd); |
| 404 } | 475 } |
| 405 | 476 |
| 406 | 477 |
| 407 bool Socket::SetBlocking(intptr_t fd) { | 478 bool Socket::SetBlocking(intptr_t fd) { |
| 408 return FDUtils::SetBlocking(fd); | 479 return FDUtils::SetBlocking(fd); |
| 409 } | 480 } |
| 410 | 481 |
| 411 | 482 |
| 483 bool Socket::GetNoDelay(intptr_t fd, bool* enabled) { |
| 484 int on; |
| 485 socklen_t len = sizeof(on); |
| 486 int err = TEMP_FAILURE_RETRY(getsockopt(fd, |
| 487 IPPROTO_TCP, |
| 488 TCP_NODELAY, |
| 489 reinterpret_cast<void *>(&on), |
| 490 &len)); |
| 491 if (err == 0) { |
| 492 *enabled = on == 1; |
| 493 } |
| 494 return err == 0; |
| 495 } |
| 496 |
| 497 |
| 412 bool Socket::SetNoDelay(intptr_t fd, bool enabled) { | 498 bool Socket::SetNoDelay(intptr_t fd, bool enabled) { |
| 413 int on = enabled ? 1 : 0; | 499 int on = enabled ? 1 : 0; |
| 414 return TEMP_FAILURE_RETRY(setsockopt(fd, | 500 return TEMP_FAILURE_RETRY(setsockopt(fd, |
| 415 IPPROTO_TCP, | 501 IPPROTO_TCP, |
| 416 TCP_NODELAY, | 502 TCP_NODELAY, |
| 417 reinterpret_cast<char *>(&on), | 503 reinterpret_cast<char *>(&on), |
| 418 sizeof(on))) == 0; | 504 sizeof(on))) == 0; |
| 419 } | 505 } |
| 420 | 506 |
| 507 |
| 508 bool Socket::GetMulticastLoop(intptr_t fd, bool* enabled) { |
| 509 uint8_t on; |
| 510 socklen_t len = sizeof(on); |
| 511 int err = TEMP_FAILURE_RETRY(getsockopt(fd, |
| 512 IPPROTO_IP, |
| 513 IP_MULTICAST_LOOP, |
| 514 reinterpret_cast<char *>(&on), |
| 515 &len)); |
| 516 if (err == 0) { |
| 517 *enabled = on == 1; |
| 518 } |
| 519 return err == 0; |
| 520 } |
| 521 |
| 522 |
| 523 bool Socket::SetMulticastLoop(intptr_t fd, bool enabled) { |
| 524 uint8_t on = enabled ? 1 : 0; |
| 525 return TEMP_FAILURE_RETRY(setsockopt(fd, |
| 526 IPPROTO_IP, |
| 527 IP_MULTICAST_LOOP, |
| 528 reinterpret_cast<char *>(&on), |
| 529 sizeof(on))) == 0; |
| 530 } |
| 531 |
| 532 |
| 533 bool Socket::GetMulticastTTL(intptr_t fd, int* value) { |
| 534 uint8_t v; |
| 535 socklen_t len = sizeof(v); |
| 536 int err = TEMP_FAILURE_RETRY(getsockopt(fd, |
| 537 IPPROTO_IP, |
| 538 IP_MULTICAST_TTL, |
| 539 reinterpret_cast<char *>(&v), |
| 540 &len)); |
| 541 if (err == 0) { |
| 542 *value = v; |
| 543 } |
| 544 return err == 0; |
| 545 } |
| 546 |
| 547 |
| 548 bool Socket::SetMulticastTTL(intptr_t fd, int value) { |
| 549 uint8_t v = value; |
| 550 return TEMP_FAILURE_RETRY(setsockopt(fd, |
| 551 IPPROTO_IP, |
| 552 IP_MULTICAST_TTL, |
| 553 reinterpret_cast<char *>(&v), |
| 554 sizeof(v))) == 0; |
| 555 } |
| 556 |
| 557 |
| 558 bool Socket::GetBroadcast(intptr_t fd, bool* enabled) { |
| 559 int on; |
| 560 socklen_t len = sizeof(on); |
| 561 int err = TEMP_FAILURE_RETRY(getsockopt(fd, |
| 562 SOL_SOCKET, |
| 563 SO_BROADCAST, |
| 564 reinterpret_cast<char *>(&on), |
| 565 &len)); |
| 566 if (err == 0) { |
| 567 *enabled = on == 1; |
| 568 } |
| 569 return err == 0; |
| 570 } |
| 571 |
| 572 |
| 573 bool Socket::SetBroadcast(intptr_t fd, bool enabled) { |
| 574 int on = enabled ? 1 : 0; |
| 575 return TEMP_FAILURE_RETRY(setsockopt(fd, |
| 576 SOL_SOCKET, |
| 577 SO_BROADCAST, |
| 578 reinterpret_cast<char *>(&on), |
| 579 sizeof(on))) == 0; |
| 580 } |
| 581 |
| 582 |
| 583 bool Socket::JoinMulticast(intptr_t fd, RawAddr* addr, int interfaceIndex) { |
| 584 struct group_req mreq; |
| 585 mreq.gr_interface = interfaceIndex; |
| 586 memmove(&mreq.gr_group, &addr->ss, SocketAddress::GetAddrLength(addr)); |
| 587 return TEMP_FAILURE_RETRY(setsockopt( |
| 588 fd, IPPROTO_IP, MCAST_JOIN_GROUP, &mreq, sizeof(mreq))) == 0; |
| 589 } |
| 590 |
| 591 |
| 592 bool Socket::LeaveMulticast(intptr_t fd, RawAddr* addr, int interfaceIndex) { |
| 593 struct group_req mreq; |
| 594 mreq.gr_interface = interfaceIndex; |
| 595 memmove(&mreq.gr_group, &addr->ss, SocketAddress::GetAddrLength(addr)); |
| 596 return TEMP_FAILURE_RETRY(setsockopt( |
| 597 fd, IPPROTO_IP, MCAST_LEAVE_GROUP, &mreq, sizeof(mreq))) == 0; |
| 598 } |
| 599 |
| 421 } // namespace bin | 600 } // namespace bin |
| 422 } // namespace dart | 601 } // namespace dart |
| 423 | 602 |
| 424 #endif // defined(TARGET_OS_LINUX) | 603 #endif // defined(TARGET_OS_LINUX) |
| OLD | NEW |