Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(63)

Side by Side Diff: runtime/bin/socket_linux.cc

Issue 85993002: Add UDP support to dart:io (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Addressed first round of comments Created 7 years ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch | Annotate | Revision Log
OLDNEW
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
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
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
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)
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698