void Device::connectAsInitiator()

in gloo/transport/uv/device.cc [361:414]


void Device::connectAsInitiator(
    const Address& remote,
    std::chrono::milliseconds timeout,
    ConnectCallback fn) {
  defer([=] {
    auto tcp = loop_->resource<libuv::TCP>();
    auto timer = loop_->resource<libuv::Timer>();

    // Enable TCP_NODELAY, which disables Nagle's algorithm.
    tcp->noDelay(true);

    // Call callback with error if an error event fired.
    // In nominal operation, this listener will NOT fire.
    // It must be cleared upon success.
    auto errorListener = tcp->once<libuv::ErrorEvent>(
        [=](const libuv::ErrorEvent& event, libuv::TCP& handle) {
          // If a request against this handle was canceled,
          // it must have been due to the timeout firing.
          // The timeout will call the callback with the
          // UV_ETIMEDOUT status and close the handle.
          if (event.code() != UV_ECANCELED) {
            fn(nullptr, event);
            handle.close();
            timer->close();
          }
        });

    // Write sequence number as soon as the connection is made.
    // In nominal operation, this listener will fire at least once.
    tcp->once<libuv::ConnectEvent>(
        [remote](const libuv::ConnectEvent&, libuv::TCP& handle) {
          handle.write(remote.getSeq());
        });

    // Call callback with success if the sequence number was written.
    // In nominal operation, this listener will fire at least once.
    tcp->once<libuv::WriteEvent>(
        [=](const libuv::WriteEvent&, libuv::TCP& handle) {
          handle.erase(errorListener);
          timer->close();
          fn(handle.shared_from_this(), libuv::ErrorEvent(0));
        });

    timer->once<libuv::TimerEvent>(
        [=](const libuv::TimerEvent&, libuv::Timer& handle) {
          fn(nullptr, libuv::ErrorEvent(ETIMEDOUT));
          tcp->close();
          handle.close();
        });

    timer->start(timeout);
    tcp->connect((const sockaddr&)remote.getSockaddr());
  });
}