HttpClient: push front available channel to fix dns cache missing

This commit is contained in:
halx99 2021-08-03 14:41:30 +08:00
parent 71c17cfc9b
commit cfffd35aec
4 changed files with 39 additions and 17 deletions

View File

@ -53,6 +53,16 @@ public:
std::lock_guard<std::recursive_mutex> lck(this->mtx_); std::lock_guard<std::recursive_mutex> lck(this->mtx_);
queue_.pop_front(); queue_.pop_front();
} }
void push_front(_Ty&& value)
{
std::lock_guard<std::recursive_mutex> lck(this->mtx_);
queue_.push_front(std::forward<_Ty>(value));
}
void push_front(const _Ty& value)
{
std::lock_guard<std::recursive_mutex> lck(this->mtx_);
queue_.push_front(value);
}
size_t size() const { size_t size() const {
std::lock_guard<std::recursive_mutex> lck(this->mtx_); std::lock_guard<std::recursive_mutex> lck(this->mtx_);
return this->queue_.size(); return this->queue_.size();
@ -89,6 +99,8 @@ public:
void unsafe_pop_front() { void unsafe_pop_front() {
queue_.pop_front(); queue_.pop_front();
} }
void unsafe_push_front(_Ty&& value) { queue_.push_font(std::forward<_Ty>(value)); }
void unsafe_push_front(const _Ty& value) { queue_.push_font(value); }
bool unsafe_empty() const { bool unsafe_empty() const {
return this->queue_.empty(); return this->queue_.empty();
} }

View File

@ -114,7 +114,7 @@ HttpClient::HttpClient()
_service->start([=](yasio::event_ptr&& e) { handleNetworkEvent(e.get()); }); _service->start([=](yasio::event_ptr&& e) { handleNetworkEvent(e.get()); });
for (int i = 0; i < HttpClient::MAX_CHANNELS; ++i) { for (int i = 0; i < HttpClient::MAX_CHANNELS; ++i) {
_availChannelQueue.push_back(i); _availChannelQueue.unsafe_push_back(i);
} }
_scheduler->schedule([=](float) { dispatchResponseCallbacks(); }, this, 0, false, "#"); _scheduler->schedule([=](float) { dispatchResponseCallbacks(); }, this, 0, false, "#");
@ -342,7 +342,7 @@ void HttpClient::handleNetworkEOF(HttpResponse* response, yasio::io_channel* cha
if (responseCode == 302) if (responseCode == 302)
response->getHttpRequest()->setRequestType(HttpRequest::Type::GET); response->getHttpRequest()->setRequestType(HttpRequest::Type::GET);
CCLOG("Process url redirect (%d): %s", responseCode, iter->second.c_str()); CCLOG("Process url redirect (%d): %s", responseCode, iter->second.c_str());
_availChannelQueue.push_back(channel->index()); _availChannelQueue.push_front(channel->index());
processResponse(response, iter->second); processResponse(response, iter->second);
response->release(); response->release();
return; return;
@ -353,7 +353,7 @@ void HttpClient::handleNetworkEOF(HttpResponse* response, yasio::io_channel* cha
finishResponse(response); finishResponse(response);
// recycle channel // recycle channel
_availChannelQueue.push_back(channel->index()); _availChannelQueue.push_front(channel->index());
// try process pending response // try process pending response
auto lck = _pendingResponseQueue.get_lock(); auto lck = _pendingResponseQueue.get_lock();

View File

@ -158,10 +158,10 @@ struct yasio__global_state {
// for single core CPU, we set minimal wait duration to 10us by default // for single core CPU, we set minimal wait duration to 10us by default
yasio__min_wait_duration = std::thread::hardware_concurrency() > 1 ? 0LL : YASIO_MIN_WAIT_DURATION; yasio__min_wait_duration = std::thread::hardware_concurrency() > 1 ? 0LL : YASIO_MIN_WAIT_DURATION;
#if defined(YASIO_SSL_BACKEND) && YASIO_SSL_BACKEND == 1 #if defined(YASIO_SSL_BACKEND) && YASIO_SSL_BACKEND == 1
#if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER) # if OPENSSL_VERSION_NUMBER >= 0x10100000 && !defined(LIBRESSL_VERSION_NUMBER)
if (OPENSSL_init_ssl(0, NULL) == 1) if (OPENSSL_init_ssl(0, NULL) == 1)
yasio__setbits(this->init_flags_, INITF_SSL); yasio__setbits(this->init_flags_, INITF_SSL);
#endif # endif
#endif #endif
#if defined(YASIO_HAVE_CARES) #if defined(YASIO_HAVE_CARES)
int ares_status = ::ares_library_init(ARES_LIB_INIT_ALL); int ares_status = ::ares_library_init(ARES_LIB_INIT_ALL);
@ -1403,10 +1403,11 @@ void io_service::do_ssl_handshake(io_channel* ctx)
the required condition: https://www.openssl.org/docs/manmaster/man3/SSL_do_handshake.html the required condition: https://www.openssl.org/docs/manmaster/man3/SSL_do_handshake.html
*/ */
if (status == SSL_ERROR_WANT_READ || status == SSL_ERROR_WANT_WRITE) if (status == SSL_ERROR_WANT_READ || status == SSL_ERROR_WANT_WRITE)
return; return;
#if defined(SSL_ERROR_WANT_ASYNC) # if defined(SSL_ERROR_WANT_ASYNC)
if (status == SSL_ERROR_WANT_ASYNC) return; if (status == SSL_ERROR_WANT_ASYNC)
#endif return;
# endif
int error = static_cast<int>(ERR_get_error()); int error = static_cast<int>(ERR_get_error());
if (error) if (error)
{ {
@ -1512,7 +1513,6 @@ void io_service::process_ares_requests(fd_set* fds_array)
} }
void io_service::recreate_ares_channel() void io_service::recreate_ares_channel()
{ {
this->options_.dns_dirty_ = false;
if (ares_) if (ares_)
destroy_ares_channel(); destroy_ares_channel();
@ -2056,6 +2056,7 @@ bool io_service::cleanup_io(io_base* obj, bool clear_state)
} }
u_short io_service::query_ares_state(io_channel* ctx) u_short io_service::query_ares_state(io_channel* ctx)
{ {
update_dns_status();
if (yasio__testbits(ctx->properties_, YCPF_NEEDS_QUERIES)) if (yasio__testbits(ctx->properties_, YCPF_NEEDS_QUERIES))
{ {
switch (static_cast<u_short>(ctx->dns_queries_state_)) switch (static_cast<u_short>(ctx->dns_queries_state_))
@ -2129,9 +2130,6 @@ void io_service::start_resolve(io_channel* ctx)
}); });
async_resolv_thread.detach(); async_resolv_thread.detach();
#else #else
if (this->options_.dns_dirty_)
recreate_ares_channel();
ares_addrinfo_hints hint; ares_addrinfo_hints hint;
memset(&hint, 0x0, sizeof(hint)); memset(&hint, 0x0, sizeof(hint));
hint.ai_family = local_address_family(); hint.ai_family = local_address_family();
@ -2146,6 +2144,18 @@ void io_service::start_resolve(io_channel* ctx)
::ares_getaddrinfo(this->ares_, ctx->remote_host_.c_str(), service, &hint, io_service::ares_getaddrinfo_cb, ctx); ::ares_getaddrinfo(this->ares_, ctx->remote_host_.c_str(), service, &hint, io_service::ares_getaddrinfo_cb, ctx);
#endif #endif
} }
void io_service::update_dns_status()
{
if (this->options_.dns_dirty_)
{
this->options_.dns_dirty_ = false;
#if defined(YASIO_HAVE_CARES)
recreate_ares_channel();
#endif
for (auto channel : this->channels_)
channel->dns_queries_state_ = YDQS_DIRTY;
}
}
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)
{ {
if (yasio__testbits(this->ipsv_, ipsv_ipv4)) if (yasio__testbits(this->ipsv_, ipsv_ipv4))

View File

@ -164,9 +164,7 @@ enum
// Set dns server dirty // Set dns server dirty
// params: reserved : int(1) // params: reserved : int(1)
// remarks: // remarks: you should set this option after your device network changed
// a. this option only works with c-ares enabled
// b. you should set this option after your mobile network changed
YOPT_S_DNS_DIRTY, YOPT_S_DNS_DIRTY,
// Sets channel length field based frame decode function, native C++ ONLY // Sets channel length field based frame decode function, native C++ ONLY
@ -1110,6 +1108,8 @@ private:
int local_address_family() const { return ((ipsv_ & ipsv_ipv4) || !ipsv_) ? AF_INET : AF_INET6; } int local_address_family() const { return ((ipsv_ & ipsv_ipv4) || !ipsv_) ? AF_INET : AF_INET6; }
YASIO__DECL void update_dns_status();
/* 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_; }
@ -1156,7 +1156,7 @@ private:
highp_time_t dns_queries_timeout_ = 5LL * std::micro::den; highp_time_t dns_queries_timeout_ = 5LL * std::micro::den;
int dns_queries_tries_ = 5; int dns_queries_tries_ = 5;
bool dns_dirty_ = true; // only for c-ares bool dns_dirty_ = false;
bool deferred_event_ = true; bool deferred_event_ = true;
defer_event_cb_t on_defer_event_; defer_event_cb_t on_defer_event_;