| 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 |