0
0
mirror of https://github.com/OpenVPN/openvpn3.git synced 2024-09-19 19:52:15 +02:00

support async connect in dco-win

Signed-off-by: Heiko Hund <heiko@openvpn.net>
This commit is contained in:
Heiko Hund 2021-04-01 17:00:00 +02:00 committed by David Sommerseth
parent 32a32cf04c
commit ef45b80a97
No known key found for this signature in database
GPG Key ID: 86CF944C9671FDF2

View File

@ -160,11 +160,12 @@ protected:
);
config->transport.remote_list->get_endpoint(endpoint_);
if (add_peer_()) {
transport_parent->transport_connecting();
queue_read_();
} else
stop_();
add_peer_([self=Ptr(this)]() {
if (!self->halt) {
self->transport_parent->transport_connecting();
self->queue_read_();
}
});
}
void queue_read_() {
@ -210,7 +211,8 @@ protected:
}
}
bool add_peer_() {
template <typename CB>
void add_peer_(CB complete) {
OVPN_NEW_PEER peer = {};
peer.Proto = proto_.is_tcp() ? OVPN_PROTO_TCP : OVPN_PROTO_UDP;
@ -232,20 +234,33 @@ protected:
peer.Local.Addr6.sin6_port = peer.Remote.Addr6.sin6_port;
}
// TODO: Driver will return better suiting error in the future
const DWORD connect_timeout_error_code = ERROR_SEM_TIMEOUT;
const DWORD ec = dco_ioctl_(OVPN_IOCTL_NEW_PEER, &peer, sizeof(peer),
connect_timeout_error_code);
if (ec != ERROR_SUCCESS) {
openvpn_io::windows::overlapped_ptr ov {io_context,
[self=Ptr(this), complete](const openvpn_io::error_code& ec,
std::size_t len) {
if (self->halt)
return;
if (!ec)
complete();
else {
std::ostringstream errmsg;
errmsg << "TCP connection error: " << ec.message();
self->config->transport.stats->error(Error::TCP_CONNECT_ERROR);
self->transport_parent->transport_error(Error::UNDEF, errmsg.str());
self->stop_();
}
}
};
const DWORD ec = dco_ioctl_(OVPN_IOCTL_NEW_PEER, &peer, sizeof(peer), &ov);
if (ec == ERROR_SUCCESS)
complete();
else if (ec != ERROR_IO_PENDING) {
std::ostringstream errmsg;
errmsg << "failed to connect '" << server_host << "' " << endpoint_;
config->transport.stats->error(Error::TCP_CONNECT_ERROR);
transport_parent->transport_error(Error::UNDEF, errmsg.str());
return false;
stop_();
}
return true;
}
void add_keepalive_() {
@ -313,7 +328,7 @@ protected:
void swap_keys_() { dco_ioctl_(OVPN_IOCTL_SWAP_KEYS); }
DWORD dco_ioctl_(DWORD code, LPVOID data = NULL, DWORD size = 0,
const DWORD non_fatal_error = ERROR_SUCCESS) {
openvpn_io::windows::overlapped_ptr* ov = nullptr) {
static const std::map<const DWORD, const char*> code_str {
{ OVPN_IOCTL_NEW_PEER, "OVPN_IOCTL_NEW_PEER" },
{ OVPN_IOCTL_GET_STATS, "OVPN_IOCTL_GET_STATS" },
@ -324,10 +339,17 @@ protected:
};
HANDLE th(handle_->native_handle());
if (!DeviceIoControl(th, code, data, size, NULL, 0, NULL, NULL)) {
LPOVERLAPPED ov_ = (ov ? ov->get() : NULL);
if (!DeviceIoControl(th, code, data, size, NULL, 0, NULL, ov_)) {
const DWORD error_code = GetLastError();
if (error_code == non_fatal_error)
return error_code;
if (ov) {
if (error_code == ERROR_IO_PENDING) {
ov->release();
return error_code;
}
openvpn_io::error_code error(error_code, openvpn_io::system_category());
ov->complete(error, 0);
}
OPENVPN_LOG("DeviceIoControl(" << code_str.at(code) << ")"
<< " failed with code " << error_code);