int win_iocp_socket_service_base::start_connect_op()

in demo_example/asio/asio/detail/impl/win_iocp_socket_service_base.ipp [609:678]


int win_iocp_socket_service_base::start_connect_op(
    win_iocp_socket_service_base::base_implementation_type& impl,
    int family, int type, const socket_addr_type* addr, std::size_t addrlen,
    win_iocp_socket_connect_op_base* op, operation* iocp_op)
{
  // If ConnectEx is available, use that.
  if (family == ASIO_OS_DEF(AF_INET)
      || family == ASIO_OS_DEF(AF_INET6))
  {
    if (connect_ex_fn connect_ex = get_connect_ex(impl, type))
    {
      union address_union
      {
        socket_addr_type base;
        sockaddr_in4_type v4;
        sockaddr_in6_type v6;
      } a;

      using namespace std; // For memset.
      memset(&a, 0, sizeof(a));
      a.base.sa_family = family;

      socket_ops::bind(impl.socket_, &a.base,
          family == ASIO_OS_DEF(AF_INET)
          ? sizeof(a.v4) : sizeof(a.v6), op->ec_);
      if (op->ec_ && op->ec_ != asio::error::invalid_argument)
      {
        iocp_service_.post_immediate_completion(op, false);
        return -1;
      }

      op->connect_ex_ = true;
      update_cancellation_thread_id(impl);
      iocp_service_.work_started();

      BOOL result = connect_ex(impl.socket_,
          addr, static_cast<int>(addrlen), 0, 0, 0, iocp_op);
      DWORD last_error = ::WSAGetLastError();
      if (!result && last_error != WSA_IO_PENDING)
        iocp_service_.on_completion(iocp_op, last_error);
      else
        iocp_service_.on_pending(iocp_op);
      return -1;
    }
  }

  // Otherwise, fall back to a reactor-based implementation.
  select_reactor& r = get_reactor();
  update_cancellation_thread_id(impl);

  if ((impl.state_ & socket_ops::non_blocking) != 0
      || socket_ops::set_internal_non_blocking(
        impl.socket_, impl.state_, true, op->ec_))
  {
    if (socket_ops::connect(impl.socket_, addr, addrlen, op->ec_) != 0)
    {
      if (op->ec_ == asio::error::in_progress
          || op->ec_ == asio::error::would_block)
      {
        op->ec_ = asio::error_code();
        r.start_op(select_reactor::connect_op, impl.socket_,
            impl.reactor_data_, op, false, false);
        return select_reactor::connect_op;
      }
    }
  }

  r.post_immediate_completion(op, false);
  return -1;
}