OLD | NEW |
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_LINUX) | 6 #if defined(TARGET_OS_LINUX) |
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/signal_blocker.h" | |
22 #include "bin/socket.h" | 21 #include "bin/socket.h" |
| 22 #include "platform/signal_blocker.h" |
23 #include "vm/thread.h" | 23 #include "vm/thread.h" |
24 | 24 |
25 | 25 |
26 namespace dart { | 26 namespace dart { |
27 namespace bin { | 27 namespace bin { |
28 | 28 |
29 SocketAddress::SocketAddress(struct sockaddr* sa) { | 29 SocketAddress::SocketAddress(struct sockaddr* sa) { |
30 ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN); | 30 ASSERT(INET6_ADDRSTRLEN >= INET_ADDRSTRLEN); |
31 if (!Socket::FormatNumericAddress( | 31 if (!Socket::FormatNumericAddress( |
32 reinterpret_cast<RawAddr*>(sa), as_string_, INET6_ADDRSTRLEN)) { | 32 reinterpret_cast<RawAddr*>(sa), as_string_, INET6_ADDRSTRLEN)) { |
33 as_string_[0] = 0; | 33 as_string_[0] = 0; |
34 } | 34 } |
35 socklen_t salen = GetAddrLength(reinterpret_cast<RawAddr*>(sa)); | 35 socklen_t salen = GetAddrLength(reinterpret_cast<RawAddr*>(sa)); |
36 memmove(reinterpret_cast<void *>(&addr_), sa, salen); | 36 memmove(reinterpret_cast<void *>(&addr_), sa, salen); |
37 } | 37 } |
38 | 38 |
39 | 39 |
40 bool Socket::FormatNumericAddress(RawAddr* addr, char* address, int len) { | 40 bool Socket::FormatNumericAddress(RawAddr* addr, char* address, int len) { |
41 socklen_t salen = SocketAddress::GetAddrLength(addr); | 41 socklen_t salen = SocketAddress::GetAddrLength(addr); |
42 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getnameinfo(&addr->addr, | 42 if (getnameinfo( |
43 salen, | 43 &addr->addr, salen, address, len, NULL, 0, NI_NUMERICHOST) != 0) { |
44 address, | |
45 len, | |
46 NULL, | |
47 0, | |
48 NI_NUMERICHOST)) != 0) { | |
49 return false; | 44 return false; |
50 } | 45 } |
51 return true; | 46 return true; |
52 } | 47 } |
53 | 48 |
54 | 49 |
55 bool Socket::Initialize() { | 50 bool Socket::Initialize() { |
56 // Nothing to do on Linux. | 51 // Nothing to do on Linux. |
57 return true; | 52 return true; |
58 } | 53 } |
59 | 54 |
60 | 55 |
61 intptr_t Socket::Create(RawAddr addr) { | 56 intptr_t Socket::Create(RawAddr addr) { |
62 intptr_t fd; | 57 intptr_t fd; |
63 fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(socket( | 58 fd = socket(addr.ss.ss_family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0); |
64 addr.ss.ss_family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); | |
65 if (fd < 0) { | 59 if (fd < 0) { |
66 const int kBufferSize = 1024; | 60 const int kBufferSize = 1024; |
67 char error_buf[kBufferSize]; | 61 char error_buf[kBufferSize]; |
68 Log::PrintErr("Error Create: %s\n", | 62 Log::PrintErr("Error Create: %s\n", |
69 strerror_r(errno, error_buf, kBufferSize)); | 63 strerror_r(errno, error_buf, kBufferSize)); |
70 return -1; | 64 return -1; |
71 } | 65 } |
72 return fd; | 66 return fd; |
73 } | 67 } |
74 | 68 |
75 | 69 |
76 intptr_t Socket::Connect(intptr_t fd, RawAddr addr, const intptr_t port) { | 70 intptr_t Socket::Connect(intptr_t fd, RawAddr addr, const intptr_t port) { |
77 SocketAddress::SetAddrPort(&addr, port); | 71 SocketAddress::SetAddrPort(&addr, port); |
78 intptr_t result = TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 72 intptr_t result = TEMP_FAILURE_RETRY( |
79 connect(fd, | 73 connect(fd, &addr.addr, SocketAddress::GetAddrLength(&addr))); |
80 &addr.addr, | |
81 SocketAddress::GetAddrLength(&addr))); | |
82 if (result == 0 || errno == EINPROGRESS) { | 74 if (result == 0 || errno == EINPROGRESS) { |
83 return fd; | 75 return fd; |
84 } | 76 } |
85 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd)); | 77 VOID_TEMP_FAILURE_RETRY(close(fd)); |
86 return -1; | 78 return -1; |
87 } | 79 } |
88 | 80 |
89 | 81 |
90 intptr_t Socket::CreateConnect(RawAddr addr, const intptr_t port) { | 82 intptr_t Socket::CreateConnect(RawAddr addr, const intptr_t port) { |
91 intptr_t fd = Socket::Create(addr); | 83 intptr_t fd = Socket::Create(addr); |
92 if (fd < 0) { | 84 if (fd < 0) { |
93 return fd; | 85 return fd; |
94 } | 86 } |
95 return Socket::Connect(fd, addr, port); | 87 return Socket::Connect(fd, addr, port); |
96 } | 88 } |
97 | 89 |
98 | 90 |
99 intptr_t Socket::Available(intptr_t fd) { | 91 intptr_t Socket::Available(intptr_t fd) { |
100 return FDUtils::AvailableBytes(fd); | 92 return FDUtils::AvailableBytes(fd); |
101 } | 93 } |
102 | 94 |
103 | 95 |
104 int Socket::Read(intptr_t fd, void* buffer, intptr_t num_bytes) { | 96 int Socket::Read(intptr_t fd, void* buffer, intptr_t num_bytes) { |
105 ASSERT(fd >= 0); | 97 ASSERT(fd >= 0); |
106 ssize_t read_bytes = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(read(fd, buffer, | 98 ssize_t read_bytes = TEMP_FAILURE_RETRY(read(fd, buffer, num_bytes)); |
107 num_bytes)); | |
108 ASSERT(EAGAIN == EWOULDBLOCK); | 99 ASSERT(EAGAIN == EWOULDBLOCK); |
109 if (read_bytes == -1 && errno == EWOULDBLOCK) { | 100 if (read_bytes == -1 && errno == EWOULDBLOCK) { |
110 // If the read would block we need to retry and therefore return 0 | 101 // If the read would block we need to retry and therefore return 0 |
111 // as the number of bytes written. | 102 // as the number of bytes written. |
112 read_bytes = 0; | 103 read_bytes = 0; |
113 } | 104 } |
114 return read_bytes; | 105 return read_bytes; |
115 } | 106 } |
116 | 107 |
117 | 108 |
118 int Socket::RecvFrom(intptr_t fd, void* buffer, intptr_t num_bytes, | 109 int Socket::RecvFrom(intptr_t fd, void* buffer, intptr_t num_bytes, |
119 RawAddr* addr) { | 110 RawAddr* addr) { |
120 ASSERT(fd >= 0); | 111 ASSERT(fd >= 0); |
121 socklen_t addr_len = sizeof(addr->ss); | 112 socklen_t addr_len = sizeof(addr->ss); |
122 ssize_t read_bytes = | 113 ssize_t read_bytes = TEMP_FAILURE_RETRY( |
123 TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 114 recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len)); |
124 recvfrom(fd, buffer, num_bytes, 0, &addr->addr, &addr_len)); | |
125 if (read_bytes == -1 && errno == EWOULDBLOCK) { | 115 if (read_bytes == -1 && errno == EWOULDBLOCK) { |
126 // If the read would block we need to retry and therefore return 0 | 116 // If the read would block we need to retry and therefore return 0 |
127 // as the number of bytes written. | 117 // as the number of bytes written. |
128 read_bytes = 0; | 118 read_bytes = 0; |
129 } | 119 } |
130 return read_bytes; | 120 return read_bytes; |
131 } | 121 } |
132 | 122 |
133 | 123 |
134 int Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) { | 124 int Socket::Write(intptr_t fd, const void* buffer, intptr_t num_bytes) { |
135 ASSERT(fd >= 0); | 125 ASSERT(fd >= 0); |
136 ssize_t written_bytes = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(write(fd, buffer, | 126 ssize_t written_bytes = TEMP_FAILURE_RETRY(write(fd, buffer, num_bytes)); |
137 num_bytes)); | |
138 ASSERT(EAGAIN == EWOULDBLOCK); | 127 ASSERT(EAGAIN == EWOULDBLOCK); |
139 if (written_bytes == -1 && errno == EWOULDBLOCK) { | 128 if (written_bytes == -1 && errno == EWOULDBLOCK) { |
140 // If the would block we need to retry and therefore return 0 as | 129 // If the would block we need to retry and therefore return 0 as |
141 // the number of bytes written. | 130 // the number of bytes written. |
142 written_bytes = 0; | 131 written_bytes = 0; |
143 } | 132 } |
144 return written_bytes; | 133 return written_bytes; |
145 } | 134 } |
146 | 135 |
147 | 136 |
148 int Socket::SendTo(intptr_t fd, const void* buffer, intptr_t num_bytes, | 137 int Socket::SendTo(intptr_t fd, const void* buffer, intptr_t num_bytes, |
149 RawAddr addr) { | 138 RawAddr addr) { |
150 ASSERT(fd >= 0); | 139 ASSERT(fd >= 0); |
151 ssize_t written_bytes = | 140 ssize_t written_bytes = TEMP_FAILURE_RETRY( |
152 TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 141 sendto(fd, buffer, num_bytes, 0, |
153 sendto(fd, buffer, num_bytes, 0, | 142 &addr.addr, SocketAddress::GetAddrLength(&addr))); |
154 &addr.addr, SocketAddress::GetAddrLength(&addr))); | |
155 ASSERT(EAGAIN == EWOULDBLOCK); | 143 ASSERT(EAGAIN == EWOULDBLOCK); |
156 if (written_bytes == -1 && errno == EWOULDBLOCK) { | 144 if (written_bytes == -1 && errno == EWOULDBLOCK) { |
157 // If the would block we need to retry and therefore return 0 as | 145 // If the would block we need to retry and therefore return 0 as |
158 // the number of bytes written. | 146 // the number of bytes written. |
159 written_bytes = 0; | 147 written_bytes = 0; |
160 } | 148 } |
161 return written_bytes; | 149 return written_bytes; |
162 } | 150 } |
163 | 151 |
164 | 152 |
165 intptr_t Socket::GetPort(intptr_t fd) { | 153 intptr_t Socket::GetPort(intptr_t fd) { |
166 ASSERT(fd >= 0); | 154 ASSERT(fd >= 0); |
167 RawAddr raw; | 155 RawAddr raw; |
168 socklen_t size = sizeof(raw); | 156 socklen_t size = sizeof(raw); |
169 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 157 if (getsockname(fd, &raw.addr, &size)) { |
170 getsockname(fd, | |
171 &raw.addr, | |
172 &size))) { | |
173 const int kBufferSize = 1024; | 158 const int kBufferSize = 1024; |
174 char error_buf[kBufferSize]; | 159 char error_buf[kBufferSize]; |
175 Log::PrintErr("Error getsockname: %s\n", | 160 Log::PrintErr("Error getsockname: %s\n", |
176 strerror_r(errno, error_buf, kBufferSize)); | 161 strerror_r(errno, error_buf, kBufferSize)); |
177 return 0; | 162 return 0; |
178 } | 163 } |
179 return SocketAddress::GetAddrPort(&raw); | 164 return SocketAddress::GetAddrPort(&raw); |
180 } | 165 } |
181 | 166 |
182 | 167 |
183 SocketAddress* Socket::GetRemotePeer(intptr_t fd, intptr_t* port) { | 168 SocketAddress* Socket::GetRemotePeer(intptr_t fd, intptr_t* port) { |
184 ASSERT(fd >= 0); | 169 ASSERT(fd >= 0); |
185 RawAddr raw; | 170 RawAddr raw; |
186 socklen_t size = sizeof(raw); | 171 socklen_t size = sizeof(raw); |
187 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 172 if (getpeername(fd, &raw.addr, &size)) { |
188 getpeername(fd, | |
189 &raw.addr, | |
190 &size))) { | |
191 const int kBufferSize = 1024; | 173 const int kBufferSize = 1024; |
192 char error_buf[kBufferSize]; | 174 char error_buf[kBufferSize]; |
193 Log::PrintErr("Error getpeername: %s\n", | 175 Log::PrintErr("Error getpeername: %s\n", |
194 strerror_r(errno, error_buf, kBufferSize)); | 176 strerror_r(errno, error_buf, kBufferSize)); |
195 return NULL; | 177 return NULL; |
196 } | 178 } |
197 *port = SocketAddress::GetAddrPort(&raw); | 179 *port = SocketAddress::GetAddrPort(&raw); |
198 return new SocketAddress(&raw.addr); | 180 return new SocketAddress(&raw.addr); |
199 } | 181 } |
200 | 182 |
(...skipping 67 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
268 freeaddrinfo(info); | 250 freeaddrinfo(info); |
269 return addresses; | 251 return addresses; |
270 } | 252 } |
271 | 253 |
272 | 254 |
273 bool Socket::ReverseLookup(RawAddr addr, | 255 bool Socket::ReverseLookup(RawAddr addr, |
274 char* host, | 256 char* host, |
275 intptr_t host_len, | 257 intptr_t host_len, |
276 OSError** os_error) { | 258 OSError** os_error) { |
277 ASSERT(host_len >= NI_MAXHOST); | 259 ASSERT(host_len >= NI_MAXHOST); |
278 int status = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getnameinfo( | 260 int status = getnameinfo( |
279 &addr.addr, | 261 &addr.addr, |
280 SocketAddress::GetAddrLength(&addr), | 262 SocketAddress::GetAddrLength(&addr), |
281 host, | 263 host, |
282 host_len, | 264 host_len, |
283 NULL, | 265 NULL, |
284 0, | 266 0, |
285 NI_NAMEREQD)); | 267 NI_NAMEREQD); |
286 if (status != 0) { | 268 if (status != 0) { |
287 ASSERT(*os_error == NULL); | 269 ASSERT(*os_error == NULL); |
288 *os_error = new OSError(status, | 270 *os_error = new OSError(status, |
289 gai_strerror(status), | 271 gai_strerror(status), |
290 OSError::kGetAddressInfo); | 272 OSError::kGetAddressInfo); |
291 return false; | 273 return false; |
292 } | 274 } |
293 return true; | 275 return true; |
294 } | 276 } |
295 | 277 |
296 | 278 |
297 bool Socket::ParseAddress(int type, const char* address, RawAddr* addr) { | 279 bool Socket::ParseAddress(int type, const char* address, RawAddr* addr) { |
298 int result; | 280 int result; |
299 if (type == SocketAddress::TYPE_IPV4) { | 281 if (type == SocketAddress::TYPE_IPV4) { |
300 result = inet_pton(AF_INET, address, &addr->in.sin_addr); | 282 result = inet_pton(AF_INET, address, &addr->in.sin_addr); |
301 } else { | 283 } else { |
302 ASSERT(type == SocketAddress::TYPE_IPV6); | 284 ASSERT(type == SocketAddress::TYPE_IPV6); |
303 result = inet_pton(AF_INET6, address, &addr->in6.sin6_addr); | 285 result = inet_pton(AF_INET6, address, &addr->in6.sin6_addr); |
304 } | 286 } |
305 return result == 1; | 287 return result == 1; |
306 } | 288 } |
307 | 289 |
308 | 290 |
309 intptr_t Socket::CreateBindDatagram( | 291 intptr_t Socket::CreateBindDatagram( |
310 RawAddr* addr, intptr_t port, bool reuseAddress) { | 292 RawAddr* addr, intptr_t port, bool reuseAddress) { |
311 intptr_t fd; | 293 intptr_t fd; |
312 | 294 |
313 fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(socket( | 295 fd = socket(addr->addr.sa_family, |
314 addr->addr.sa_family, | 296 SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, |
315 SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, | 297 IPPROTO_UDP); |
316 IPPROTO_UDP)); | |
317 if (fd < 0) return -1; | 298 if (fd < 0) return -1; |
318 | 299 |
319 if (reuseAddress) { | 300 if (reuseAddress) { |
320 int optval = 1; | 301 int optval = 1; |
321 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 302 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); |
322 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))); | |
323 } | 303 } |
324 | 304 |
325 SocketAddress::SetAddrPort(addr, port); | 305 SocketAddress::SetAddrPort(addr, port); |
326 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 306 if (bind(fd, &addr->addr, SocketAddress::GetAddrLength(addr)) < 0) { |
327 bind(fd, | 307 TEMP_FAILURE_RETRY(close(fd)); |
328 &addr->addr, | |
329 SocketAddress::GetAddrLength(addr))) < 0) { | |
330 TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd)); | |
331 return -1; | 308 return -1; |
332 } | 309 } |
333 return fd; | 310 return fd; |
334 } | 311 } |
335 | 312 |
336 | 313 |
337 static bool ShouldIncludeIfaAddrs(struct ifaddrs* ifa, int lookup_family) { | 314 static bool ShouldIncludeIfaAddrs(struct ifaddrs* ifa, int lookup_family) { |
338 if (ifa->ifa_addr == NULL) { | 315 if (ifa->ifa_addr == NULL) { |
339 // OpenVPN's virtual device tun0. | 316 // OpenVPN's virtual device tun0. |
340 return false; | 317 return false; |
(...skipping 43 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
384 return addresses; | 361 return addresses; |
385 } | 362 } |
386 | 363 |
387 | 364 |
388 intptr_t ServerSocket::CreateBindListen(RawAddr addr, | 365 intptr_t ServerSocket::CreateBindListen(RawAddr addr, |
389 intptr_t port, | 366 intptr_t port, |
390 intptr_t backlog, | 367 intptr_t backlog, |
391 bool v6_only) { | 368 bool v6_only) { |
392 intptr_t fd; | 369 intptr_t fd; |
393 | 370 |
394 fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(socket( | 371 fd = socket(addr.ss.ss_family, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0); |
395 addr.ss.ss_family, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)); | |
396 if (fd < 0) return -1; | 372 if (fd < 0) return -1; |
397 | 373 |
398 int optval = 1; | 374 int optval = 1; |
399 TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 375 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)); |
400 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))); | |
401 | 376 |
402 if (addr.ss.ss_family == AF_INET6) { | 377 if (addr.ss.ss_family == AF_INET6) { |
403 optval = v6_only ? 1 : 0; | 378 optval = v6_only ? 1 : 0; |
404 TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 379 setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval)); |
405 setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval))); | |
406 } | 380 } |
407 | 381 |
408 SocketAddress::SetAddrPort(&addr, port); | 382 SocketAddress::SetAddrPort(&addr, port); |
409 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 383 if (bind(fd, &addr.addr, SocketAddress::GetAddrLength(&addr)) < 0) { |
410 bind(fd, | 384 VOID_TEMP_FAILURE_RETRY(close(fd)); |
411 &addr.addr, | |
412 SocketAddress::GetAddrLength(&addr))) < 0) { | |
413 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd)); | |
414 return -1; | 385 return -1; |
415 } | 386 } |
416 | 387 |
417 // Test for invalid socket port 65535 (some browsers disallow it). | 388 // Test for invalid socket port 65535 (some browsers disallow it). |
418 if (port == 0 && Socket::GetPort(fd) == 65535) { | 389 if (port == 0 && Socket::GetPort(fd) == 65535) { |
419 // Don't close the socket until we have created a new socket, ensuring | 390 // Don't close the socket until we have created a new socket, ensuring |
420 // that we do not get the bad port number again. | 391 // that we do not get the bad port number again. |
421 intptr_t new_fd = CreateBindListen(addr, 0, backlog, v6_only); | 392 intptr_t new_fd = CreateBindListen(addr, 0, backlog, v6_only); |
422 int err = errno; | 393 int err = errno; |
423 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd)); | 394 VOID_TEMP_FAILURE_RETRY(close(fd)); |
424 errno = err; | 395 errno = err; |
425 return new_fd; | 396 return new_fd; |
426 } | 397 } |
427 | 398 |
428 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 399 if (listen(fd, backlog > 0 ? backlog : SOMAXCONN) != 0) { |
429 listen(fd, backlog > 0 ? backlog : SOMAXCONN)) != 0) { | 400 VOID_TEMP_FAILURE_RETRY(close(fd)); |
430 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd)); | |
431 return -1; | 401 return -1; |
432 } | 402 } |
433 | 403 |
434 return fd; | 404 return fd; |
435 } | 405 } |
436 | 406 |
437 | 407 |
438 static bool IsTemporaryAcceptError(int error) { | 408 static bool IsTemporaryAcceptError(int error) { |
439 // On Linux a number of protocol errors should be treated as EAGAIN. | 409 // On Linux a number of protocol errors should be treated as EAGAIN. |
440 // These are the ones for TCP/IP. | 410 // These are the ones for TCP/IP. |
441 return (error == EAGAIN) || (error == ENETDOWN) || (error == EPROTO) || | 411 return (error == EAGAIN) || (error == ENETDOWN) || (error == EPROTO) || |
442 (error == ENOPROTOOPT) || (error == EHOSTDOWN) || (error == ENONET) || | 412 (error == ENOPROTOOPT) || (error == EHOSTDOWN) || (error == ENONET) || |
443 (error == EHOSTUNREACH) || (error == EOPNOTSUPP) || | 413 (error == EHOSTUNREACH) || (error == EOPNOTSUPP) || |
444 (error == ENETUNREACH); | 414 (error == ENETUNREACH); |
445 } | 415 } |
446 | 416 |
447 | 417 |
448 intptr_t ServerSocket::Accept(intptr_t fd) { | 418 intptr_t ServerSocket::Accept(intptr_t fd) { |
449 intptr_t socket; | 419 intptr_t socket; |
450 struct sockaddr clientaddr; | 420 struct sockaddr clientaddr; |
451 socklen_t addrlen = sizeof(clientaddr); | 421 socklen_t addrlen = sizeof(clientaddr); |
452 socket = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(accept4( | 422 socket = TEMP_FAILURE_RETRY(accept4( |
453 fd, &clientaddr, &addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC)); | 423 fd, &clientaddr, &addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC)); |
454 if (socket == -1) { | 424 if (socket == -1) { |
455 if (IsTemporaryAcceptError(errno)) { | 425 if (IsTemporaryAcceptError(errno)) { |
456 // We need to signal to the caller that this is actually not an | 426 // We need to signal to the caller that this is actually not an |
457 // error. We got woken up from the poll on the listening socket, | 427 // error. We got woken up from the poll on the listening socket, |
458 // but there is no connection ready to be accepted. | 428 // but there is no connection ready to be accepted. |
459 ASSERT(kTemporaryFailure != -1); | 429 ASSERT(kTemporaryFailure != -1); |
460 socket = kTemporaryFailure; | 430 socket = kTemporaryFailure; |
461 } | 431 } |
462 } | 432 } |
463 return socket; | 433 return socket; |
464 } | 434 } |
465 | 435 |
466 | 436 |
467 void Socket::Close(intptr_t fd) { | 437 void Socket::Close(intptr_t fd) { |
468 ASSERT(fd >= 0); | 438 ASSERT(fd >= 0); |
469 int err = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd)); | 439 int err = TEMP_FAILURE_RETRY(close(fd)); |
470 if (err != 0) { | 440 if (err != 0) { |
471 const int kBufferSize = 1024; | 441 const int kBufferSize = 1024; |
472 char error_buf[kBufferSize]; | 442 char error_buf[kBufferSize]; |
473 Log::PrintErr("%s\n", strerror_r(errno, error_buf, kBufferSize)); | 443 Log::PrintErr("%s\n", strerror_r(errno, error_buf, kBufferSize)); |
474 } | 444 } |
475 } | 445 } |
476 | 446 |
477 | 447 |
478 bool Socket::GetNoDelay(intptr_t fd, bool* enabled) { | 448 bool Socket::GetNoDelay(intptr_t fd, bool* enabled) { |
479 int on; | 449 int on; |
480 socklen_t len = sizeof(on); | 450 socklen_t len = sizeof(on); |
481 int err = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getsockopt(fd, | 451 int err = getsockopt( |
482 IPPROTO_TCP, | 452 fd, IPPROTO_TCP, TCP_NODELAY, reinterpret_cast<void *>(&on), &len); |
483 TCP_NODELAY, | |
484 reinterpret_cast<void *>(&on), | |
485 &len)); | |
486 if (err == 0) { | 453 if (err == 0) { |
487 *enabled = on == 1; | 454 *enabled = on == 1; |
488 } | 455 } |
489 return err == 0; | 456 return err == 0; |
490 } | 457 } |
491 | 458 |
492 | 459 |
493 bool Socket::SetNoDelay(intptr_t fd, bool enabled) { | 460 bool Socket::SetNoDelay(intptr_t fd, bool enabled) { |
494 int on = enabled ? 1 : 0; | 461 int on = enabled ? 1 : 0; |
495 return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt(fd, | 462 return setsockopt(fd, |
496 IPPROTO_TCP, | 463 IPPROTO_TCP, |
497 TCP_NODELAY, | 464 TCP_NODELAY, |
498 reinterpret_cast<char *>(&on), | 465 reinterpret_cast<char *>(&on), |
499 sizeof(on))) == 0; | 466 sizeof(on)) == 0; |
500 } | 467 } |
501 | 468 |
502 | 469 |
503 bool Socket::GetMulticastLoop(intptr_t fd, intptr_t protocol, bool* enabled) { | 470 bool Socket::GetMulticastLoop(intptr_t fd, intptr_t protocol, bool* enabled) { |
504 uint8_t on; | 471 uint8_t on; |
505 socklen_t len = sizeof(on); | 472 socklen_t len = sizeof(on); |
506 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; | 473 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; |
507 int optname = protocol == SocketAddress::TYPE_IPV4 | 474 int optname = protocol == SocketAddress::TYPE_IPV4 |
508 ? IP_MULTICAST_LOOP : IPV6_MULTICAST_LOOP; | 475 ? IP_MULTICAST_LOOP : IPV6_MULTICAST_LOOP; |
509 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getsockopt(fd, | 476 if (getsockopt( |
510 level, | 477 fd, level, optname, reinterpret_cast<char *>(&on), &len) == 0) { |
511 optname, | |
512 reinterpret_cast<char *>(&on), | |
513 &len)) == 0) { | |
514 *enabled = (on == 1); | 478 *enabled = (on == 1); |
515 return true; | 479 return true; |
516 } | 480 } |
517 return false; | 481 return false; |
518 } | 482 } |
519 | 483 |
520 | 484 |
521 bool Socket::SetMulticastLoop(intptr_t fd, intptr_t protocol, bool enabled) { | 485 bool Socket::SetMulticastLoop(intptr_t fd, intptr_t protocol, bool enabled) { |
522 int on = enabled ? 1 : 0; | 486 int on = enabled ? 1 : 0; |
523 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; | 487 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; |
524 int optname = protocol == SocketAddress::TYPE_IPV4 | 488 int optname = protocol == SocketAddress::TYPE_IPV4 |
525 ? IP_MULTICAST_LOOP : IPV6_MULTICAST_LOOP; | 489 ? IP_MULTICAST_LOOP : IPV6_MULTICAST_LOOP; |
526 return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt(fd, | 490 return setsockopt( |
527 level, | 491 fd, level, optname, reinterpret_cast<char *>(&on), sizeof(on)) == 0; |
528 optname, | |
529 reinterpret_cast<char *>(&on), | |
530 sizeof(on))) == 0; | |
531 } | 492 } |
532 | 493 |
533 | 494 |
534 bool Socket::GetMulticastHops(intptr_t fd, intptr_t protocol, int* value) { | 495 bool Socket::GetMulticastHops(intptr_t fd, intptr_t protocol, int* value) { |
535 uint8_t v; | 496 uint8_t v; |
536 socklen_t len = sizeof(v); | 497 socklen_t len = sizeof(v); |
537 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; | 498 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; |
538 int optname = protocol == SocketAddress::TYPE_IPV4 | 499 int optname = protocol == SocketAddress::TYPE_IPV4 |
539 ? IP_MULTICAST_TTL : IPV6_MULTICAST_HOPS; | 500 ? IP_MULTICAST_TTL : IPV6_MULTICAST_HOPS; |
540 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getsockopt(fd, | 501 if (getsockopt(fd, level, optname, reinterpret_cast<char *>(&v), &len) == 0) { |
541 level, | |
542 optname, | |
543 reinterpret_cast<char *>(&v), | |
544 &len)) == 0) { | |
545 *value = v; | 502 *value = v; |
546 return true; | 503 return true; |
547 } | 504 } |
548 return false; | 505 return false; |
549 } | 506 } |
550 | 507 |
551 | 508 |
552 bool Socket::SetMulticastHops(intptr_t fd, intptr_t protocol, int value) { | 509 bool Socket::SetMulticastHops(intptr_t fd, intptr_t protocol, int value) { |
553 int v = value; | 510 int v = value; |
554 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; | 511 int level = protocol == SocketAddress::TYPE_IPV4 ? IPPROTO_IP : IPPROTO_IPV6; |
555 int optname = protocol == SocketAddress::TYPE_IPV4 | 512 int optname = protocol == SocketAddress::TYPE_IPV4 |
556 ? IP_MULTICAST_TTL : IPV6_MULTICAST_HOPS; | 513 ? IP_MULTICAST_TTL : IPV6_MULTICAST_HOPS; |
557 return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt(fd, | 514 return setsockopt( |
558 level, | 515 fd, level, optname, reinterpret_cast<char *>(&v), sizeof(v)) == 0; |
559 optname, | |
560 reinterpret_cast<char *>(&v), | |
561 sizeof(v))) == 0; | |
562 } | 516 } |
563 | 517 |
564 | 518 |
565 bool Socket::GetBroadcast(intptr_t fd, bool* enabled) { | 519 bool Socket::GetBroadcast(intptr_t fd, bool* enabled) { |
566 int on; | 520 int on; |
567 socklen_t len = sizeof(on); | 521 socklen_t len = sizeof(on); |
568 int err = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getsockopt(fd, | 522 int err = getsockopt( |
569 SOL_SOCKET, | 523 fd, SOL_SOCKET, SO_BROADCAST, reinterpret_cast<char *>(&on), &len); |
570 SO_BROADCAST, | |
571 reinterpret_cast<char *>(&on), | |
572 &len)); | |
573 if (err == 0) { | 524 if (err == 0) { |
574 *enabled = on == 1; | 525 *enabled = on == 1; |
575 } | 526 } |
576 return err == 0; | 527 return err == 0; |
577 } | 528 } |
578 | 529 |
579 | 530 |
580 bool Socket::SetBroadcast(intptr_t fd, bool enabled) { | 531 bool Socket::SetBroadcast(intptr_t fd, bool enabled) { |
581 int on = enabled ? 1 : 0; | 532 int on = enabled ? 1 : 0; |
582 return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt(fd, | 533 return setsockopt(fd, |
583 SOL_SOCKET, | 534 SOL_SOCKET, |
584 SO_BROADCAST, | 535 SO_BROADCAST, |
585 reinterpret_cast<char *>(&on), | 536 reinterpret_cast<char *>(&on), |
586 sizeof(on))) == 0; | 537 sizeof(on)) == 0; |
587 } | 538 } |
588 | 539 |
589 | 540 |
590 bool Socket::JoinMulticast( | 541 bool Socket::JoinMulticast( |
591 intptr_t fd, RawAddr* addr, RawAddr*, int interfaceIndex) { | 542 intptr_t fd, RawAddr* addr, RawAddr*, int interfaceIndex) { |
592 int proto = addr->addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; | 543 int proto = addr->addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; |
593 struct group_req mreq; | 544 struct group_req mreq; |
594 mreq.gr_interface = interfaceIndex; | 545 mreq.gr_interface = interfaceIndex; |
595 memmove(&mreq.gr_group, &addr->ss, SocketAddress::GetAddrLength(addr)); | 546 memmove(&mreq.gr_group, &addr->ss, SocketAddress::GetAddrLength(addr)); |
596 return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt( | 547 return setsockopt(fd, proto, MCAST_JOIN_GROUP, &mreq, sizeof(mreq)) == 0; |
597 fd, proto, MCAST_JOIN_GROUP, &mreq, sizeof(mreq))) == 0; | |
598 } | 548 } |
599 | 549 |
600 | 550 |
601 bool Socket::LeaveMulticast( | 551 bool Socket::LeaveMulticast( |
602 intptr_t fd, RawAddr* addr, RawAddr*, int interfaceIndex) { | 552 intptr_t fd, RawAddr* addr, RawAddr*, int interfaceIndex) { |
603 int proto = addr->addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; | 553 int proto = addr->addr.sa_family == AF_INET ? IPPROTO_IP : IPPROTO_IPV6; |
604 struct group_req mreq; | 554 struct group_req mreq; |
605 mreq.gr_interface = interfaceIndex; | 555 mreq.gr_interface = interfaceIndex; |
606 memmove(&mreq.gr_group, &addr->ss, SocketAddress::GetAddrLength(addr)); | 556 memmove(&mreq.gr_group, &addr->ss, SocketAddress::GetAddrLength(addr)); |
607 return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt( | 557 return setsockopt(fd, proto, MCAST_LEAVE_GROUP, &mreq, sizeof(mreq)) == 0; |
608 fd, proto, MCAST_LEAVE_GROUP, &mreq, sizeof(mreq))) == 0; | |
609 } | 558 } |
610 | 559 |
611 } // namespace bin | 560 } // namespace bin |
612 } // namespace dart | 561 } // namespace dart |
613 | 562 |
614 #endif // defined(TARGET_OS_LINUX) | 563 #endif // defined(TARGET_OS_LINUX) |
OLD | NEW |