| 51 | |
| 52 | |
| 53 | Future<std::shared_ptr<SocketImpl>> PollSocketImpl::accept() |
| 54 | { |
| 55 | // Need to hold a copy of `this` so that we can detect if the underlying |
| 56 | // socket has changed (i.e. closed) before we return from `io::poll`. |
| 57 | std::weak_ptr<SocketImpl> weak_self(shared(this)); |
| 58 | |
| 59 | return io::poll(get(), io::READ) |
| 60 | .then([weak_self]() -> Future<std::shared_ptr<SocketImpl>> { |
| 61 | std::shared_ptr<SocketImpl> self(weak_self.lock()); |
| 62 | if (self == nullptr) { |
| 63 | return Failure("Socket destroyed while accepting"); |
| 64 | } |
| 65 | |
| 66 | Try<int_fd> accepted = network::accept(self->get()); |
| 67 | if (accepted.isError()) { |
| 68 | return Failure(accepted.error()); |
| 69 | } |
| 70 | |
| 71 | int_fd s = accepted.get(); |
| 72 | Try<Nothing> nonblock = os::nonblock(s); |
| 73 | if (nonblock.isError()) { |
| 74 | os::close(s); |
| 75 | return Failure("Failed to accept, nonblock: " + nonblock.error()); |
| 76 | } |
| 77 | |
| 78 | Try<Nothing> cloexec = os::cloexec(s); |
| 79 | if (cloexec.isError()) { |
| 80 | os::close(s); |
| 81 | return Failure("Failed to accept, cloexec: " + cloexec.error()); |
| 82 | } |
| 83 | |
| 84 | Try<Address> address = network::address(s); |
| 85 | if (address.isError()) { |
| 86 | os::close(s); |
| 87 | return Failure("Failed to get address: " + address.error()); |
| 88 | } |
| 89 | |
| 90 | // Turn off Nagle (TCP_NODELAY) so pipelined requests don't wait. |
| 91 | // NOTE: We cast to `char*` here because the function prototypes |
| 92 | // on Windows use `char*` instead of `void*`. |
| 93 | if (address->family() == Address::Family::INET4 || |
| 94 | address->family() == Address::Family::INET6) { |
| 95 | int on = 1; |
| 96 | if (::setsockopt( |
| 97 | s, |
| 98 | SOL_TCP, |
| 99 | TCP_NODELAY, |
| 100 | reinterpret_cast<const char*>(&on), |
| 101 | sizeof(on)) < 0) { |
| 102 | const string error = os::strerror(errno); |
| 103 | os::close(s); |
| 104 | return Failure( |
| 105 | "Failed to turn off the Nagle algorithm: " + stringify(error)); |
| 106 | } |
| 107 | } |
| 108 | |
| 109 | Try<std::shared_ptr<SocketImpl>> impl = create(s); |
| 110 | if (impl.isError()) { |