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

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

Issue 2797993005: Re-land socket refactor with fixes for Windows. (Closed)
Patch Set: Rebased + reverted original revert Created 3 years, 8 months 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
« no previous file with comments | « runtime/bin/socket_macos.h ('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 #if !defined(DART_IO_DISABLED) 5 #if !defined(DART_IO_DISABLED)
6 6
7 #include "platform/globals.h" 7 #include "platform/globals.h"
8 #if defined(HOST_OS_MACOS) 8 #if defined(HOST_OS_MACOS)
9 9
10 #include "bin/socket.h"
11 #include "bin/socket_macos.h"
12
13 #include <errno.h> // NOLINT 10 #include <errno.h> // NOLINT
14 #include <ifaddrs.h> // NOLINT 11 #include <ifaddrs.h> // NOLINT
15 #include <net/if.h> // NOLINT 12 #include <net/if.h> // NOLINT
16 #include <netinet/tcp.h> // NOLINT 13 #include <netinet/tcp.h> // NOLINT
17 #include <stdio.h> // NOLINT 14 #include <stdio.h> // NOLINT
18 #include <stdlib.h> // NOLINT 15 #include <stdlib.h> // NOLINT
19 #include <string.h> // NOLINT 16 #include <string.h> // NOLINT
20 #include <sys/stat.h> // NOLINT 17 #include <sys/stat.h> // NOLINT
21 #include <unistd.h> // NOLINT 18 #include <unistd.h> // NOLINT
22 19
23 #include "bin/fdutils.h" 20 #include "bin/fdutils.h"
24 #include "bin/file.h" 21 #include "bin/file.h"
22 #include "bin/socket.h"
23 #include "bin/socket_base_macos.h"
25 #include "platform/signal_blocker.h" 24 #include "platform/signal_blocker.h"
26 25
27 namespace dart { 26 namespace dart {
28 namespace bin { 27 namespace bin {
29 28
30 SocketAddress::SocketAddress(struct sockaddr* sa) {
31 ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
32 if (!Socket::FormatNumericAddress(*reinterpret_cast<RawAddr*>(sa), as_string_,
33 INET6_ADDRSTRLEN)) {
34 as_string_[0] = 0;
35 }
36 socklen_t salen = GetAddrLength(*reinterpret_cast<RawAddr*>(sa));
37 memmove(reinterpret_cast<void*>(&addr_), sa, salen);
38 }
39
40
41 bool Socket::FormatNumericAddress(const RawAddr& addr, char* address, int len) {
42 socklen_t salen = SocketAddress::GetAddrLength(addr);
43 return (NO_RETRY_EXPECTED(getnameinfo(&addr.addr, salen, address, len, NULL,
44 0, NI_NUMERICHOST)) == 0);
45 }
46
47
48 Socket::Socket(intptr_t fd) 29 Socket::Socket(intptr_t fd)
49 : ReferenceCounted(), fd_(fd), port_(ILLEGAL_PORT) {} 30 : ReferenceCounted(), fd_(fd), port_(ILLEGAL_PORT) {}
50 31
51 32
52 void Socket::SetClosedFd() { 33 void Socket::SetClosedFd() {
53 fd_ = kClosedFd; 34 fd_ = kClosedFd;
54 } 35 }
55 36
56 37
57 bool Socket::Initialize() {
58 // Nothing to do on Mac OS.
59 return true;
60 }
61
62
63 static intptr_t Create(const RawAddr& addr) { 38 static intptr_t Create(const RawAddr& addr) {
64 intptr_t fd; 39 intptr_t fd;
65 fd = NO_RETRY_EXPECTED(socket(addr.ss.ss_family, SOCK_STREAM, 0)); 40 fd = NO_RETRY_EXPECTED(socket(addr.ss.ss_family, SOCK_STREAM, 0));
66 if (fd < 0) { 41 if (fd < 0) {
67 return -1; 42 return -1;
68 } 43 }
69 if (!FDUtils::SetCloseOnExec(fd)) { 44 if (!FDUtils::SetCloseOnExec(fd)) {
70 FDUtils::SaveErrorAndClose(fd); 45 FDUtils::SaveErrorAndClose(fd);
71 return -1; 46 return -1;
72 } 47 }
(...skipping 37 matching lines...) Expand 10 before | Expand all | Expand 10 after
110 bind(fd, &source_addr.addr, SocketAddress::GetAddrLength(source_addr))); 85 bind(fd, &source_addr.addr, SocketAddress::GetAddrLength(source_addr)));
111 if ((result != 0) && (errno != EINPROGRESS)) { 86 if ((result != 0) && (errno != EINPROGRESS)) {
112 FDUtils::SaveErrorAndClose(fd); 87 FDUtils::SaveErrorAndClose(fd);
113 return -1; 88 return -1;
114 } 89 }
115 90
116 return Connect(fd, addr); 91 return Connect(fd, addr);
117 } 92 }
118 93
119 94
120 bool Socket::IsBindError(intptr_t error_number) {
121 return error_number == EADDRINUSE || error_number == EADDRNOTAVAIL ||
122 error_number == EINVAL;
123 }
124
125
126 intptr_t Socket::Available(intptr_t fd) {
127 return FDUtils::AvailableBytes(fd);
128 }
129
130
131 intptr_t Socket::Read(intptr_t fd, void* buffer, intptr_t num_bytes) {
132 ASSERT(fd >= 0);
133 ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, buffer, num_bytes));
134 ASSERT(EAGAIN == EWOULDBLOCK);
135 if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
136 // If the read would block we need to retry and therefore return 0
137 // as the number of bytes written.
138 read_bytes = 0;
139 }
140 return read_bytes;
141 }
142
143
144 intptr_t Socket::RecvFrom(intptr_t fd,
145 void* buffer,
146 intptr_t num_bytes,
147 RawAddr* addr) {
148 ASSERT(fd >= 0);
149 socklen_t addr_len = sizeof(addr->ss);
150 ssize_t read_bytes = TEMP_FAILURE_RETRY(
151 recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len));
152 if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
153 // If the read would block we need to retry and therefore return 0
154 // as the number of bytes written.
155 read_bytes = 0;
156 }
157 return read_bytes;
158 }
159
160
161 intptr_t Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) {
162 ASSERT(fd >= 0);
163 ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes));
164 ASSERT(EAGAIN == EWOULDBLOCK);
165 if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
166 // If the would block we need to retry and therefore return 0 as
167 // the number of bytes written.
168 written_bytes = 0;
169 }
170 return written_bytes;
171 }
172
173
174 intptr_t Socket::SendTo(intptr_t fd,
175 const void* buffer,
176 intptr_t num_bytes,
177 const RawAddr& addr) {
178 ASSERT(fd >= 0);
179 ssize_t written_bytes =
180 TEMP_FAILURE_RETRY(sendto(fd, buffer, num_bytes, 0, &addr.addr,
181 SocketAddress::GetAddrLength(addr)));
182 ASSERT(EAGAIN == EWOULDBLOCK);
183 if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
184 // If the would block we need to retry and therefore return 0 as
185 // the number of bytes written.
186 written_bytes = 0;
187 }
188 return written_bytes;
189 }
190
191
192 intptr_t Socket::GetPort(intptr_t fd) {
193 ASSERT(fd >= 0);
194 RawAddr raw;
195 socklen_t size = sizeof(raw);
196 if (NO_RETRY_EXPECTED(getsockname(fd, &raw.addr, &size))) {
197 return 0;
198 }
199 return SocketAddress::GetAddrPort(raw);
200 }
201
202
203 SocketAddress* Socket::GetRemotePeer(intptr_t fd, intptr_t* port) {
204 ASSERT(fd >= 0);
205 RawAddr raw;
206 socklen_t size = sizeof(raw);
207 if (NO_RETRY_EXPECTED(getpeername(fd, &raw.addr, &size))) {
208 return NULL;
209 }
210 *port = SocketAddress::GetAddrPort(raw);
211 return new SocketAddress(&raw.addr);
212 }
213
214
215 void Socket::GetError(intptr_t fd, OSError* os_error) {
216 int len = sizeof(errno);
217 getsockopt(fd, SOL_SOCKET, SO_ERROR, &errno,
218 reinterpret_cast<socklen_t*>(&len));
219 os_error->SetCodeAndMessage(OSError::kSystem, errno);
220 }
221
222
223 int Socket::GetType(intptr_t fd) {
224 struct stat buf;
225 int result = fstat(fd, &buf);
226 if (result == -1) {
227 return -1;
228 }
229 if (S_ISCHR(buf.st_mode)) {
230 return File::kTerminal;
231 }
232 if (S_ISFIFO(buf.st_mode)) {
233 return File::kPipe;
234 }
235 if (S_ISREG(buf.st_mode)) {
236 return File::kFile;
237 }
238 return File::kOther;
239 }
240
241
242 intptr_t Socket::GetStdioHandle(intptr_t num) {
243 return num;
244 }
245
246
247 AddressList<SocketAddress>* Socket::LookupAddress(const char* host,
248 int type,
249 OSError** os_error) {
250 // Perform a name lookup for a host name.
251 struct addrinfo hints;
252 memset(&hints, 0, sizeof(hints));
253 hints.ai_family = SocketAddress::FromType(type);
254 hints.ai_socktype = SOCK_STREAM;
255 hints.ai_flags = 0;
256 hints.ai_protocol = IPPROTO_TCP;
257 struct addrinfo* info = NULL;
258 int status = getaddrinfo(host, 0, &hints, &info);
259 if (status != 0) {
260 ASSERT(*os_error == NULL);
261 *os_error =
262 new OSError(status, gai_strerror(status), OSError::kGetAddressInfo);
263 return NULL;
264 }
265 intptr_t count = 0;
266 for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
267 if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
268 count++;
269 }
270 }
271 intptr_t i = 0;
272 AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count);
273 for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
274 if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
275 addresses->SetAt(i, new SocketAddress(c->ai_addr));
276 i++;
277 }
278 }
279 freeaddrinfo(info);
280 return addresses;
281 }
282
283
284 bool Socket::ReverseLookup(const RawAddr& addr,
285 char* host,
286 intptr_t host_len,
287 OSError** os_error) {
288 ASSERT(host_len >= NI_MAXHOST);
289 int status = NO_RETRY_EXPECTED(
290 getnameinfo(&addr.addr, SocketAddress::GetAddrLength(addr), host,
291 host_len, NULL, 0, NI_NAMEREQD));
292 if (status != 0) {
293 ASSERT(*os_error == NULL);
294 *os_error =
295 new OSError(status, gai_strerror(status), OSError::kGetAddressInfo);
296 return false;
297 }
298 return true;
299 }
300
301
302 bool Socket::ParseAddress(int type, const char* address, RawAddr* addr) {
303 int result;
304 if (type == SocketAddress::TYPE_IPV4) {
305 result = inet_pton(AF_INET, address, &addr->in.sin_addr);
306 } else {
307 ASSERT(type == SocketAddress::TYPE_IPV6);
308 result = inet_pton(AF_INET6, address, &addr->in6.sin6_addr);
309 }
310 return (result == 1);
311 }
312
313
314 intptr_t Socket::CreateBindDatagram(const RawAddr& addr, bool reuseAddress) { 95 intptr_t Socket::CreateBindDatagram(const RawAddr& addr, bool reuseAddress) {
315 intptr_t fd; 96 intptr_t fd;
316 97
317 fd = NO_RETRY_EXPECTED(socket(addr.addr.sa_family, SOCK_DGRAM, IPPROTO_UDP)); 98 fd = NO_RETRY_EXPECTED(socket(addr.addr.sa_family, SOCK_DGRAM, IPPROTO_UDP));
318 if (fd < 0) { 99 if (fd < 0) {
319 return -1; 100 return -1;
320 } 101 }
321 102
322 if (!FDUtils::SetCloseOnExec(fd)) { 103 if (!FDUtils::SetCloseOnExec(fd)) {
323 FDUtils::SaveErrorAndClose(fd); 104 FDUtils::SaveErrorAndClose(fd);
(...skipping 13 matching lines...) Expand all
337 } 118 }
338 119
339 if (!FDUtils::SetNonBlocking(fd)) { 120 if (!FDUtils::SetNonBlocking(fd)) {
340 FDUtils::SaveErrorAndClose(fd); 121 FDUtils::SaveErrorAndClose(fd);
341 return -1; 122 return -1;
342 } 123 }
343 return fd; 124 return fd;
344 } 125 }
345 126
346 127
347 static bool ShouldIncludeIfaAddrs(struct ifaddrs* ifa, int lookup_family) {
348 if (ifa->ifa_addr == NULL) {
349 // OpenVPN's virtual device tun0.
350 return false;
351 }
352 int family = ifa->ifa_addr->sa_family;
353 return ((lookup_family == family) ||
354 ((lookup_family == AF_UNSPEC) &&
355 ((family == AF_INET) || (family == AF_INET6))));
356 }
357
358
359 bool Socket::ListInterfacesSupported() {
360 return true;
361 }
362
363
364 AddressList<InterfaceSocketAddress>* Socket::ListInterfaces(
365 int type,
366 OSError** os_error) {
367 struct ifaddrs* ifaddr;
368
369 int status = getifaddrs(&ifaddr);
370 if (status != 0) {
371 ASSERT(*os_error == NULL);
372 *os_error =
373 new OSError(status, gai_strerror(status), OSError::kGetAddressInfo);
374 return NULL;
375 }
376
377 int lookup_family = SocketAddress::FromType(type);
378
379 intptr_t count = 0;
380 for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
381 if (ShouldIncludeIfaAddrs(ifa, lookup_family)) {
382 count++;
383 }
384 }
385
386 AddressList<InterfaceSocketAddress>* addresses =
387 new AddressList<InterfaceSocketAddress>(count);
388 int i = 0;
389 for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
390 if (ShouldIncludeIfaAddrs(ifa, lookup_family)) {
391 char* ifa_name = DartUtils::ScopedCopyCString(ifa->ifa_name);
392 addresses->SetAt(
393 i, new InterfaceSocketAddress(ifa->ifa_addr, ifa_name,
394 if_nametoindex(ifa->ifa_name)));
395 i++;
396 }
397 }
398 freeifaddrs(ifaddr);
399 return addresses;
400 }
401
402
403 intptr_t ServerSocket::CreateBindListen(const RawAddr& addr, 128 intptr_t ServerSocket::CreateBindListen(const RawAddr& addr,
404 intptr_t backlog, 129 intptr_t backlog,
405 bool v6_only) { 130 bool v6_only) {
406 intptr_t fd; 131 intptr_t fd;
407 132
408 fd = TEMP_FAILURE_RETRY(socket(addr.ss.ss_family, SOCK_STREAM, 0)); 133 fd = TEMP_FAILURE_RETRY(socket(addr.ss.ss_family, SOCK_STREAM, 0));
409 if (fd < 0) { 134 if (fd < 0) {
410 return -1; 135 return -1;
411 } 136 }
412 137
(...skipping 13 matching lines...) Expand all
426 } 151 }
427 152
428 if (NO_RETRY_EXPECTED( 153 if (NO_RETRY_EXPECTED(
429 bind(fd, &addr.addr, SocketAddress::GetAddrLength(addr))) < 0) { 154 bind(fd, &addr.addr, SocketAddress::GetAddrLength(addr))) < 0) {
430 FDUtils::SaveErrorAndClose(fd); 155 FDUtils::SaveErrorAndClose(fd);
431 return -1; 156 return -1;
432 } 157 }
433 158
434 // Test for invalid socket port 65535 (some browsers disallow it). 159 // Test for invalid socket port 65535 (some browsers disallow it).
435 if ((SocketAddress::GetAddrPort(addr) == 0) && 160 if ((SocketAddress::GetAddrPort(addr) == 0) &&
436 (Socket::GetPort(fd) == 65535)) { 161 (SocketBase::GetPort(fd) == 65535)) {
437 // Don't close the socket until we have created a new socket, ensuring 162 // Don't close the socket until we have created a new socket, ensuring
438 // that we do not get the bad port number again. 163 // that we do not get the bad port number again.
439 intptr_t new_fd = CreateBindListen(addr, backlog, v6_only); 164 intptr_t new_fd = CreateBindListen(addr, backlog, v6_only);
440 FDUtils::SaveErrorAndClose(fd); 165 FDUtils::SaveErrorAndClose(fd);
441 return new_fd; 166 return new_fd;
442 } 167 }
443 168
444 if (NO_RETRY_EXPECTED(listen(fd, backlog > 0 ? backlog : SOMAXCONN)) != 0) { 169 if (NO_RETRY_EXPECTED(listen(fd, backlog > 0 ? backlog : SOMAXCONN)) != 0) {
445 FDUtils::SaveErrorAndClose(fd); 170 FDUtils::SaveErrorAndClose(fd);
446 return -1; 171 return -1;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
479 return -1; 204 return -1;
480 } 205 }
481 if (!FDUtils::SetNonBlocking(socket)) { 206 if (!FDUtils::SetNonBlocking(socket)) {
482 FDUtils::SaveErrorAndClose(socket); 207 FDUtils::SaveErrorAndClose(socket);
483 return -1; 208 return -1;
484 } 209 }
485 } 210 }
486 return socket; 211 return socket;
487 } 212 }
488 213
489
490 void Socket::Close(intptr_t fd) {
491 ASSERT(fd >= 0);
492 VOID_TEMP_FAILURE_RETRY(close(fd));
493 }
494
495
496 bool Socket::GetNoDelay(intptr_t fd, bool* enabled) {
497 int on;
498 socklen_t len = sizeof(on);
499 int err = NO_RETRY_EXPECTED(getsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
500 reinterpret_cast<void*>(&on), &len));
501 if (err == 0) {
502 *enabled = (on == 1);
503 }
504 return (err == 0);
505 }
506
507
508 bool Socket::SetNoDelay(intptr_t fd, bool enabled) {
509 int on = enabled ? 1 : 0;
510 return NO_RETRY_EXPECTED(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
511 reinterpret_cast<char*>(&on),
512 sizeof(on))) == 0;
513 }
514
515
516 bool Socket::GetMulticastLoop(intptr_t fd, intptr_t protocol, bool* enabled) {
517 uint8_t on;
518 socklen_t len = sizeof(on);
519 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
520 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_LOOP
521 : IPV6_MULTICAST_LOOP;
522 if (NO_RETRY_EXPECTED(getsockopt(fd, level, optname,
523 reinterpret_cast<char*>(&on), &len)) == 0) {
524 *enabled = (on == 1);
525 return true;
526 }
527 return false;
528 }
529
530
531 bool Socket::SetMulticastLoop(intptr_t fd, intptr_t protocol, bool enabled) {
532 u_int on = enabled ? 1 : 0;
533 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
534 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_LOOP
535 : IPV6_MULTICAST_LOOP;
536 return NO_RETRY_EXPECTED(setsockopt(
537 fd, level, optname, reinterpret_cast<char*>(&on), sizeof(on))) ==
538 0;
539 }
540
541
542 bool Socket::GetMulticastHops(intptr_t fd, intptr_t protocol, int* value) {
543 uint8_t v;
544 socklen_t len = sizeof(v);
545 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
546 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_TTL
547 : IPV6_MULTICAST_HOPS;
548 if (NO_RETRY_EXPECTED(getsockopt(fd, level, optname,
549 reinterpret_cast<char*>(&v), &len)) == 0) {
550 *value = v;
551 return true;
552 }
553 return false;
554 }
555
556
557 bool Socket::SetMulticastHops(intptr_t fd, intptr_t protocol, int value) {
558 int v = value;
559 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
560 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_TTL
561 : IPV6_MULTICAST_HOPS;
562 return NO_RETRY_EXPECTED(setsockopt(
563 fd, level, optname, reinterpret_cast<char*>(&v), sizeof(v))) == 0;
564 }
565
566
567 bool Socket::GetBroadcast(intptr_t fd, bool* enabled) {
568 int on;
569 socklen_t len = sizeof(on);
570 int err = NO_RETRY_EXPECTED(getsockopt(fd, SOL_SOCKET, SO_BROADCAST,
571 reinterpret_cast<char*>(&on), &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 NO_RETRY_EXPECTED(setsockopt(fd, SOL_SOCKET, SO_BROADCAST,
582 reinterpret_cast<char*>(&on),
583 sizeof(on))) == 0;
584 }
585
586
587 static bool JoinOrLeaveMulticast(intptr_t fd,
588 const RawAddr& addr,
589 const RawAddr& interface,
590 int interfaceIndex,
591 bool join) {
592 if (addr.addr.sa_family == AF_INET) {
593 ASSERT(interface.addr.sa_family == AF_INET);
594 struct ip_mreq mreq;
595 memmove(&mreq.imr_multiaddr, &addr.in.sin_addr,
596 SocketAddress::GetInAddrLength(addr));
597 memmove(&mreq.imr_interface, &interface.in.sin_addr,
598 SocketAddress::GetInAddrLength(interface));
599 if (join) {
600 return NO_RETRY_EXPECTED(setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
601 &mreq, sizeof(mreq))) == 0;
602 } else {
603 return NO_RETRY_EXPECTED(setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
604 &mreq, sizeof(mreq))) == 0;
605 }
606 } else {
607 ASSERT(addr.addr.sa_family == AF_INET6);
608 struct ipv6_mreq mreq;
609 memmove(&mreq.ipv6mr_multiaddr, &addr.in6.sin6_addr,
610 SocketAddress::GetInAddrLength(addr));
611 mreq.ipv6mr_interface = interfaceIndex;
612 if (join) {
613 return NO_RETRY_EXPECTED(setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
614 &mreq, sizeof(mreq))) == 0;
615 } else {
616 return NO_RETRY_EXPECTED(setsockopt(fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
617 &mreq, sizeof(mreq))) == 0;
618 }
619 }
620 }
621
622 bool Socket::JoinMulticast(intptr_t fd,
623 const RawAddr& addr,
624 const RawAddr& interface,
625 int interfaceIndex) {
626 return JoinOrLeaveMulticast(fd, addr, interface, interfaceIndex, true);
627 }
628
629
630 bool Socket::LeaveMulticast(intptr_t fd,
631 const RawAddr& addr,
632 const RawAddr& interface,
633 int interfaceIndex) {
634 return JoinOrLeaveMulticast(fd, addr, interface, interfaceIndex, false);
635 }
636
637 } // namespace bin 214 } // namespace bin
638 } // namespace dart 215 } // namespace dart
639 216
640 #endif // defined(HOST_OS_MACOS) 217 #endif // defined(HOST_OS_MACOS)
641 218
642 #endif // !defined(DART_IO_DISABLED) 219 #endif // !defined(DART_IO_DISABLED)
OLDNEW
« no previous file with comments | « runtime/bin/socket_macos.h ('k') | runtime/bin/socket_patch.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698