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;
}