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 |