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

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

Issue 85993002: Add UDP support to dart:io (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Fix Windows build 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
« no previous file with comments | « runtime/bin/socket_linux.cc ('k') | runtime/bin/socket_patch.dart » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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_MACOS) 6 #if defined(TARGET_OS_MACOS)
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 <net/if.h> // NOLINT
15 #include <netinet/tcp.h> // NOLINT 15 #include <netinet/tcp.h> // NOLINT
16 #include <ifaddrs.h> // NOLINT 16 #include <ifaddrs.h> // NOLINT
17 17
18 #include "bin/fdutils.h" 18 #include "bin/fdutils.h"
19 #include "bin/file.h" 19 #include "bin/file.h"
20 #include "bin/log.h" 20 #include "bin/log.h"
21 #include "bin/socket.h" 21 #include "bin/socket.h"
22 22
23 23
24 namespace dart { 24 namespace dart {
25 namespace bin { 25 namespace bin {
26 26
27 SocketAddress::SocketAddress(struct sockaddr* sa) { 27 SocketAddress::SocketAddress(struct sockaddr* sa) {
28 ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN); 28 ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
29 socklen_t salen = GetAddrLength(reinterpret_cast<RawAddr*>(sa)); 29 if (!Socket::FormatNumericAddress(
30 if (TEMP_FAILURE_RETRY(getnameinfo(sa, 30 reinterpret_cast<RawAddr*>(sa), as_string_, INET6_ADDRSTRLEN)) {
31 salen,
32 as_string_,
33 INET6_ADDRSTRLEN,
34 NULL,
35 0,
36 NI_NUMERICHOST)) != 0) {
37 as_string_[0] = 0; 31 as_string_[0] = 0;
38 } 32 }
33 socklen_t salen = GetAddrLength(reinterpret_cast<RawAddr*>(sa));
39 memmove(reinterpret_cast<void *>(&addr_), sa, salen); 34 memmove(reinterpret_cast<void *>(&addr_), sa, salen);
40 } 35 }
41 36
42 37
38 bool Socket::FormatNumericAddress(RawAddr* addr, char* address, int len) {
39 socklen_t salen = SocketAddress::GetAddrLength(addr);
40 if (TEMP_FAILURE_RETRY(getnameinfo(&addr->addr,
41 salen,
42 address,
43 len,
44 NULL,
45 0,
46 NI_NUMERICHOST)) != 0) {
47 return false;
48 }
49 return true;
50 }
51
52
43 bool Socket::Initialize() { 53 bool Socket::Initialize() {
44 // Nothing to do on Mac OS. 54 // Nothing to do on Mac OS.
45 return true; 55 return true;
46 } 56 }
47 57
48 58
49 intptr_t Socket::Create(RawAddr addr) { 59 intptr_t Socket::Create(RawAddr addr) {
50 intptr_t fd; 60 intptr_t fd;
51 61
52 fd = TEMP_FAILURE_RETRY(socket(addr.ss.ss_family, SOCK_STREAM, 0)); 62 fd = TEMP_FAILURE_RETRY(socket(addr.ss.ss_family, SOCK_STREAM, 0));
(...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after
100 ASSERT(EAGAIN == EWOULDBLOCK); 110 ASSERT(EAGAIN == EWOULDBLOCK);
101 if (read_bytes == -1 && errno == EWOULDBLOCK) { 111 if (read_bytes == -1 && errno == EWOULDBLOCK) {
102 // If the read would block we need to retry and therefore return 0 112 // If the read would block we need to retry and therefore return 0
103 // as the number of bytes written. 113 // as the number of bytes written.
104 read_bytes = 0; 114 read_bytes = 0;
105 } 115 }
106 return read_bytes; 116 return read_bytes;
107 } 117 }
108 118
109 119
120 int Socket::RecvFrom(intptr_t fd, void* buffer, intptr_t num_bytes,
121 RawAddr* addr) {
122 ASSERT(fd >= 0);
123 socklen_t addr_len = sizeof(addr->ss);
124 ssize_t read_bytes =
125 TEMP_FAILURE_RETRY(
126 recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len));
127 if (read_bytes == -1 && errno == EWOULDBLOCK) {
128 // If the read would block we need to retry and therefore return 0
129 // as the number of bytes written.
130 read_bytes = 0;
131 }
132 return read_bytes;
133 }
134
135
110 int Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) { 136 int Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) {
111 ASSERT(fd >= 0); 137 ASSERT(fd >= 0);
112 ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes)); 138 ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes));
113 ASSERT(EAGAIN == EWOULDBLOCK); 139 ASSERT(EAGAIN == EWOULDBLOCK);
114 if (written_bytes == -1 && errno == EWOULDBLOCK) { 140 if (written_bytes == -1 && errno == EWOULDBLOCK) {
115 // If the would block we need to retry and therefore return 0 as 141 // If the would block we need to retry and therefore return 0 as
116 // the number of bytes written. 142 // the number of bytes written.
117 written_bytes = 0; 143 written_bytes = 0;
118 } 144 }
119 return written_bytes; 145 return written_bytes;
120 } 146 }
121 147
122 148
149 int Socket::SendTo(intptr_t fd, const void* buffer, intptr_t num_bytes,
150 RawAddr addr) {
151 ASSERT(fd >= 0);
152 ssize_t written_bytes =
153 TEMP_FAILURE_RETRY(
154 sendto(fd, buffer, num_bytes, 0,
155 &addr.addr, SocketAddress::GetAddrLength(&addr)));
156 ASSERT(EAGAIN == EWOULDBLOCK);
157 if (written_bytes == -1 && errno == EWOULDBLOCK) {
158 // If the would block we need to retry and therefore return 0 as
159 // the number of bytes written.
160 written_bytes = 0;
161 }
162 return written_bytes;
163 }
164
165
123 intptr_t Socket::GetPort(intptr_t fd) { 166 intptr_t Socket::GetPort(intptr_t fd) {
124 ASSERT(fd >= 0); 167 ASSERT(fd >= 0);
125 RawAddr raw; 168 RawAddr raw;
126 socklen_t size = sizeof(raw); 169 socklen_t size = sizeof(raw);
127 if (TEMP_FAILURE_RETRY( 170 if (TEMP_FAILURE_RETRY(
128 getsockname(fd, 171 getsockname(fd,
129 &raw.addr, 172 &raw.addr,
130 &size))) { 173 &size))) {
131 const int kBufferSize = 1024; 174 const int kBufferSize = 1024;
132 char error_message[kBufferSize]; 175 char error_message[kBufferSize];
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after
250 if (type == SocketAddress::TYPE_IPV4) { 293 if (type == SocketAddress::TYPE_IPV4) {
251 result = inet_pton(AF_INET, address, &addr->in.sin_addr); 294 result = inet_pton(AF_INET, address, &addr->in.sin_addr);
252 } else { 295 } else {
253 ASSERT(type == SocketAddress::TYPE_IPV6); 296 ASSERT(type == SocketAddress::TYPE_IPV6);
254 result = inet_pton(AF_INET6, address, &addr->in6.sin6_addr); 297 result = inet_pton(AF_INET6, address, &addr->in6.sin6_addr);
255 } 298 }
256 return result == 1; 299 return result == 1;
257 } 300 }
258 301
259 302
303 intptr_t Socket::CreateBindDatagram(
304 RawAddr* addr, intptr_t port, bool reuseAddress) {
305 intptr_t fd;
306
307 fd = TEMP_FAILURE_RETRY(
308 socket(addr->addr.sa_family, SOCK_DGRAM, IPPROTO_UDP));
309 if (fd < 0) return -1;
310
311 FDUtils::SetCloseOnExec(fd);
312
313 if (reuseAddress) {
314 int optval = 1;
315 TEMP_FAILURE_RETRY(
316 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)));
317 }
318
319 SocketAddress::SetAddrPort(addr, port);
320 if (TEMP_FAILURE_RETRY(
321 bind(fd,
322 &addr->addr,
323 SocketAddress::GetAddrLength(addr))) < 0) {
324 TEMP_FAILURE_RETRY(close(fd));
325 return -1;
326 }
327
328 Socket::SetNonBlocking(fd);
329 return fd;
330 }
331
332
260 static bool ShouldIncludeIfaAddrs(struct ifaddrs* ifa, int lookup_family) { 333 static bool ShouldIncludeIfaAddrs(struct ifaddrs* ifa, int lookup_family) {
261 if (ifa->ifa_addr == NULL) { 334 if (ifa->ifa_addr == NULL) {
262 // OpenVPN's virtual device tun0. 335 // OpenVPN's virtual device tun0.
263 return false; 336 return false;
264 } 337 }
265 int family = ifa->ifa_addr->sa_family; 338 int family = ifa->ifa_addr->sa_family;
266 if (lookup_family == family) return true; 339 if (lookup_family == family) return true;
267 if (lookup_family == AF_UNSPEC && 340 if (lookup_family == AF_UNSPEC &&
268 (family == AF_INET || family == AF_INET6)) { 341 (family == AF_INET || family == AF_INET6)) {
269 return true; 342 return true;
(...skipping 124 matching lines...) Expand 10 before | Expand all | Expand 10 after
394 bool Socket::SetNonBlocking(intptr_t fd) { 467 bool Socket::SetNonBlocking(intptr_t fd) {
395 return FDUtils::SetNonBlocking(fd); 468 return FDUtils::SetNonBlocking(fd);
396 } 469 }
397 470
398 471
399 bool Socket::SetBlocking(intptr_t fd) { 472 bool Socket::SetBlocking(intptr_t fd) {
400 return FDUtils::SetBlocking(fd); 473 return FDUtils::SetBlocking(fd);
401 } 474 }
402 475
403 476
477 bool Socket::GetNoDelay(intptr_t fd, bool* enabled) {
478 int on;
479 socklen_t len = sizeof(on);
480 int err = TEMP_FAILURE_RETRY(getsockopt(fd,
481 IPPROTO_TCP,
482 TCP_NODELAY,
483 reinterpret_cast<void *>(&on),
484 &len));
485 if (err == 0) {
486 *enabled = on == 1;
487 }
488 return err == 0;
489 }
490
491
404 bool Socket::SetNoDelay(intptr_t fd, bool enabled) { 492 bool Socket::SetNoDelay(intptr_t fd, bool enabled) {
405 int on = enabled ? 1 : 0; 493 int on = enabled ? 1 : 0;
406 return TEMP_FAILURE_RETRY(setsockopt(fd, 494 return TEMP_FAILURE_RETRY(setsockopt(fd,
407 IPPROTO_TCP, 495 IPPROTO_TCP,
408 TCP_NODELAY, 496 TCP_NODELAY,
409 reinterpret_cast<char *>(&on), 497 reinterpret_cast<char *>(&on),
410 sizeof(on))) == 0; 498 sizeof(on))) == 0;
411 } 499 }
412 500
501
502 bool Socket::GetMulticastLoop(intptr_t fd, intptr_t protocol, bool* enabled) {
503 uint8_t on;
504 socklen_t len = sizeof(on);
505 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
506 int optname = protocol == SocketAddress::TYPE_IPV4
507 ? IP_MULTICAST_LOOP : IPV6_MULTICAST_LOOP;
508 if (TEMP_FAILURE_RETRY(getsockopt(fd,
509 level,
510 optname,
511 reinterpret_cast<char *>(&on),
512 &len)) == 0) {
513 *enabled = (on == 1);
514 return true;
515 }
516 return false;
517 }
518
519
520 bool Socket::SetMulticastLoop(intptr_t fd, intptr_t protocol, bool enabled) {
521 u_int on = enabled ? 1 : 0;
522 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
523 int optname = protocol == SocketAddress::TYPE_IPV4
524 ? IP_MULTICAST_LOOP : IPV6_MULTICAST_LOOP;
525 return TEMP_FAILURE_RETRY(setsockopt(fd,
526 level,
527 optname,
528 reinterpret_cast<char *>(&on),
529 sizeof(on))) == 0;
530 }
531
532
533 bool Socket::GetMulticastHops(intptr_t fd, intptr_t protocol, int* value) {
534 uint8_t v;
535 socklen_t len = sizeof(v);
536 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
537 int optname = protocol == SocketAddress::TYPE_IPV4
538 ? IP_MULTICAST_TTL : IPV6_MULTICAST_HOPS;
539 if (TEMP_FAILURE_RETRY(getsockopt(fd,
540 level,
541 optname,
542 reinterpret_cast<char *>(&v),
543 &len)) == 0) {
544 *value = v;
545 return true;
546 }
547 return false;
548 }
549
550
551 bool Socket::SetMulticastHops(intptr_t fd, intptr_t protocol, int value) {
552 int v = value;
553 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
554 int optname = protocol == SocketAddress::TYPE_IPV4
555 ? IP_MULTICAST_TTL : IPV6_MULTICAST_HOPS;
556 return TEMP_FAILURE_RETRY(setsockopt(fd,
557 level,
558 optname,
559 reinterpret_cast<char *>(&v),
560 sizeof(v))) == 0;
561 }
562
563
564 bool Socket::GetBroadcast(intptr_t fd, bool* enabled) {
565 int on;
566 socklen_t len = sizeof(on);
567 int err = TEMP_FAILURE_RETRY(getsockopt(fd,
568 SOL_SOCKET,
569 SO_BROADCAST,
570 reinterpret_cast<char *>(&on),
571 &len));
572 if (err == 0) {
573 *enabled = on == 1;
574 }
575 return err == 0;
576 }
577
578
579 bool Socket::SetBroadcast(intptr_t fd, bool enabled) {
580 int on = enabled ? 1 : 0;
581 return TEMP_FAILURE_RETRY(setsockopt(fd,
582 SOL_SOCKET,
583 SO_BROADCAST,
584 reinterpret_cast<char *>(&on),
585 sizeof(on))) == 0;
586 }
587
588
589 static bool JoinOrLeaveMulticast(intptr_t fd,
590 RawAddr* addr,
591 RawAddr* interface,
592 int interfaceIndex,
593 bool join) {
594 if (addr->addr.sa_family == AF_INET) {
595 ASSERT(interface->addr.sa_family == AF_INET);
596 struct ip_mreq mreq;
597 memmove(&mreq.imr_multiaddr,
598 &addr->in.sin_addr,
599 SocketAddress::GetAddrLength(addr));
600 memmove(&mreq.imr_interface,
601 &interface->in.sin_addr,
602 SocketAddress::GetAddrLength(interface));
603 if (join) {
604 return TEMP_FAILURE_RETRY(setsockopt(
605 fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq))) == 0;
606 } else {
607 return TEMP_FAILURE_RETRY(setsockopt(
608 fd, IPPROTO_IP, IP_DROP_MEMBERSHIP, &mreq, sizeof(mreq))) == 0;
609 }
610 } else {
611 ASSERT(addr->addr.sa_family == AF_INET6);
612 struct ipv6_mreq mreq;
613 memmove(&mreq.ipv6mr_multiaddr,
614 &addr->in6.sin6_addr,
615 SocketAddress::GetAddrLength(addr));
616 mreq.ipv6mr_interface = interfaceIndex;
617 if (join) {
618 return TEMP_FAILURE_RETRY(setsockopt(
619 fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq))) == 0;
620 } else {
621 return TEMP_FAILURE_RETRY(setsockopt(
622 fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP, &mreq, sizeof(mreq))) == 0;
623 }
624 }
625 }
626
627 bool Socket::JoinMulticast(
628 intptr_t fd, RawAddr* addr, RawAddr* interface, int interfaceIndex) {
629 return JoinOrLeaveMulticast(fd, addr, interface, interfaceIndex, true);
630 if (addr->addr.sa_family == AF_INET) {
631 ASSERT(interface->addr.sa_family == AF_INET);
632 struct ip_mreq mreq;
633 memmove(&mreq.imr_multiaddr,
634 &addr->in.sin_addr,
635 SocketAddress::GetAddrLength(addr));
636 memmove(&mreq.imr_interface,
637 &interface->in.sin_addr,
638 SocketAddress::GetAddrLength(interface));
639 return TEMP_FAILURE_RETRY(setsockopt(
640 fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq))) == 0;
641 } else {
642 ASSERT(addr->addr.sa_family == AF_INET6);
643 ASSERT(interface->addr.sa_family == AF_INET6);
644 struct ipv6_mreq mreq;
645 memmove(&mreq.ipv6mr_multiaddr,
646 &addr->in6.sin6_addr,
647 SocketAddress::GetAddrLength(addr));
648 mreq.ipv6mr_interface = interfaceIndex;
649 return TEMP_FAILURE_RETRY(setsockopt(
650 fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mreq, sizeof(mreq))) == 0;
651 }
652 }
653
654
655 bool Socket::LeaveMulticast(
656 intptr_t fd, RawAddr* addr, RawAddr* interface, int interfaceIndex) {
657 return JoinOrLeaveMulticast(fd, addr, interface, interfaceIndex, false);
658 }
659
413 } // namespace bin 660 } // namespace bin
414 } // namespace dart 661 } // namespace dart
415 662
416 #endif // defined(TARGET_OS_MACOS) 663 #endif // defined(TARGET_OS_MACOS)
OLDNEW
« no previous file with comments | « runtime/bin/socket_linux.cc ('k') | runtime/bin/socket_patch.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698