| 49 | |
| 50 | |
| 51 | Future<std::shared_ptr<SocketImpl>> PollSocketImpl::accept() |
| 52 | { |
| 53 | // Need to hold a copy of `this` so that the underlying socket |
| 54 | // doesn't end up getting reused before we return from the call to |
| 55 | // `io::poll` and end up accepting a socket incorrectly. |
| 56 | auto self = shared(this); |
| 57 | |
| 58 | Try<Address> address = network::address(get()); |
| 59 | if (address.isError()) { |
| 60 | return Failure("Failed to get address: " + address.error()); |
| 61 | } |
| 62 | |
| 63 | int family = 0; |
| 64 | if (address->family() == Address::Family::INET4) { |
| 65 | family = AF_INET; |
| 66 | } else if (address->family() == Address::Family::INET6) { |
| 67 | family = AF_INET6; |
| 68 | } else { |
| 69 | return Failure("Unsupported address family. Windows only supports IP."); |
| 70 | } |
| 71 | |
| 72 | Try<int_fd> accept_socket_ = net::socket(family, SOCK_STREAM, 0); |
| 73 | if (accept_socket_.isError()) { |
| 74 | return Failure(accept_socket_.error()); |
| 75 | } |
| 76 | |
| 77 | int_fd accept_socket = accept_socket_.get(); |
| 78 | |
| 79 | return windows::accept(self->get(), accept_socket) |
| 80 | .onAny([accept_socket](const Future<Nothing> future) { |
| 81 | if (!future.isReady()) { |
| 82 | os::close(accept_socket); |
| 83 | } |
| 84 | }) |
| 85 | .then([self, accept_socket]() -> Future<std::shared_ptr<SocketImpl>> { |
| 86 | SOCKET listen = self->get(); |
| 87 | |
| 88 | // Inherit from the listening socket. |
| 89 | int res = ::setsockopt( |
| 90 | accept_socket, |
| 91 | SOL_SOCKET, |
| 92 | SO_UPDATE_ACCEPT_CONTEXT, |
| 93 | reinterpret_cast<char*>(&listen), |
| 94 | sizeof(listen)); |
| 95 | |
| 96 | if (res != 0) { |
| 97 | const WindowsError error; |
| 98 | os::close(accept_socket); |
| 99 | return Failure("Failed to set accepted socket: " + error.message); |
| 100 | } |
| 101 | |
| 102 | // Disable Nagle algorithm, since we care about latency more than |
| 103 | // throughput. See https://en.wikipedia.org/wiki/Nagle%27s_algorithm |
| 104 | // for more info. |
| 105 | const int on = 1; |
| 106 | res = ::setsockopt( |
| 107 | accept_socket, |
| 108 | SOL_TCP, |