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

Side by Side Diff: runtime/bin/socket_base_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_base_macos.h ('k') | runtime/bin/socket_base_unsupported.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // BSD-style license that can be found in the LICENSE file.
4
5 #if !defined(DART_IO_DISABLED)
6
7 #include "platform/globals.h"
8 #if defined(HOST_OS_MACOS)
9
10 #include "bin/socket_base.h"
11
12 #include <errno.h> // NOLINT
13 #include <ifaddrs.h> // NOLINT
14 #include <net/if.h> // NOLINT
15 #include <netinet/tcp.h> // NOLINT
16 #include <stdio.h> // NOLINT
17 #include <stdlib.h> // NOLINT
18 #include <string.h> // NOLINT
19 #include <sys/stat.h> // NOLINT
20 #include <unistd.h> // NOLINT
21
22 #include "bin/fdutils.h"
23 #include "bin/file.h"
24 #include "bin/socket_base_macos.h"
25 #include "platform/signal_blocker.h"
26
27 namespace dart {
28 namespace bin {
29
30 SocketAddress::SocketAddress(struct sockaddr* sa) {
31 ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN);
32 if (!SocketBase::FormatNumericAddress(*reinterpret_cast<RawAddr*>(sa),
33 as_string_, 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 SocketBase::FormatNumericAddress(const RawAddr& addr,
42 char* address,
43 int len) {
44 socklen_t salen = SocketAddress::GetAddrLength(addr);
45 return (NO_RETRY_EXPECTED(getnameinfo(&addr.addr, salen, address, len, NULL,
46 0, NI_NUMERICHOST)) == 0);
47 }
48
49
50 bool SocketBase::IsBindError(intptr_t error_number) {
51 return error_number == EADDRINUSE || error_number == EADDRNOTAVAIL ||
52 error_number == EINVAL;
53 }
54
55
56 intptr_t SocketBase::Available(intptr_t fd) {
57 return FDUtils::AvailableBytes(fd);
58 }
59
60
61 intptr_t SocketBase::Read(intptr_t fd, void* buffer, intptr_t num_bytes) {
62 ASSERT(fd >= 0);
63 ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, buffer, num_bytes));
64 ASSERT(EAGAIN == EWOULDBLOCK);
65 if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
66 // If the read would block we need to retry and therefore return 0
67 // as the number of bytes written.
68 read_bytes = 0;
69 }
70 return read_bytes;
71 }
72
73
74 intptr_t SocketBase::RecvFrom(intptr_t fd,
75 void* buffer,
76 intptr_t num_bytes,
77 RawAddr* addr) {
78 ASSERT(fd >= 0);
79 socklen_t addr_len = sizeof(addr->ss);
80 ssize_t read_bytes = TEMP_FAILURE_RETRY(
81 recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len));
82 if ((read_bytes == -1) && (errno == EWOULDBLOCK)) {
83 // If the read would block we need to retry and therefore return 0
84 // as the number of bytes written.
85 read_bytes = 0;
86 }
87 return read_bytes;
88 }
89
90
91 intptr_t SocketBase::Write(intptr_t fd,
92 const void* buffer,
93 intptr_t num_bytes) {
94 ASSERT(fd >= 0);
95 ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes));
96 ASSERT(EAGAIN == EWOULDBLOCK);
97 if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
98 // If the would block we need to retry and therefore return 0 as
99 // the number of bytes written.
100 written_bytes = 0;
101 }
102 return written_bytes;
103 }
104
105
106 intptr_t SocketBase::SendTo(intptr_t fd,
107 const void* buffer,
108 intptr_t num_bytes,
109 const RawAddr& addr) {
110 ASSERT(fd >= 0);
111 ssize_t written_bytes =
112 TEMP_FAILURE_RETRY(sendto(fd, buffer, num_bytes, 0, &addr.addr,
113 SocketAddress::GetAddrLength(addr)));
114 ASSERT(EAGAIN == EWOULDBLOCK);
115 if ((written_bytes == -1) && (errno == EWOULDBLOCK)) {
116 // If the would block we need to retry and therefore return 0 as
117 // the number of bytes written.
118 written_bytes = 0;
119 }
120 return written_bytes;
121 }
122
123
124 intptr_t SocketBase::GetPort(intptr_t fd) {
125 ASSERT(fd >= 0);
126 RawAddr raw;
127 socklen_t size = sizeof(raw);
128 if (NO_RETRY_EXPECTED(getsockname(fd, &raw.addr, &size))) {
129 return 0;
130 }
131 return SocketAddress::GetAddrPort(raw);
132 }
133
134
135 SocketAddress* SocketBase::GetRemotePeer(intptr_t fd, intptr_t* port) {
136 ASSERT(fd >= 0);
137 RawAddr raw;
138 socklen_t size = sizeof(raw);
139 if (NO_RETRY_EXPECTED(getpeername(fd, &raw.addr, &size))) {
140 return NULL;
141 }
142 *port = SocketAddress::GetAddrPort(raw);
143 return new SocketAddress(&raw.addr);
144 }
145
146
147 void SocketBase::GetError(intptr_t fd, OSError* os_error) {
148 int len = sizeof(errno);
149 getsockopt(fd, SOL_SOCKET, SO_ERROR, &errno,
150 reinterpret_cast<socklen_t*>(&len));
151 os_error->SetCodeAndMessage(OSError::kSystem, errno);
152 }
153
154
155 int SocketBase::GetType(intptr_t fd) {
156 struct stat buf;
157 int result = fstat(fd, &buf);
158 if (result == -1) {
159 return -1;
160 }
161 if (S_ISCHR(buf.st_mode)) {
162 return File::kTerminal;
163 }
164 if (S_ISFIFO(buf.st_mode)) {
165 return File::kPipe;
166 }
167 if (S_ISREG(buf.st_mode)) {
168 return File::kFile;
169 }
170 return File::kOther;
171 }
172
173
174 intptr_t SocketBase::GetStdioHandle(intptr_t num) {
175 return num;
176 }
177
178
179 AddressList<SocketAddress>* SocketBase::LookupAddress(const char* host,
180 int type,
181 OSError** os_error) {
182 // Perform a name lookup for a host name.
183 struct addrinfo hints;
184 memset(&hints, 0, sizeof(hints));
185 hints.ai_family = SocketAddress::FromType(type);
186 hints.ai_socktype = SOCK_STREAM;
187 hints.ai_flags = 0;
188 hints.ai_protocol = IPPROTO_TCP;
189 struct addrinfo* info = NULL;
190 int status = getaddrinfo(host, 0, &hints, &info);
191 if (status != 0) {
192 ASSERT(*os_error == NULL);
193 *os_error =
194 new OSError(status, gai_strerror(status), OSError::kGetAddressInfo);
195 return NULL;
196 }
197 intptr_t count = 0;
198 for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
199 if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
200 count++;
201 }
202 }
203 intptr_t i = 0;
204 AddressList<SocketAddress>* addresses = new AddressList<SocketAddress>(count);
205 for (struct addrinfo* c = info; c != NULL; c = c->ai_next) {
206 if ((c->ai_family == AF_INET) || (c->ai_family == AF_INET6)) {
207 addresses->SetAt(i, new SocketAddress(c->ai_addr));
208 i++;
209 }
210 }
211 freeaddrinfo(info);
212 return addresses;
213 }
214
215
216 bool SocketBase::ReverseLookup(const RawAddr& addr,
217 char* host,
218 intptr_t host_len,
219 OSError** os_error) {
220 ASSERT(host_len >= NI_MAXHOST);
221 int status = NO_RETRY_EXPECTED(
222 getnameinfo(&addr.addr, SocketAddress::GetAddrLength(addr), host,
223 host_len, NULL, 0, NI_NAMEREQD));
224 if (status != 0) {
225 ASSERT(*os_error == NULL);
226 *os_error =
227 new OSError(status, gai_strerror(status), OSError::kGetAddressInfo);
228 return false;
229 }
230 return true;
231 }
232
233
234 bool SocketBase::ParseAddress(int type, const char* address, RawAddr* addr) {
235 int result;
236 if (type == SocketAddress::TYPE_IPV4) {
237 result = inet_pton(AF_INET, address, &addr->in.sin_addr);
238 } else {
239 ASSERT(type == SocketAddress::TYPE_IPV6);
240 result = inet_pton(AF_INET6, address, &addr->in6.sin6_addr);
241 }
242 return (result == 1);
243 }
244
245
246 static bool ShouldIncludeIfaAddrs(struct ifaddrs* ifa, int lookup_family) {
247 if (ifa->ifa_addr == NULL) {
248 // OpenVPN's virtual device tun0.
249 return false;
250 }
251 int family = ifa->ifa_addr->sa_family;
252 return ((lookup_family == family) ||
253 ((lookup_family == AF_UNSPEC) &&
254 ((family == AF_INET) || (family == AF_INET6))));
255 }
256
257
258 bool SocketBase::ListInterfacesSupported() {
259 return true;
260 }
261
262
263 AddressList<InterfaceSocketAddress>* SocketBase::ListInterfaces(
264 int type,
265 OSError** os_error) {
266 struct ifaddrs* ifaddr;
267
268 int status = getifaddrs(&ifaddr);
269 if (status != 0) {
270 ASSERT(*os_error == NULL);
271 *os_error =
272 new OSError(status, gai_strerror(status), OSError::kGetAddressInfo);
273 return NULL;
274 }
275
276 int lookup_family = SocketAddress::FromType(type);
277
278 intptr_t count = 0;
279 for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
280 if (ShouldIncludeIfaAddrs(ifa, lookup_family)) {
281 count++;
282 }
283 }
284
285 AddressList<InterfaceSocketAddress>* addresses =
286 new AddressList<InterfaceSocketAddress>(count);
287 int i = 0;
288 for (struct ifaddrs* ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) {
289 if (ShouldIncludeIfaAddrs(ifa, lookup_family)) {
290 char* ifa_name = DartUtils::ScopedCopyCString(ifa->ifa_name);
291 addresses->SetAt(
292 i, new InterfaceSocketAddress(ifa->ifa_addr, ifa_name,
293 if_nametoindex(ifa->ifa_name)));
294 i++;
295 }
296 }
297 freeifaddrs(ifaddr);
298 return addresses;
299 }
300
301
302 void SocketBase::Close(intptr_t fd) {
303 ASSERT(fd >= 0);
304 VOID_TEMP_FAILURE_RETRY(close(fd));
305 }
306
307
308 bool SocketBase::GetNoDelay(intptr_t fd, bool* enabled) {
309 int on;
310 socklen_t len = sizeof(on);
311 int err = NO_RETRY_EXPECTED(getsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
312 reinterpret_cast<void*>(&on), &len));
313 if (err == 0) {
314 *enabled = (on == 1);
315 }
316 return (err == 0);
317 }
318
319
320 bool SocketBase::SetNoDelay(intptr_t fd, bool enabled) {
321 int on = enabled ? 1 : 0;
322 return NO_RETRY_EXPECTED(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
323 reinterpret_cast<char*>(&on),
324 sizeof(on))) == 0;
325 }
326
327
328 bool SocketBase::GetMulticastLoop(intptr_t fd,
329 intptr_t protocol,
330 bool* enabled) {
331 uint8_t on;
332 socklen_t len = sizeof(on);
333 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
334 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_LOOP
335 : IPV6_MULTICAST_LOOP;
336 if (NO_RETRY_EXPECTED(getsockopt(fd, level, optname,
337 reinterpret_cast<char*>(&on), &len)) == 0) {
338 *enabled = (on == 1);
339 return true;
340 }
341 return false;
342 }
343
344
345 bool SocketBase::SetMulticastLoop(intptr_t fd,
346 intptr_t protocol,
347 bool enabled) {
348 u_int on = enabled ? 1 : 0;
349 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
350 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_LOOP
351 : IPV6_MULTICAST_LOOP;
352 return NO_RETRY_EXPECTED(setsockopt(
353 fd, level, optname, reinterpret_cast<char*>(&on), sizeof(on))) ==
354 0;
355 }
356
357
358 bool SocketBase::GetMulticastHops(intptr_t fd, intptr_t protocol, int* value) {
359 uint8_t v;
360 socklen_t len = sizeof(v);
361 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
362 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_TTL
363 : IPV6_MULTICAST_HOPS;
364 if (NO_RETRY_EXPECTED(getsockopt(fd, level, optname,
365 reinterpret_cast<char*>(&v), &len)) == 0) {
366 *value = v;
367 return true;
368 }
369 return false;
370 }
371
372
373 bool SocketBase::SetMulticastHops(intptr_t fd, intptr_t protocol, int value) {
374 int v = value;
375 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6;
376 int optname = protocol == SocketAddress::TYPE_IPV4 ? IP_MULTICAST_TTL
377 : IPV6_MULTICAST_HOPS;
378 return NO_RETRY_EXPECTED(setsockopt(
379 fd, level, optname, reinterpret_cast<char*>(&v), sizeof(v))) == 0;
380 }
381
382
383 bool SocketBase::GetBroadcast(intptr_t fd, bool* enabled) {
384 int on;
385 socklen_t len = sizeof(on);
386 int err = NO_RETRY_EXPECTED(getsockopt(fd, SOL_SOCKET, SO_BROADCAST,
387 reinterpret_cast<char*>(&on), &len));
388 if (err == 0) {
389 *enabled = (on == 1);
390 }
391 return (err == 0);
392 }
393
394
395 bool SocketBase::SetBroadcast(intptr_t fd, bool enabled) {
396 int on = enabled ? 1 : 0;
397 return NO_RETRY_EXPECTED(setsockopt(fd, SOL_SOCKET, SO_BROADCAST,
398 reinterpret_cast<char*>(&on),
399 sizeof(on))) == 0;
400 }
401
402
403 static bool JoinOrLeaveMulticast(intptr_t fd,
404 const RawAddr& addr,
405 const RawAddr& interface,
406 int interfaceIndex,
407 bool join) {
408 if (addr.addr.sa_family == AF_INET) {
409 ASSERT(interface.addr.sa_family == AF_INET);
410 struct ip_mreq mreq;
411 memmove(&mreq.imr_multiaddr, &addr.in.sin_addr,
412 SocketAddress::GetInAddrLength(addr));
413 memmove(&mreq.imr_interface, &interface.in.sin_addr,
414 SocketAddress::GetInAddrLength(interface));
415 if (join) {
416 return NO_RETRY_EXPECTED(setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP,
417 &mreq, sizeof(mreq))) == 0;
418 } else {
419 return NO_RETRY_EXPECTED(setsockopt(fd, IPPROTO_IP, IP_DROP_MEMBERSHIP,
420 &mreq, sizeof(mreq))) == 0;
421 }
422 } else {
423 ASSERT(addr.addr.sa_family == AF_INET6);
424 struct ipv6_mreq mreq;
425 memmove(&mreq.ipv6mr_multiaddr, &addr.in6.sin6_addr,
426 SocketAddress::GetInAddrLength(addr));
427 mreq.ipv6mr_interface = interfaceIndex;
428 if (join) {
429 return NO_RETRY_EXPECTED(setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP,
430 &mreq, sizeof(mreq))) == 0;
431 } else {
432 return NO_RETRY_EXPECTED(setsockopt(fd, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
433 &mreq, sizeof(mreq))) == 0;
434 }
435 }
436 }
437
438 bool SocketBase::JoinMulticast(intptr_t fd,
439 const RawAddr& addr,
440 const RawAddr& interface,
441 int interfaceIndex) {
442 return JoinOrLeaveMulticast(fd, addr, interface, interfaceIndex, true);
443 }
444
445
446 bool SocketBase::LeaveMulticast(intptr_t fd,
447 const RawAddr& addr,
448 const RawAddr& interface,
449 int interfaceIndex) {
450 return JoinOrLeaveMulticast(fd, addr, interface, interfaceIndex, false);
451 }
452
453 } // namespace bin
454 } // namespace dart
455
456 #endif // defined(HOST_OS_MACOS)
457
458 #endif // !defined(DART_IO_DISABLED)
OLDNEW
« no previous file with comments | « runtime/bin/socket_base_macos.h ('k') | runtime/bin/socket_base_unsupported.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698