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

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

Issue 2791163004: Reverting until bots clear up. (Closed)
Patch Set: 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
10 #include <errno.h> // NOLINT 13 #include <errno.h> // NOLINT
11 #include <ifaddrs.h> // NOLINT 14 #include <ifaddrs.h> // NOLINT
12 #include <net/if.h> // NOLINT 15 #include <net/if.h> // NOLINT
13 #include <netinet/tcp.h> // NOLINT 16 #include <netinet/tcp.h> // NOLINT
14 #include <stdio.h> // NOLINT 17 #include <stdio.h> // NOLINT
15 #include <stdlib.h> // NOLINT 18 #include <stdlib.h> // NOLINT
16 #include <string.h> // NOLINT 19 #include <string.h> // NOLINT
17 #include <sys/stat.h> // NOLINT 20 #include <sys/stat.h> // NOLINT
18 #include <unistd.h> // NOLINT 21 #include <unistd.h> // NOLINT
19 22
20 #include "bin/fdutils.h" 23 #include "bin/fdutils.h"
21 #include "bin/file.h" 24 #include "bin/file.h"
22 #include "bin/socket.h"
23 #include "bin/socket_base_macos.h"
24 #include "platform/signal_blocker.h" 25 #include "platform/signal_blocker.h"
25 26
26 namespace dart { 27 namespace dart {
27 namespace bin { 28 namespace bin {
28 29
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
29 Socket::Socket(intptr_t fd) 48 Socket::Socket(intptr_t fd)
30 : ReferenceCounted(), fd_(fd), port_(ILLEGAL_PORT) {} 49 : ReferenceCounted(), fd_(fd), port_(ILLEGAL_PORT) {}
31 50
32 51
33 void Socket::SetClosedFd() { 52 void Socket::SetClosedFd() {
34 fd_ = kClosedFd; 53 fd_ = kClosedFd;
35 } 54 }
36 55
37 56
38 bool Socket::Initialize() { 57 bool Socket::Initialize() {
(...skipping 52 matching lines...) Expand 10 before | Expand all | Expand 10 after
91 bind(fd, &source_addr.addr, SocketAddress::GetAddrLength(source_addr))); 110 bind(fd, &source_addr.addr, SocketAddress::GetAddrLength(source_addr)));
92 if ((result != 0) && (errno != EINPROGRESS)) { 111 if ((result != 0) && (errno != EINPROGRESS)) {
93 FDUtils::SaveErrorAndClose(fd); 112 FDUtils::SaveErrorAndClose(fd);
94 return -1; 113 return -1;
95 } 114 }
96 115
97 return Connect(fd, addr); 116 return Connect(fd, addr);
98 } 117 }
99 118
100 119
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
101 intptr_t Socket::CreateBindDatagram(const RawAddr& addr, bool reuseAddress) { 314 intptr_t Socket::CreateBindDatagram(const RawAddr& addr, bool reuseAddress) {
102 intptr_t fd; 315 intptr_t fd;
103 316
104 fd = NO_RETRY_EXPECTED(socket(addr.addr.sa_family, SOCK_DGRAM, IPPROTO_UDP)); 317 fd = NO_RETRY_EXPECTED(socket(addr.addr.sa_family, SOCK_DGRAM, IPPROTO_UDP));
105 if (fd < 0) { 318 if (fd < 0) {
106 return -1; 319 return -1;
107 } 320 }
108 321
109 if (!FDUtils::SetCloseOnExec(fd)) { 322 if (!FDUtils::SetCloseOnExec(fd)) {
110 FDUtils::SaveErrorAndClose(fd); 323 FDUtils::SaveErrorAndClose(fd);
(...skipping 13 matching lines...) Expand all
124 } 337 }
125 338
126 if (!FDUtils::SetNonBlocking(fd)) { 339 if (!FDUtils::SetNonBlocking(fd)) {
127 FDUtils::SaveErrorAndClose(fd); 340 FDUtils::SaveErrorAndClose(fd);
128 return -1; 341 return -1;
129 } 342 }
130 return fd; 343 return fd;
131 } 344 }
132 345
133 346
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
134 intptr_t ServerSocket::CreateBindListen(const RawAddr& addr, 403 intptr_t ServerSocket::CreateBindListen(const RawAddr& addr,
135 intptr_t backlog, 404 intptr_t backlog,
136 bool v6_only) { 405 bool v6_only) {
137 intptr_t fd; 406 intptr_t fd;
138 407
139 fd = TEMP_FAILURE_RETRY(socket(addr.ss.ss_family, SOCK_STREAM, 0)); 408 fd = TEMP_FAILURE_RETRY(socket(addr.ss.ss_family, SOCK_STREAM, 0));
140 if (fd < 0) { 409 if (fd < 0) {
141 return -1; 410 return -1;
142 } 411 }
143 412
(...skipping 13 matching lines...) Expand all
157 } 426 }
158 427
159 if (NO_RETRY_EXPECTED( 428 if (NO_RETRY_EXPECTED(
160 bind(fd, &addr.addr, SocketAddress::GetAddrLength(addr))) < 0) { 429 bind(fd, &addr.addr, SocketAddress::GetAddrLength(addr))) < 0) {
161 FDUtils::SaveErrorAndClose(fd); 430 FDUtils::SaveErrorAndClose(fd);
162 return -1; 431 return -1;
163 } 432 }
164 433
165 // Test for invalid socket port 65535 (some browsers disallow it). 434 // Test for invalid socket port 65535 (some browsers disallow it).
166 if ((SocketAddress::GetAddrPort(addr) == 0) && 435 if ((SocketAddress::GetAddrPort(addr) == 0) &&
167 (SocketBase::GetPort(fd) == 65535)) { 436 (Socket::GetPort(fd) == 65535)) {
168 // Don't close the socket until we have created a new socket, ensuring 437 // Don't close the socket until we have created a new socket, ensuring
169 // that we do not get the bad port number again. 438 // that we do not get the bad port number again.
170 intptr_t new_fd = CreateBindListen(addr, backlog, v6_only); 439 intptr_t new_fd = CreateBindListen(addr, backlog, v6_only);
171 FDUtils::SaveErrorAndClose(fd); 440 FDUtils::SaveErrorAndClose(fd);
172 return new_fd; 441 return new_fd;
173 } 442 }
174 443
175 if (NO_RETRY_EXPECTED(listen(fd, backlog > 0 ? backlog : SOMAXCONN)) != 0) { 444 if (NO_RETRY_EXPECTED(listen(fd, backlog > 0 ? backlog : SOMAXCONN)) != 0) {
176 FDUtils::SaveErrorAndClose(fd); 445 FDUtils::SaveErrorAndClose(fd);
177 return -1; 446 return -1;
(...skipping 32 matching lines...) Expand 10 before | Expand all | Expand 10 after
210 return -1; 479 return -1;
211 } 480 }
212 if (!FDUtils::SetNonBlocking(socket)) { 481 if (!FDUtils::SetNonBlocking(socket)) {
213 FDUtils::SaveErrorAndClose(socket); 482 FDUtils::SaveErrorAndClose(socket);
214 return -1; 483 return -1;
215 } 484 }
216 } 485 }
217 return socket; 486 return socket;
218 } 487 }
219 488
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
220 } // namespace bin 637 } // namespace bin
221 } // namespace dart 638 } // namespace dart
222 639
223 #endif // defined(HOST_OS_MACOS) 640 #endif // defined(HOST_OS_MACOS)
224 641
225 #endif // !defined(DART_IO_DISABLED) 642 #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