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 |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
53 | 53 |
54 | 54 |
55 bool Socket::Initialize() { | 55 bool Socket::Initialize() { |
56 // Nothing to do on Linux. | 56 // Nothing to do on Linux. |
57 return true; | 57 return true; |
58 } | 58 } |
59 | 59 |
60 | 60 |
61 intptr_t Socket::Create(RawAddr addr) { | 61 intptr_t Socket::Create(RawAddr addr) { |
62 intptr_t fd; | 62 intptr_t fd; |
63 fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(socket(addr.ss.ss_family, SOCK_STREAM, | 63 fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(socket( |
64 0)); | 64 addr.ss.ss_family, SOCK_STREAM | SOCK_NONBLOCK | SOCK_CLOEXEC, 0)); |
65 if (fd < 0) { | 65 if (fd < 0) { |
66 const int kBufferSize = 1024; | 66 const int kBufferSize = 1024; |
67 char error_buf[kBufferSize]; | 67 char error_buf[kBufferSize]; |
68 Log::PrintErr("Error Create: %s\n", | 68 Log::PrintErr("Error Create: %s\n", |
69 strerror_r(errno, error_buf, kBufferSize)); | 69 strerror_r(errno, error_buf, kBufferSize)); |
70 return -1; | 70 return -1; |
71 } | 71 } |
72 | |
73 FDUtils::SetCloseOnExec(fd); | |
74 return fd; | 72 return fd; |
75 } | 73 } |
76 | 74 |
77 | 75 |
78 intptr_t Socket::Connect(intptr_t fd, RawAddr addr, const intptr_t port) { | 76 intptr_t Socket::Connect(intptr_t fd, RawAddr addr, const intptr_t port) { |
79 SocketAddress::SetAddrPort(&addr, port); | 77 SocketAddress::SetAddrPort(&addr, port); |
80 intptr_t result = TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 78 intptr_t result = TEMP_FAILURE_RETRY_BLOCK_SIGNALS( |
81 connect(fd, | 79 connect(fd, |
82 &addr.addr, | 80 &addr.addr, |
83 SocketAddress::GetAddrLength(&addr))); | 81 SocketAddress::GetAddrLength(&addr))); |
84 if (result == 0 || errno == EINPROGRESS) { | 82 if (result == 0 || errno == EINPROGRESS) { |
85 return fd; | 83 return fd; |
86 } | 84 } |
87 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd)); | 85 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd)); |
88 return -1; | 86 return -1; |
89 } | 87 } |
90 | 88 |
91 | 89 |
92 intptr_t Socket::CreateConnect(RawAddr addr, const intptr_t port) { | 90 intptr_t Socket::CreateConnect(RawAddr addr, const intptr_t port) { |
93 intptr_t fd = Socket::Create(addr); | 91 intptr_t fd = Socket::Create(addr); |
94 if (fd < 0) { | 92 if (fd < 0) { |
95 return fd; | 93 return fd; |
96 } | 94 } |
97 | |
98 Socket::SetNonBlocking(fd); | |
99 | |
100 return Socket::Connect(fd, addr, port); | 95 return Socket::Connect(fd, addr, port); |
101 } | 96 } |
102 | 97 |
103 | 98 |
104 intptr_t Socket::Available(intptr_t fd) { | 99 intptr_t Socket::Available(intptr_t fd) { |
105 return FDUtils::AvailableBytes(fd); | 100 return FDUtils::AvailableBytes(fd); |
106 } | 101 } |
107 | 102 |
108 | 103 |
109 int Socket::Read(intptr_t fd, void* buffer, intptr_t num_bytes) { | 104 int Socket::Read(intptr_t fd, void* buffer, intptr_t num_bytes) { |
(...skipping 198 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
308 result = inet_pton(AF_INET6, address, &addr->in6.sin6_addr); | 303 result = inet_pton(AF_INET6, address, &addr->in6.sin6_addr); |
309 } | 304 } |
310 return result == 1; | 305 return result == 1; |
311 } | 306 } |
312 | 307 |
313 | 308 |
314 intptr_t Socket::CreateBindDatagram( | 309 intptr_t Socket::CreateBindDatagram( |
315 RawAddr* addr, intptr_t port, bool reuseAddress) { | 310 RawAddr* addr, intptr_t port, bool reuseAddress) { |
316 intptr_t fd; | 311 intptr_t fd; |
317 | 312 |
318 fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 313 fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(socket( |
319 socket(addr->addr.sa_family, SOCK_DGRAM, IPPROTO_UDP)); | 314 addr->addr.sa_family, |
| 315 SOCK_DGRAM | SOCK_CLOEXEC | SOCK_NONBLOCK, |
| 316 IPPROTO_UDP)); |
320 if (fd < 0) return -1; | 317 if (fd < 0) return -1; |
321 | 318 |
322 FDUtils::SetCloseOnExec(fd); | |
323 | |
324 if (reuseAddress) { | 319 if (reuseAddress) { |
325 int optval = 1; | 320 int optval = 1; |
326 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 321 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS( |
327 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))); | 322 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))); |
328 } | 323 } |
329 | 324 |
330 SocketAddress::SetAddrPort(addr, port); | 325 SocketAddress::SetAddrPort(addr, port); |
331 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 326 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS( |
332 bind(fd, | 327 bind(fd, |
333 &addr->addr, | 328 &addr->addr, |
334 SocketAddress::GetAddrLength(addr))) < 0) { | 329 SocketAddress::GetAddrLength(addr))) < 0) { |
335 TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd)); | 330 TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd)); |
336 return -1; | 331 return -1; |
337 } | 332 } |
338 | |
339 Socket::SetNonBlocking(fd); | |
340 return fd; | 333 return fd; |
341 } | 334 } |
342 | 335 |
343 | 336 |
344 static bool ShouldIncludeIfaAddrs(struct ifaddrs* ifa, int lookup_family) { | 337 static bool ShouldIncludeIfaAddrs(struct ifaddrs* ifa, int lookup_family) { |
345 if (ifa->ifa_addr == NULL) { | 338 if (ifa->ifa_addr == NULL) { |
346 // OpenVPN's virtual device tun0. | 339 // OpenVPN's virtual device tun0. |
347 return false; | 340 return false; |
348 } | 341 } |
349 int family = ifa->ifa_addr->sa_family; | 342 int family = ifa->ifa_addr->sa_family; |
(...skipping 41 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
391 return addresses; | 384 return addresses; |
392 } | 385 } |
393 | 386 |
394 | 387 |
395 intptr_t ServerSocket::CreateBindListen(RawAddr addr, | 388 intptr_t ServerSocket::CreateBindListen(RawAddr addr, |
396 intptr_t port, | 389 intptr_t port, |
397 intptr_t backlog, | 390 intptr_t backlog, |
398 bool v6_only) { | 391 bool v6_only) { |
399 intptr_t fd; | 392 intptr_t fd; |
400 | 393 |
401 fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(socket(addr.ss.ss_family, SOCK_STREAM, | 394 fd = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(socket( |
402 0)); | 395 addr.ss.ss_family, SOCK_STREAM | SOCK_CLOEXEC | SOCK_NONBLOCK, 0)); |
403 if (fd < 0) return -1; | 396 if (fd < 0) return -1; |
404 | 397 |
405 FDUtils::SetCloseOnExec(fd); | |
406 | |
407 int optval = 1; | 398 int optval = 1; |
408 TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 399 TEMP_FAILURE_RETRY_BLOCK_SIGNALS( |
409 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))); | 400 setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))); |
410 | 401 |
411 if (addr.ss.ss_family == AF_INET6) { | 402 if (addr.ss.ss_family == AF_INET6) { |
412 optval = v6_only ? 1 : 0; | 403 optval = v6_only ? 1 : 0; |
413 TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 404 TEMP_FAILURE_RETRY_BLOCK_SIGNALS( |
414 setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval))); | 405 setsockopt(fd, IPPROTO_IPV6, IPV6_V6ONLY, &optval, sizeof(optval))); |
415 } | 406 } |
416 | 407 |
(...skipping 16 matching lines...) Expand all Loading... |
433 errno = err; | 424 errno = err; |
434 return new_fd; | 425 return new_fd; |
435 } | 426 } |
436 | 427 |
437 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS( | 428 if (TEMP_FAILURE_RETRY_BLOCK_SIGNALS( |
438 listen(fd, backlog > 0 ? backlog : SOMAXCONN)) != 0) { | 429 listen(fd, backlog > 0 ? backlog : SOMAXCONN)) != 0) { |
439 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd)); | 430 VOID_TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd)); |
440 return -1; | 431 return -1; |
441 } | 432 } |
442 | 433 |
443 Socket::SetNonBlocking(fd); | |
444 return fd; | 434 return fd; |
445 } | 435 } |
446 | 436 |
447 | 437 |
448 static bool IsTemporaryAcceptError(int error) { | 438 static bool IsTemporaryAcceptError(int error) { |
449 // On Linux a number of protocol errors should be treated as EAGAIN. | 439 // On Linux a number of protocol errors should be treated as EAGAIN. |
450 // These are the ones for TCP/IP. | 440 // These are the ones for TCP/IP. |
451 return (error == EAGAIN) || (error == ENETDOWN) || (error == EPROTO) || | 441 return (error == EAGAIN) || (error == ENETDOWN) || (error == EPROTO) || |
452 (error == ENOPROTOOPT) || (error == EHOSTDOWN) || (error == ENONET) || | 442 (error == ENOPROTOOPT) || (error == EHOSTDOWN) || (error == ENONET) || |
453 (error == EHOSTUNREACH) || (error == EOPNOTSUPP) || | 443 (error == EHOSTUNREACH) || (error == EOPNOTSUPP) || |
454 (error == ENETUNREACH); | 444 (error == ENETUNREACH); |
455 } | 445 } |
456 | 446 |
457 | 447 |
458 intptr_t ServerSocket::Accept(intptr_t fd) { | 448 intptr_t ServerSocket::Accept(intptr_t fd) { |
459 intptr_t socket; | 449 intptr_t socket; |
460 struct sockaddr clientaddr; | 450 struct sockaddr clientaddr; |
461 socklen_t addrlen = sizeof(clientaddr); | 451 socklen_t addrlen = sizeof(clientaddr); |
462 socket = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(accept(fd, &clientaddr, &addrlen)); | 452 socket = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(accept4( |
| 453 fd, &clientaddr, &addrlen, SOCK_NONBLOCK | SOCK_CLOEXEC)); |
463 if (socket == -1) { | 454 if (socket == -1) { |
464 if (IsTemporaryAcceptError(errno)) { | 455 if (IsTemporaryAcceptError(errno)) { |
465 // We need to signal to the caller that this is actually not an | 456 // We need to signal to the caller that this is actually not an |
466 // error. We got woken up from the poll on the listening socket, | 457 // error. We got woken up from the poll on the listening socket, |
467 // but there is no connection ready to be accepted. | 458 // but there is no connection ready to be accepted. |
468 ASSERT(kTemporaryFailure != -1); | 459 ASSERT(kTemporaryFailure != -1); |
469 socket = kTemporaryFailure; | 460 socket = kTemporaryFailure; |
470 } | 461 } |
471 } else { | |
472 Socket::SetNonBlocking(socket); | |
473 } | 462 } |
474 return socket; | 463 return socket; |
475 } | 464 } |
476 | 465 |
477 | 466 |
478 void Socket::Close(intptr_t fd) { | 467 void Socket::Close(intptr_t fd) { |
479 ASSERT(fd >= 0); | 468 ASSERT(fd >= 0); |
480 int err = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd)); | 469 int err = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(close(fd)); |
481 if (err != 0) { | 470 if (err != 0) { |
482 const int kBufferSize = 1024; | 471 const int kBufferSize = 1024; |
483 char error_buf[kBufferSize]; | 472 char error_buf[kBufferSize]; |
484 Log::PrintErr("%s\n", strerror_r(errno, error_buf, kBufferSize)); | 473 Log::PrintErr("%s\n", strerror_r(errno, error_buf, kBufferSize)); |
485 } | 474 } |
486 } | 475 } |
487 | 476 |
488 | 477 |
489 bool Socket::SetNonBlocking(intptr_t fd) { | |
490 return FDUtils::SetNonBlocking(fd); | |
491 } | |
492 | |
493 | |
494 bool Socket::SetBlocking(intptr_t fd) { | |
495 return FDUtils::SetBlocking(fd); | |
496 } | |
497 | |
498 | |
499 bool Socket::GetNoDelay(intptr_t fd, bool* enabled) { | 478 bool Socket::GetNoDelay(intptr_t fd, bool* enabled) { |
500 int on; | 479 int on; |
501 socklen_t len = sizeof(on); | 480 socklen_t len = sizeof(on); |
502 int err = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getsockopt(fd, | 481 int err = TEMP_FAILURE_RETRY_BLOCK_SIGNALS(getsockopt(fd, |
503 IPPROTO_TCP, | 482 IPPROTO_TCP, |
504 TCP_NODELAY, | 483 TCP_NODELAY, |
505 reinterpret_cast<void *>(&on), | 484 reinterpret_cast<void *>(&on), |
506 &len)); | 485 &len)); |
507 if (err == 0) { | 486 if (err == 0) { |
508 *enabled = on == 1; | 487 *enabled = on == 1; |
(...skipping 117 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
626 mreq.gr_interface = interfaceIndex; | 605 mreq.gr_interface = interfaceIndex; |
627 memmove(&mreq.gr_group, &addr->ss, SocketAddress::GetAddrLength(addr)); | 606 memmove(&mreq.gr_group, &addr->ss, SocketAddress::GetAddrLength(addr)); |
628 return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt( | 607 return TEMP_FAILURE_RETRY_BLOCK_SIGNALS(setsockopt( |
629 fd, proto, MCAST_LEAVE_GROUP, &mreq, sizeof(mreq))) == 0; | 608 fd, proto, MCAST_LEAVE_GROUP, &mreq, sizeof(mreq))) == 0; |
630 } | 609 } |
631 | 610 |
632 } // namespace bin | 611 } // namespace bin |
633 } // namespace dart | 612 } // namespace dart |
634 | 613 |
635 #endif // defined(TARGET_OS_LINUX) | 614 #endif // defined(TARGET_OS_LINUX) |
OLD | NEW |