Update yasio

This commit is contained in:
halx99 2021-12-14 14:05:22 +08:00
parent 7a0c89b7fd
commit bc0fabe245
2 changed files with 46 additions and 58 deletions

View File

@ -123,16 +123,13 @@ enum
/* whether port dirty */ /* whether port dirty */
YCPF_PORT_DIRTY = 1 << 20, YCPF_PORT_DIRTY = 1 << 20,
/* host is domain name, needs resolve */ /* host is domain name, needs query via internet */
YCPF_NEEDS_RESOLVE = 1 << 21, YCPF_NEEDS_QUERY = 1 << 21,
/// below is byte2 of private flags (25~32) are mutable, and will be cleared automatically when connect flow done. /// below is byte2 of private flags (25~32) are mutable, and will be cleared automatically when connect flow done, see clear_mutable_flags.
/* whether the name resolve in progress */
YCPF_NAME_RESOLVING = 1 << 25,
/* whether ssl client in handshaking */ /* whether ssl client in handshaking */
YCPF_SSL_HANDSHAKING = 1 << 26, YCPF_SSL_HANDSHAKING = 1 << 25,
}; };
namespace namespace
@ -236,7 +233,7 @@ io_channel::io_channel(io_service& service, int index) : io_base(), service_(ser
const print_fn2_t& io_channel::__get_cprint() const { return get_service().options_.print_; } const print_fn2_t& io_channel::__get_cprint() const { return get_service().options_.print_; }
std::string io_channel::format_destination() const std::string io_channel::format_destination() const
{ {
if (yasio__testbits(properties_, YCPF_NEEDS_RESOLVE)) if (yasio__testbits(properties_, YCPF_NEEDS_QUERY))
return yasio::strfmt(127, "%s(%s):%u", remote_host_.c_str(), !remote_eps_.empty() ? remote_eps_[0].ip().c_str() : "undefined", remote_port_); return yasio::strfmt(127, "%s(%s):%u", remote_host_.c_str(), !remote_eps_.empty() ? remote_eps_[0].ip().c_str() : "undefined", remote_port_);
return yasio::strfmt(127, "%s:%u", remote_host_.c_str(), remote_port_); return yasio::strfmt(127, "%s:%u", remote_host_.c_str(), remote_port_);
@ -467,10 +464,7 @@ void io_transport::set_primitives()
inline io_transport_tcp::io_transport_tcp(io_channel* ctx, xxsocket_ptr&& s) : io_transport(ctx, std::forward<xxsocket_ptr>(s)) {} inline io_transport_tcp::io_transport_tcp(io_channel* ctx, xxsocket_ptr&& s) : io_transport(ctx, std::forward<xxsocket_ptr>(s)) {}
// ----------------------- io_transport_ssl ---------------- // ----------------------- io_transport_ssl ----------------
#if defined(YASIO_SSL_BACKEND) #if defined(YASIO_SSL_BACKEND)
io_transport_ssl::io_transport_ssl(io_channel* ctx, xxsocket_ptr&& s) : io_transport_tcp(ctx, std::forward<xxsocket_ptr>(s)), ssl_(std::move(ctx->ssl_)) io_transport_ssl::io_transport_ssl(io_channel* ctx, xxsocket_ptr&& s) : io_transport_tcp(ctx, std::forward<xxsocket_ptr>(s)), ssl_(std::move(ctx->ssl_)) {}
{
yasio__clearbits(ctx->properties_, YCPF_SSL_HANDSHAKING);
}
void io_transport_ssl::set_primitives() void io_transport_ssl::set_primitives()
{ {
this->read_cb_ = [=](void* data, int len) { this->read_cb_ = [=](void* data, int len) {
@ -1447,19 +1441,18 @@ void io_service::ares_getaddrinfo_cb(void* arg, int status, int /*timeouts*/, ar
auto __get_cprint = [&]() -> const print_fn2_t& { return current_service.options_.print_; }; auto __get_cprint = [&]() -> const print_fn2_t& { return current_service.options_.print_; };
if (!ctx->remote_eps_.empty()) if (!ctx->remote_eps_.empty())
{ {
ctx->last_resolved_time_ = highp_clock(); ctx->query_success_time_ = highp_clock();
# if defined(YASIO_ENABLE_ARES_PROFILER) # if defined(YASIO_ENABLE_ARES_PROFILER)
YASIO_KLOGD("[index: %d] ares_getaddrinfo_cb: resolve %s succeed, cost:%g(ms)", ctx->index_, ctx->remote_host_.c_str(), YASIO_KLOGD("[index: %d] ares_getaddrinfo_cb: query %s succeed, cost:%g(ms)", ctx->index_, ctx->remote_host_.c_str(),
(ctx->last_resolved_time_ - ctx->ares_start_time_) / 1000.0); (ctx->query_success_time_ - ctx->query_start_time_) / 1000.0);
# endif # endif
} }
else else
{ {
ctx->set_last_errno(yasio::errc::resolve_host_failed); ctx->set_last_errno(yasio::errc::resolve_host_failed);
YASIO_KLOGE("[index: %d] ares_getaddrinfo_cb: resolve %s failed, status=%d, detail:%s", ctx->index_, ctx->remote_host_.c_str(), status, YASIO_KLOGE("[index: %d] ares_getaddrinfo_cb: query %s failed, status=%d, detail:%s", ctx->index_, ctx->remote_host_.c_str(), status,
::ares_strerror(status)); ::ares_strerror(status));
} }
yasio__clearbits(ctx->properties_, YCPF_NAME_RESOLVING);
current_service.interrupt(); current_service.interrupt();
} }
void io_service::process_ares_requests(fd_set* fds_array) void io_service::process_ares_requests(fd_set* fds_array)
@ -1710,7 +1703,7 @@ void io_service::handle_connect_succeed(transport_handle_t transport)
{ {
auto ctx = transport->ctx_; auto ctx = transport->ctx_;
ctx->clear_mutable_flags(); ctx->clear_mutable_flags();
ctx->set_last_errno(0); // clear errno, value may be EINPROGRESS ctx->error_ = 0; // clear errno, value may be EINPROGRESS
auto& connection = transport->socket_; auto& connection = transport->socket_;
if (yasio__testbits(ctx->properties_, YCM_CLIENT)) if (yasio__testbits(ctx->properties_, YCM_CLIENT))
{ {
@ -2041,7 +2034,7 @@ int io_service::do_resolve(io_channel* ctx)
{ {
if (yasio__testbits(ctx->properties_, YCPF_HOST_DIRTY)) if (yasio__testbits(ctx->properties_, YCPF_HOST_DIRTY))
{ {
yasio__clearbits(ctx->properties_, YCPF_HOST_DIRTY); yasio__clearbits(ctx->properties_, YCPF_HOST_DIRTY | YCPF_NEEDS_QUERY);
ctx->remote_eps_.clear(); ctx->remote_eps_.clear();
ip::endpoint ep; ip::endpoint ep;
#if defined(YASIO_ENABLE_UDS) && YASIO__HAS_UDS #if defined(YASIO_ENABLE_UDS) && YASIO__HAS_UDS
@ -2055,52 +2048,49 @@ int io_service::do_resolve(io_channel* ctx)
if (ep.as_in(ctx->remote_host_.c_str(), ctx->remote_port_)) if (ep.as_in(ctx->remote_host_.c_str(), ctx->remote_port_))
ctx->remote_eps_.push_back(ep); ctx->remote_eps_.push_back(ep);
else else
yasio__setbits(ctx->properties_, YCPF_NEEDS_RESOLVE); yasio__setbits(ctx->properties_, YCPF_NEEDS_QUERY);
} }
if (yasio__testbits(ctx->properties_, YCPF_PORT_DIRTY)) if (yasio__testbits(ctx->properties_, YCPF_PORT_DIRTY))
{ {
yasio__clearbits(ctx->properties_, YCPF_PORT_DIRTY); yasio__clearbits(ctx->properties_, YCPF_PORT_DIRTY);
if (!ctx->remote_eps_.empty()) for (auto& ep : ctx->remote_eps_)
for (auto& ep : ctx->remote_eps_) ep.port(ctx->remote_port_);
ep.port(ctx->remote_port_);
} }
if (!ctx->remote_eps_.empty()) if (!ctx->remote_eps_.empty())
{ {
if (!yasio__testbits(ctx->properties_, YCPF_NEEDS_RESOLVE)) if (!yasio__testbits(ctx->properties_, YCPF_NEEDS_QUERY))
return 0; return 0; // remote host is IP address, no needs to query
update_dns_status();
if (ctx->last_resolved_reuse_ == 0 || (highp_clock() - ctx->last_resolved_time_) < options_.dns_cache_timeout_) update_dns_status(); // will reset our resolved address expire time
{
++ctx->last_resolved_reuse_; if (ctx->error_ == EINPROGRESS)
return 0; return 0; // queried address not consumed by this connect flow
}
if (!address_expired(ctx))
return 0; // queried address not exipred
ctx->remote_eps_.clear(); ctx->remote_eps_.clear();
} }
if (!ctx->remote_host_.empty()) if (!ctx->remote_host_.empty())
{ {
if (ctx->error_ == yasio::errc::resolve_host_failed) if (!ctx->error_)
return -1; start_query(ctx);
if (!yasio__testbits(ctx->properties_, YCPF_NAME_RESOLVING))
start_resolve(ctx);
} }
else else
ctx->error_ = yasio::errc::no_available_address; ctx->error_ = yasio::errc::no_available_address;
return -1; return -1;
} }
void io_service::start_resolve(io_channel* ctx) void io_service::start_query(io_channel* ctx)
{ {
ctx->last_resolved_reuse_ = 0;
yasio__setbits(ctx->properties_, YCPF_NAME_RESOLVING);
ctx->set_last_errno(EINPROGRESS); ctx->set_last_errno(EINPROGRESS);
YASIO_KLOGD("[index: %d] resolving %s", ctx->index_, ctx->remote_host_.c_str()); YASIO_KLOGD("[index: %d] start query %s...", ctx->index_, ctx->remote_host_.c_str());
#if defined(YASIO_ENABLE_ARES_PROFILER) #if defined(YASIO_ENABLE_ARES_PROFILER)
ctx->ares_start_time_ = highp_clock(); ctx->query_start_time_ = highp_clock();
#endif #endif
#if !defined(YASIO_HAVE_CARES) #if !defined(YASIO_HAVE_CARES)
// init async resolve thread state // init async name query thread state
std::string resolving_host = ctx->remote_host_; std::string resolving_host = ctx->remote_host_;
u_short resolving_port = ctx->remote_port_; u_short 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_;
@ -2127,15 +2117,14 @@ void io_service::start_resolve(io_channel* ctx)
if (error == 0) if (error == 0)
{ {
ctx->remote_eps_ = std::move(remote_eps); ctx->remote_eps_ = std::move(remote_eps);
ctx->last_resolved_time_ = highp_clock(); ctx->query_success_time_ = highp_clock();
# if defined(YASIO_ENABLE_ARES_PROFILER) # if defined(YASIO_ENABLE_ARES_PROFILER)
YASIO_KLOGD("[index: %d] resolve %s succeed, cost: %g(ms)", ctx->index_, ctx->remote_host_.c_str(), YASIO_KLOGD("[index: %d] query %s succeed, cost: %g(ms)", ctx->index_, ctx->remote_host_.c_str(),
(ctx->resolved_time_ - ctx->ares_start_time_) / 1000.0); (ctx->query_success_time_ - ctx->query_start_time_) / 1000.0);
# endif # endif
} }
else else
YASIO_KLOGE("[index: %d] resolve %s failed, ec=%d, detail:%s", ctx->index_, ctx->remote_host_.c_str(), error, xxsocket::gai_strerror(error)); YASIO_KLOGE("[index: %d] query %s failed, ec=%d, detail:%s", ctx->index_, ctx->remote_host_.c_str(), error, xxsocket::gai_strerror(error));
yasio__clearbits(ctx->properties_, YCPF_NAME_RESOLVING);
this->interrupt(); this->interrupt();
}); });
async_resolv_thread.detach(); async_resolv_thread.detach();
@ -2163,7 +2152,7 @@ void io_service::update_dns_status()
recreate_ares_channel(); recreate_ares_channel();
#endif #endif
for (auto channel : this->channels_) for (auto channel : this->channels_)
channel->last_resolved_time_ = 0; channel->query_success_time_ = 0;
} }
} }
int io_service::resolve(std::vector<ip::endpoint>& endpoints, const char* hostname, unsigned short port) int io_service::resolve(std::vector<ip::endpoint>& endpoints, const char* hostname, unsigned short port)

View File

@ -565,11 +565,12 @@ private:
*/ */
u_short remote_port_ = 0; u_short remote_port_ = 0;
// The last resolved address time in microseconds for dns cache support // The last query success time in microseconds for dns cache support
highp_time_t last_resolved_time_ = 0; highp_time_t query_success_time_ = 0;
// The last resolved address reuse times #if defined(YASIO_ENABLE_ARES_PROFILER)
unsigned int last_resolved_reuse_ = 0; highp_time_t query_start_time_;
#endif
int index_; int index_;
int socktype_ = 0; int socktype_ = 0;
@ -622,10 +623,6 @@ private:
#if defined(YASIO_SSL_BACKEND) #if defined(YASIO_SSL_BACKEND)
ssl_auto_handle ssl_; ssl_auto_handle ssl_;
#endif #endif
#if defined(YASIO_ENABLE_ARES_PROFILER)
highp_time_t ares_start_time_;
#endif
}; };
// for tcp transport only // for tcp transport only
@ -1044,8 +1041,8 @@ private:
[](const timer_impl_t& lhs, const timer_impl_t& rhs) { return lhs.first->wait_duration() > rhs.first->wait_duration(); }); [](const timer_impl_t& lhs, const timer_impl_t& rhs) { return lhs.first->wait_duration() > rhs.first->wait_duration(); });
} }
// Start a async resolve, It's only for internal use // Start a async domain name query
YASIO__DECL void start_resolve(io_channel*); YASIO__DECL void start_query(io_channel*);
YASIO__DECL void initialize(const io_hostent* channel_eps /* could be nullptr */, int channel_count); YASIO__DECL void initialize(const io_hostent* channel_eps /* could be nullptr */, int channel_count);
YASIO__DECL void finalize(); YASIO__DECL void finalize();
@ -1135,6 +1132,8 @@ private:
YASIO__DECL void update_dns_status(); YASIO__DECL void update_dns_status();
bool address_expired(io_channel* ctx) const { return (highp_clock() - ctx->query_success_time_) > options_.dns_cache_timeout_; }
/* For log macro only */ /* For log macro only */
inline const print_fn2_t& __get_cprint() const { return options_.print_; } inline const print_fn2_t& __get_cprint() const { return options_.print_; }