コード例 #1
0
ファイル: poll_socket.cpp プロジェクト: GrovoLearning/mesos
Future<std::shared_ptr<SocketImpl>> PollSocketImpl::accept()
{
  // Need to hold a copy of `this` so that the underlying socket
  // doesn't end up getting reused before we return from the call to
  // `io::poll` and end up accepting a socket incorrectly.
  auto self = shared(this);

  Try<Address> address = network::address(get());
  if (address.isError()) {
    return Failure("Failed to get address: " + address.error());
  }

  int family = 0;
  if (address->family() == Address::Family::INET4) {
    family = AF_INET;
  } else if (address->family() == Address::Family::INET6) {
    family = AF_INET6;
  } else {
    return Failure("Unsupported address family. Windows only supports IP.");
  }

  Try<int_fd> accept_socket_ = net::socket(family, SOCK_STREAM, 0);
  if (accept_socket_.isError()) {
    return Failure(accept_socket_.error());
  }

  int_fd accept_socket = accept_socket_.get();

  return windows::accept(self->get(), accept_socket)
    .onAny([accept_socket](const Future<Nothing> future) {
      if (!future.isReady()) {
        os::close(accept_socket);
      }
    })
    .then([self, accept_socket]() -> Future<std::shared_ptr<SocketImpl>> {
      SOCKET listen = self->get();

      // Inherit from the listening socket.
      int res = ::setsockopt(
          accept_socket,
          SOL_SOCKET,
          SO_UPDATE_ACCEPT_CONTEXT,
          reinterpret_cast<char*>(&listen),
          sizeof(listen));

      if (res != 0) {
        const WindowsError error;
        os::close(accept_socket);
        return Failure("Failed to set accepted socket: " + error.message);
      }

      // Disable Nagle algorithm, since we care about latency more than
      // throughput. See https://en.wikipedia.org/wiki/Nagle%27s_algorithm
      // for more info.
      const int on = 1;
      res = ::setsockopt(
          accept_socket,
          SOL_TCP,
          TCP_NODELAY,
          reinterpret_cast<const char*>(&on),
          sizeof(on));

      if (res != 0) {
        const WindowsError error;
        os::close(accept_socket);
        return Failure(
            "Failed to turn off the Nagle algorithm: " + error.message);
      }

      Try<Nothing> error = io::prepare_async(accept_socket);
      if (error.isError()) {
        os::close(accept_socket);
        return Failure(
            "Failed to set socket for asynchronous IO: " + error.error());
      }

      Try<std::shared_ptr<SocketImpl>> impl = create(accept_socket);
      if (impl.isError()) {
        os::close(accept_socket);
        return Failure("Failed to create socket: " + impl.error());
      }

      return impl.get();
    });
}