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 |