Update yasio to latest

This commit is contained in:
halx99 2023-01-10 22:19:30 +08:00
parent b032ba2f56
commit 1464009e63
12 changed files with 193 additions and 130 deletions

View File

@ -238,7 +238,7 @@
## yasio ## yasio
- [![Upstream](https://img.shields.io/github/v/release/yasio/yasio?label=Upstream)](https://github.com/yasio/yasio) - [![Upstream](https://img.shields.io/github/v/release/yasio/yasio?label=Upstream)](https://github.com/yasio/yasio)
- Version: 3.39.6 - Version: git 3.39.7-2e7723f
- License: MIT WITH Anti-996 - License: MIT WITH Anti-996
## zlib ## zlib

View File

@ -227,6 +227,12 @@ SOFTWARE.
// https://github.com/c-ares/c-ares/pull/148 // https://github.com/c-ares/c-ares/pull/148
#define YASIO_FALLBACK_NAME_SERVERS "8.8.8.8,223.5.5.5,114.114.114.114" #define YASIO_FALLBACK_NAME_SERVERS "8.8.8.8,223.5.5.5,114.114.114.114"
// Since ubuntu 16.04, the /etc/resolv.conf control by systemd-resolved service,
// and the preferred non loopback name server was store to /run/systemd/resolve/resolv.conf
// refer to: https://unix.stackexchange.com/questions/612416/why-does-etc-resolv-conf-point-at-127-0-0-53
#define YASIO_SYSTEMD_RESOLV_PATH "/run/systemd/resolve/resolv.conf"
#define YASIO_SYSTEMD_RESOLV_PATH_LEN (sizeof(YASIO_SYSTEMD_RESOLV_PATH) - 1)
// The yasio ssl client PIN for server to recognize // The yasio ssl client PIN for server to recognize
#define YASIO_SSL_PIN "yasio_ssl_client" #define YASIO_SSL_PIN "yasio_ssl_client"
#define YASIO_SSL_PIN_LEN (sizeof(YASIO_SSL_PIN) - 1) #define YASIO_SSL_PIN_LEN (sizeof(YASIO_SSL_PIN) - 1)

View File

@ -62,13 +62,20 @@ YASIO__DECL ssl_ctx_st* yssl_ctx_new(const yssl_options& opts)
int authmode = MBEDTLS_SSL_VERIFY_OPTIONAL; int authmode = MBEDTLS_SSL_VERIFY_OPTIONAL;
if (yasio__valid_str(opts.crtfile_)) // the cafile_ must be full path if (yasio__valid_str(opts.crtfile_)) // the cafile_ must be full path
{ {
if ((ret = ::mbedtls_x509_crt_parse_file(&ctx->cert, opts.crtfile_)) == 0) int fail_count = 0;
authmode = MBEDTLS_SSL_VERIFY_REQUIRED; yssl_splitpath(opts.crtfile_, [&](char* first, char* last) {
else yssl_split_term null_term(last);
if ((ret = ::mbedtls_x509_crt_parse_file(&ctx->cert, first)) != 0)
{ {
++fail_count;
YASIO_LOG("mbedtls_x509_crt_parse_file with ret=-0x%x", (unsigned int)-ret); YASIO_LOG("mbedtls_x509_crt_parse_file with ret=-0x%x", (unsigned int)-ret);
break;
} }
return !!ret;
});
if (!fail_count)
authmode = MBEDTLS_SSL_VERIFY_REQUIRED;
} }
if (opts.client) if (opts.client)
@ -127,6 +134,7 @@ YASIO__DECL ssl_st* yssl_new(ssl_ctx_st* ctx, int fd, const char* hostname, bool
// ssl_set_fd // ssl_set_fd
ssl->bio.fd = fd; ssl->bio.fd = fd;
::mbedtls_ssl_set_bio(ssl, &ssl->bio, ::mbedtls_net_send, ::mbedtls_net_recv, nullptr /* rev_timeout() */); ::mbedtls_ssl_set_bio(ssl, &ssl->bio, ::mbedtls_net_send, ::mbedtls_net_recv, nullptr /* rev_timeout() */);
if (client)
::mbedtls_ssl_set_hostname(ssl, hostname); ::mbedtls_ssl_set_hostname(ssl, hostname);
return ssl; return ssl;
} }

View File

@ -47,9 +47,29 @@ YASIO__DECL ssl_ctx_st* yssl_ctx_new(const yssl_options& opts)
if (opts.client) if (opts.client)
{ {
int fail_count = -1;
if (yasio__valid_str(opts.crtfile_)) if (yasio__valid_str(opts.crtfile_))
{ {
if (::SSL_CTX_load_verify_locations(ctx, opts.crtfile_, nullptr) == 1) fail_count = 0;
yssl_splitpath(opts.crtfile_, [&](char* first, char* last) {
yssl_split_term null_term(last);
# if defined(OPENSSL_VERSION_MAJOR) && (OPENSSL_VERSION_MAJOR >= 3)
/* OpenSSL 3.0.0 has deprecated SSL_CTX_load_verify_locations */
bool ok = ::SSL_CTX_load_verify_file(ctx, first) == 1;
# else
bool ok = ::SSL_CTX_load_verify_locations(ctx, first, nullptr) == 1;
# endif
if (!ok)
{
++fail_count;
YASIO_LOG("[global] load ca certifaction file failed!");
}
return !ok;
});
}
if (!fail_count)
{ {
::SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, ::SSL_CTX_get_verify_callback(ctx)); ::SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER, ::SSL_CTX_get_verify_callback(ctx));
# if OPENSSL_VERSION_NUMBER >= 0x10101000L # if OPENSSL_VERSION_NUMBER >= 0x10101000L
@ -60,14 +80,11 @@ YASIO__DECL ssl_ctx_st* yssl_ctx_new(const yssl_options& opts)
trust-anchors, in the same way as self-signed root CA certificates trust-anchors, in the same way as self-signed root CA certificates
are. This allows users to verify servers using the intermediate cert are. This allows users to verify servers using the intermediate cert
only, instead of needing the whole chain. */ only, instead of needing the whole chain. */
X509_STORE_set_flags(SSL_CTX_get_cert_store(ctx), X509_V_FLAG_PARTIAL_CHAIN); ::X509_STORE_set_flags(::SSL_CTX_get_cert_store(ctx), X509_V_FLAG_PARTIAL_CHAIN);
# endif # endif
} }
else else
YASIO_LOG("[global] load ca certifaction file failed!"); ::SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, nullptr);
}
else
SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, nullptr);
} }
else else
{ {

View File

@ -10,6 +10,7 @@
#pragma once #pragma once
#include <vector> #include <vector>
#include <chrono>
#include "yasio/detail/socket.hpp" #include "yasio/detail/socket.hpp"
namespace yasio namespace yasio
@ -38,7 +39,7 @@ public:
int poll_io(int waitd_ms) int poll_io(int waitd_ms)
{ {
timeval waitd_tv = {(decltype(timeval::tv_sec))(waitd_ms / 1000), (decltype(timeval::tv_usec))(waitd_ms % 1000)}; timeval waitd_tv = {(decltype(timeval::tv_sec))(waitd_ms / std::milli::den), (decltype(timeval::tv_usec))(waitd_ms % std::milli::den)};
return ::select(this->max_descriptor_, &(fd_set_[read_op]), &(fd_set_[write_op]), nullptr, &waitd_tv); return ::select(this->max_descriptor_, &(fd_set_[read_op]), &(fd_set_[write_op]), nullptr, &waitd_tv);
} }

View File

@ -1,55 +0,0 @@
//////////////////////////////////////////////////////////////////////////////////////////
// A multi-platform support c++11 library with focus on asynchronous socket I/O for any
// client application.
//////////////////////////////////////////////////////////////////////////////////////////
//
// detail/signal_blocker.hpp
// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
//
// Copyright (c) 2012-2023 HALX99 (halx99 at live dot com)
#pragma once
#include "yasio/compiler/feature_test.hpp"
#if !defined(_WIN32)
#include <pthread.h>
#include <signal.h>
#endif
namespace yasio
{
YASIO__NS_INLINE
namespace inet
{
#if defined(_WIN32)
class signal_blocker {};
#else
class signal_blocker {
public:
// Constructor blocks all signals for the calling thread.
signal_blocker() : blocked_(false)
{
sigset_t new_mask;
sigfillset(&new_mask);
blocked_ = (pthread_sigmask(SIG_BLOCK, &new_mask, &old_mask_) == 0);
}
// Destructor restores the previous signal mask.
~signal_blocker()
{
if (blocked_)
pthread_sigmask(SIG_SETMASK, &old_mask_, 0);
}
private:
// Have signals been blocked.
bool blocked_;
// The previous signal mask.
sigset_t old_mask_;
};
#endif
} // namespace inet
} // namespace yasio

View File

@ -58,8 +58,8 @@ struct ssl_st : public mbedtls_ssl_context {
#if defined(YASIO_SSL_BACKEND) #if defined(YASIO_SSL_BACKEND)
struct yssl_options { struct yssl_options {
const char* crtfile_; char* crtfile_;
const char* keyfile_; char* keyfile_;
bool client; bool client;
}; };
@ -87,7 +87,50 @@ YASIO__DECL int yssl_read(ssl_st* ssl, void* data, size_t len, int& err);
/////////////////////////////////////////////////////////////////// ///////////////////////////////////////////////////////////////////
// --- Implement common yasio ssl api with different ssl backends // --- Implement common yasio ssl api with different ssl backends
#define yasio__valid_str(str) (str && *str) #define yasio__valid_str(cstr) (cstr && *cstr)
#define yasio__c_str(str) (!str.empty() ? &str.front() : nullptr)
/* private use for split cert files */
template <typename _Fty>
inline bool yssl_splitpath(char* str, _Fty&& func)
{
auto _Start = str; // the start of every string
auto _Ptr = str; // source string iterator
bool aborted = false;
while ((_Ptr = strchr(_Ptr, ',')))
{
if (_Start <= _Ptr)
{
if ((aborted = func(_Start, _Ptr)))
break;
}
_Start = _Ptr + 1;
++_Ptr;
}
if (!aborted)
aborted = func(_Start, nullptr); // last one
return aborted;
}
struct yssl_split_term {
yssl_split_term(char* end)
{
if (end) {
this->val_ = *end;
*end = '\0';
this->end_ = end;
}
}
~yssl_split_term()
{
if (this->end_)
*this->end_ = this->val_;
}
private:
char* end_ = nullptr;
char val_ = '\0';
};
#if YASIO_SSL_BACKEND == 1 // openssl #if YASIO_SSL_BACKEND == 1 // openssl
# include "yasio/detail/openssl.inl" # include "yasio/detail/openssl.inl"

View File

@ -28,6 +28,7 @@ SOFTWARE.
#ifndef YASIO__UTILS_HPP #ifndef YASIO__UTILS_HPP
#define YASIO__UTILS_HPP #define YASIO__UTILS_HPP
#include <assert.h> #include <assert.h>
#include <sys/stat.h>
#include <chrono> #include <chrono>
#include <algorithm> #include <algorithm>
#include "yasio/compiler/feature_test.hpp" #include "yasio/compiler/feature_test.hpp"
@ -40,18 +41,21 @@ typedef std::chrono::high_resolution_clock steady_clock_t;
typedef std::chrono::system_clock system_clock_t; typedef std::chrono::system_clock system_clock_t;
// The high precision nano seconds timestamp since epoch // The high precision nano seconds timestamp since epoch
template <typename _Ty = steady_clock_t> inline highp_time_t xhighp_clock() template <typename _Ty = steady_clock_t>
inline highp_time_t xhighp_clock()
{ {
auto duration = _Ty::now().time_since_epoch(); auto duration = _Ty::now().time_since_epoch();
return std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count(); return std::chrono::duration_cast<std::chrono::nanoseconds>(duration).count();
} }
// The high precision micro seconds timestamp since epoch // The high precision micro seconds timestamp since epoch
template <typename _Ty = steady_clock_t> inline highp_time_t highp_clock() template <typename _Ty = steady_clock_t>
inline highp_time_t highp_clock()
{ {
return xhighp_clock<_Ty>() / std::milli::den; return xhighp_clock<_Ty>() / std::milli::den;
} }
// The normal precision milli seconds timestamp since epoch // The normal precision milli seconds timestamp since epoch
template <typename _Ty = steady_clock_t> inline highp_time_t clock() template <typename _Ty = steady_clock_t>
inline highp_time_t clock()
{ {
return xhighp_clock<_Ty>() / std::micro::den; return xhighp_clock<_Ty>() / std::micro::den;
} }
@ -63,14 +67,26 @@ inline highp_time_t time_now() { return ::time(nullptr); }
#if YASIO__HAS_CXX17 #if YASIO__HAS_CXX17
using std::clamp; using std::clamp;
#else #else
template <typename _Ty> const _Ty& clamp(const _Ty& v, const _Ty& lo, const _Ty& hi) template <typename _Ty>
const _Ty& clamp(const _Ty& v, const _Ty& lo, const _Ty& hi)
{ {
assert(!(hi < lo)); assert(!(hi < lo));
return v < lo ? lo : hi < v ? hi : v; return v < lo ? lo : hi < v ? hi : v;
} }
#endif #endif
template <typename _Ty> inline void invoke_dtor(_Ty* p) { p->~_Ty(); } template <typename _Ty>
inline void invoke_dtor(_Ty* p)
{
p->~_Ty();
}
inline bool is_regular_file(const char* path)
{
struct stat st;
return (::stat(path, &st) == 0) && (st.st_mode & S_IFREG);
}
} // namespace yasio } // namespace yasio
#endif #endif

View File

@ -384,7 +384,26 @@ xxsocket& xxsocket::swap(xxsocket& rhs)
bool xxsocket::open(int af, int type, int protocol) bool xxsocket::open(int af, int type, int protocol)
{ {
if (invalid_socket == this->fd) if (invalid_socket == this->fd)
{
# if defined(_WIN32)
this->fd = ::socket(af, type, protocol); this->fd = ::socket(af, type, protocol);
//socket_native_type s = ::WSASocketW(af, type, protocol, 0, 0, WSA_FLAG_OVERLAPPED);
////get_last_error(ec, s == invalid_socket);
//if (s == invalid_socket)
// return false;
//this->fd = s;
//if (af == ASIO_OS_DEF(AF_INET6))
//{
// // Try to enable the POSIX default behaviour of having IPV6_V6ONLY set to
// // false. This will only succeed on Windows Vista and later versions of
// // Windows, where a dual-stack IPv4/v6 implementation is available.
// DWORD optval = 0;
// ::setsockopt(s, IPPROTO_IPV6, IPV6_V6ONLY, reinterpret_cast<const char*>(&optval), sizeof(optval));
//}
#else
this->fd = ::socket(af, type, protocol);
#endif
}
return is_open(); return is_open();
} }

View File

@ -62,7 +62,7 @@ namespace ip
{ {
#pragma pack(push, 1) #pragma pack(push, 1)
// ip packet // ip packet
struct ip_header { struct ip_hdr_st {
// header size; 5+ // header size; 5+
unsigned char header_length : 4; unsigned char header_length : 4;
@ -106,7 +106,7 @@ struct ip_header {
unsigned char protocol; // TCP / UDP / Other unsigned char protocol; // TCP / UDP / Other
// check header of IP-PACKET 's correctness. // check header of IP-PACKET 's correctness.
unsigned short checksum; unsigned short sum;
typedef union { typedef union {
unsigned int value; unsigned int value;
@ -122,7 +122,7 @@ struct ip_header {
dotted_decimal_t dst_ip; dotted_decimal_t dst_ip;
}; };
struct psd_header { struct psd_hdr_st {
unsigned long src_addr; unsigned long src_addr;
unsigned long dst_addr; unsigned long dst_addr;
char mbz; char mbz;
@ -130,7 +130,7 @@ struct psd_header {
unsigned short tcp_length; unsigned short tcp_length;
}; };
struct tcp_header { struct tcp_hdr_st {
unsigned short src_port; // lgtm [cpp/class-many-fields] unsigned short src_port; // lgtm [cpp/class-many-fields]
unsigned short dst_port; unsigned short dst_port;
unsigned int seqno; unsigned int seqno;
@ -139,32 +139,32 @@ struct tcp_header {
unsigned char reserved : 4; unsigned char reserved : 4;
unsigned char flg_fin : 1, flg_syn : 1, flg_rst : 1, flg_psh : 1, flg_ack : 1, flg_urg : 1, flg_reserved : 2; unsigned char flg_fin : 1, flg_syn : 1, flg_rst : 1, flg_psh : 1, flg_ack : 1, flg_urg : 1, flg_reserved : 2;
unsigned short win_length; unsigned short win_length;
unsigned short checksum; unsigned short sum;
unsigned short urp; unsigned short urp;
}; };
struct udp_header { struct udp_hdr_st {
unsigned short src_port; unsigned short src_port;
unsigned short dst_port; unsigned short dst_port;
unsigned short length; unsigned short length;
unsigned short checksum; unsigned short sum;
}; };
struct icmp_header { struct icmp_hdr_st {
unsigned char type; // 8bit type unsigned char type; // 8bit type
unsigned char code; // 8bit code unsigned char code; // 8bit code
unsigned short checksum; // 16bit check sum unsigned short sum; // 16bit check sum
unsigned short id; // identifier: usually use process id unsigned short id; // identifier: usually use process id
unsigned short seqno; // message sequence NO. unsigned short seqno; // message sequence NO.
}; };
struct eth_header { struct eth_hdr_st {
unsigned dst_eth[6]; unsigned dst_eth[6];
unsigned src_eth[6]; unsigned src_eth[6];
unsigned eth_type; unsigned eth_type;
}; };
struct arp_header { struct arp_hdr_st {
unsigned short arp_hw; // format of hardware address unsigned short arp_hw; // format of hardware address
unsigned short arp_pro; // format of protocol address unsigned short arp_pro; // format of protocol address
unsigned char arp_hlen; // length of hardware address unsigned char arp_hlen; // length of hardware address
@ -176,9 +176,9 @@ struct arp_header {
unsigned long arp_tpa; // target protocol address; unsigned long arp_tpa; // target protocol address;
}; };
struct arp_packet { struct arp_packet_st {
eth_header ethhdr; eth_hdr_st ethhdr;
arp_header arphdr; arp_hdr_st arphdr;
}; };
#pragma pack(pop) #pragma pack(pop)

View File

@ -39,7 +39,6 @@ SOFTWARE.
#include <sys/stat.h> #include <sys/stat.h>
#include <fcntl.h> #include <fcntl.h>
#include "yasio/detail/thread_name.hpp" #include "yasio/detail/thread_name.hpp"
#include "yasio/detail/signal_blocker.hpp"
#if defined(YASIO_SSL_BACKEND) #if defined(YASIO_SSL_BACKEND)
# include "yasio/detail/ssl.hpp" # include "yasio/detail/ssl.hpp"
@ -207,7 +206,7 @@ io_channel::io_channel(io_service& service, int index) : io_base(), service_(ser
socket_ = std::make_shared<xxsocket>(); socket_ = std::make_shared<xxsocket>();
state_ = io_base::state::CLOSED; state_ = io_base::state::CLOSED;
index_ = index; index_ = index;
decode_len_ = [=](void* ptr, int len) { return this->__builtin_decode_len(ptr, len); }; decode_len_ = [this](void* ptr, int len) { return this->__builtin_decode_len(ptr, len); };
} }
#if defined(YASIO_SSL_BACKEND) #if defined(YASIO_SSL_BACKEND)
SSL_CTX* io_channel::get_ssl_context(bool client) const SSL_CTX* io_channel::get_ssl_context(bool client) const
@ -443,13 +442,13 @@ void io_transport::complete_op(io_send_op* op, int error)
} }
void io_transport::set_primitives() void io_transport::set_primitives()
{ {
this->write_cb_ = [=](const void* data, int len, const ip::endpoint*, int& error) { this->write_cb_ = [this](const void* data, int len, const ip::endpoint*, int& error) {
int n = socket_->send(data, len); int n = socket_->send(data, len);
if (n < 0) if (n < 0)
error = xxsocket::get_last_errno(); error = xxsocket::get_last_errno();
return n; return n;
}; };
this->read_cb_ = [=](void* data, int len, int revent, int& error) { this->read_cb_ = [this](void* data, int len, int revent, int& error) {
if (revent) if (revent)
{ {
int n = socket_->recv(data, len); int n = socket_->recv(data, len);
@ -478,13 +477,13 @@ int io_transport_ssl::do_ssl_handshake(int& error)
if (ret == 0) // handshake succeed if (ret == 0) // handshake succeed
{ // because we invoke handshake in call_read, so we emit EWOULDBLOCK to mark ssl transport status `ok` { // because we invoke handshake in call_read, so we emit EWOULDBLOCK to mark ssl transport status `ok`
this->state_ = io_base::state::OPENED; this->state_ = io_base::state::OPENED;
this->read_cb_ = [=](void* data, int len, int revent, int& error) { this->read_cb_ = [this](void* data, int len, int revent, int& error) {
if (revent) if (revent)
return yssl_read(ssl_, data, len, error); return yssl_read(ssl_, data, len, error);
error = EWOULDBLOCK; error = EWOULDBLOCK;
return -1; return -1;
}; };
this->write_cb_ = [=](const void* data, int len, const ip::endpoint*, int& error) { return yssl_write(ssl_, data, len, error); }; this->write_cb_ = [this](const void* data, int len, const ip::endpoint*, int& error) { return yssl_write(ssl_, data, len, error); };
YASIO_KLOGD("[index: %d] the connection #%u <%s> --> <%s> is established.", ctx_->index_, this->id_, this->local_endpoint().to_string().c_str(), YASIO_KLOGD("[index: %d] the connection #%u <%s> --> <%s> is established.", ctx_->index_, this->id_, this->local_endpoint().to_string().c_str(),
this->remote_endpoint().to_string().c_str()); this->remote_endpoint().to_string().c_str());
@ -517,7 +516,7 @@ void io_transport_ssl::do_ssl_shutdown()
} }
void io_transport_ssl::set_primitives() void io_transport_ssl::set_primitives()
{ {
this->read_cb_ = [=](void* /*data*/, int /*len*/, int /*revent*/, int& error) { return do_ssl_handshake(error); }; this->read_cb_ = [this](void* /*data*/, int /*len*/, int /*revent*/, int& error) { return do_ssl_handshake(error); };
} }
#endif #endif
// ----------------------- io_transport_udp ---------------- // ----------------------- io_transport_udp ----------------
@ -589,7 +588,7 @@ void io_transport_udp::set_primitives()
io_transport::set_primitives(); io_transport::set_primitives();
else else
{ {
this->write_cb_ = [=](const void* data, int len, const ip::endpoint* destination, int& error) { this->write_cb_ = [this](const void* data, int len, const ip::endpoint* destination, int& error) {
assert(destination); assert(destination);
int n = socket_->sendto(data, len, *destination); int n = socket_->sendto(data, len, *destination);
if (n < 0) if (n < 0)
@ -600,7 +599,7 @@ void io_transport_udp::set_primitives()
} }
return n; return n;
}; };
this->read_cb_ = [=](void* data, int len, int revent, int& error) { this->read_cb_ = [this](void* data, int len, int revent, int& error) {
if (revent) if (revent)
{ {
ip::endpoint peer; ip::endpoint peer;
@ -735,8 +734,6 @@ void io_service::start(event_cb_t cb)
this->state_ = io_service::state::RUNNING; this->state_ = io_service::state::RUNNING;
if (!options_.no_new_thread_) if (!options_.no_new_thread_)
{ {
signal_blocker sb;
(void)sb;
this->worker_ = std::thread(&io_service::run, this); this->worker_ = std::thread(&io_service::run, this);
this->worker_id_ = worker_.get_id(); this->worker_id_ = worker_.get_id();
} }
@ -805,7 +802,7 @@ void io_service::initialize(const io_hostent* channel_eps, int channel_count)
if (channel_count < 1) if (channel_count < 1)
channel_count = 1; channel_count = 1;
options_.resolv_ = [=](std::vector<ip::endpoint>& eps, const char* host, unsigned short port) { return this->resolve(eps, host, port); }; options_.resolv_ = [this](std::vector<ip::endpoint>& eps, const char* host, unsigned short port) { return this->resolve(eps, host, port); };
register_descriptor(interrupter_.read_descriptor(), socket_event::read); register_descriptor(interrupter_.read_descriptor(), socket_event::read);
// create channels // create channels
@ -894,11 +891,9 @@ void io_service::run()
do do
{ {
auto wait_duration = get_timeout(this->wait_duration_); // Gets current wait duration
this->wait_duration_ = yasio__max_wait_usec; // Reset next wait duration
fd_set = this->fd_set_; fd_set = this->fd_set_;
timeval waitd_tv = {(decltype(timeval::tv_sec))(wait_duration / 1000000), (decltype(timeval::tv_usec))(wait_duration % 1000000)};
const auto waitd_usec = get_timeout(this->wait_duration_); // Gets current wait duration
#if defined(YASIO_HAVE_CARES) #if defined(YASIO_HAVE_CARES)
/** /**
* retrieves the set of file descriptors which the calling application should poll io, * retrieves the set of file descriptors which the calling application should poll io,
@ -907,10 +902,13 @@ void io_service::run()
* https://c-ares.org/ares_timeout.html * https://c-ares.org/ares_timeout.html
* https://c-ares.org/ares_process_fd.html * https://c-ares.org/ares_process_fd.html
*/ */
timeval waitd_tv = {(decltype(timeval::tv_sec))(waitd_usec / std::micro::den), (decltype(timeval::tv_usec))(waitd_usec % std::micro::den)};
auto ares_nfds = do_ares_fds(ares_socks, fd_set, waitd_tv); auto ares_nfds = do_ares_fds(ares_socks, fd_set, waitd_tv);
const auto waitd_ms = static_cast<int>(waitd_tv.tv_sec * std::milli::den + waitd_tv.tv_usec / std::milli::den);
#else
const auto waitd_ms = static_cast<int>(waitd_usec / std::milli::den);
#endif #endif
const int waitd_ms = static_cast<int>(waitd_tv.tv_sec * 1000 + waitd_tv.tv_usec / 1000);
if (waitd_ms > 0) if (waitd_ms > 0)
{ {
YASIO_KLOGV("[core] poll_io max_nfds=%d, waiting... %ld milliseconds", fd_set.max_descriptor(), waitd_ms); YASIO_KLOGV("[core] poll_io max_nfds=%d, waiting... %ld milliseconds", fd_set.max_descriptor(), waitd_ms);
@ -1219,8 +1217,8 @@ void io_service::do_connect_completion(io_channel* ctx, fd_set_adapter& fd_set)
#if defined(YASIO_SSL_BACKEND) #if defined(YASIO_SSL_BACKEND)
SSL_CTX* io_service::init_ssl_context(ssl_role role) SSL_CTX* io_service::init_ssl_context(ssl_role role)
{ {
auto ctx = role == YSSL_CLIENT ? yssl_ctx_new(yssl_options{options_.cafile_.c_str(), nullptr, true}) auto ctx = role == YSSL_CLIENT ? yssl_ctx_new(yssl_options{yasio__c_str(options_.cafile_), nullptr, true})
: yssl_ctx_new(yssl_options{options_.crtfile_.c_str(), options_.keyfile_.c_str(), false}); : yssl_ctx_new(yssl_options{yasio__c_str(options_.crtfile_), yasio__c_str(options_.keyfile_), false});
ssl_roles_[role] = ctx; ssl_roles_[role] = ctx;
return ctx; return ctx;
} }
@ -1309,10 +1307,18 @@ void io_service::recreate_ares_channel()
if (ares_) if (ares_)
destroy_ares_channel(); destroy_ares_channel();
int optmask = ARES_OPT_TIMEOUTMS | ARES_OPT_TRIES /* | ARES_OPT_LOOKUPS*/;
ares_options options = {}; ares_options options = {};
options.timeout = static_cast<int>(this->options_.dns_queries_timeout_ / std::milli::den); options.timeout = static_cast<int>(this->options_.dns_queries_timeout_ / std::milli::den);
options.tries = this->options_.dns_queries_tries_; options.tries = this->options_.dns_queries_tries_;
int status = ::ares_init_options(&ares_, &options, ARES_OPT_TIMEOUTMS | ARES_OPT_TRIES /* | ARES_OPT_LOOKUPS*/); # if defined(__linux__) && !defined(__ANDROID__)
if (yasio::is_regular_file(YASIO_SYSTEMD_RESOLV_PATH))
{
options.resolvconf_path = strndup(YASIO_SYSTEMD_RESOLV_PATH, YASIO_SYSTEMD_RESOLV_PATH_LEN);
optmask |= ARES_OPT_RESOLVCONF;
}
# endif
int status = ::ares_init_options(&ares_, &options, optmask);
if (status == ARES_SUCCESS) if (status == ARES_SUCCESS)
{ {
YASIO_KLOGD("[c-ares] create channel succeed"); YASIO_KLOGD("[c-ares] create channel succeed");
@ -1806,6 +1812,8 @@ void io_service::process_timers()
} }
highp_time_t io_service::get_timeout(highp_time_t usec) highp_time_t io_service::get_timeout(highp_time_t usec)
{ {
this->wait_duration_ = yasio__max_wait_usec; // Reset next wait duration per frame
if (this->timer_queue_.empty()) if (this->timer_queue_.empty())
return usec; return usec;
@ -1905,11 +1913,11 @@ void io_service::start_query(io_channel* ctx)
#endif #endif
#if !defined(YASIO_HAVE_CARES) #if !defined(YASIO_HAVE_CARES)
// init async name query thread state // init async name query thread state
std::string resolving_host = ctx->remote_host_; auto resolving_host = ctx->remote_host_;
u_short resolving_port = ctx->remote_port_; auto resolving_port = ctx->remote_port_;
std::weak_ptr<cxx17::shared_mutex> weak_mutex = life_mutex_; std::weak_ptr<cxx17::shared_mutex> weak_mutex = life_mutex_;
std::weak_ptr<life_token> life_token = life_token_; std::weak_ptr<life_token> life_token = life_token_;
std::thread async_resolv_thread([=] { std::thread async_resolv_thread([this, life_token, weak_mutex, resolving_host, resolving_port, ctx] {
// check life token // check life token
if (life_token.use_count() < 1) if (life_token.use_count() < 1)
return; return;

View File

@ -1048,6 +1048,8 @@ public:
// Gets channel by index // Gets channel by index
YASIO__DECL io_channel* channel_at(size_t index) const; YASIO__DECL io_channel* channel_at(size_t index) const;
YASIO__DECL static const char* strerror(int error);
private: private:
YASIO__DECL void do_stop(uint8_t flags); YASIO__DECL void do_stop(uint8_t flags);
YASIO__DECL void schedule_timer(highp_timer*, timer_cb_t&&); YASIO__DECL void schedule_timer(highp_timer*, timer_cb_t&&);
@ -1151,8 +1153,6 @@ private:
YASIO__DECL void do_accept(io_channel*); YASIO__DECL void do_accept(io_channel*);
YASIO__DECL void do_accept_completion(io_channel*, fd_set_adapter& fd_set); YASIO__DECL void do_accept_completion(io_channel*, fd_set_adapter& fd_set);
YASIO__DECL static const char* strerror(int error);
/* /*
** summary: For udp-server only, make dgram handle to communicate with client ** summary: For udp-server only, make dgram handle to communicate with client
*/ */