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

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

Powered by Google App Engine
This is Rietveld 408576698