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_);
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 {
std::lock_guard<std::recursive_mutex> lck(this->mtx_);
return this->queue_.size();
@ -89,6 +99,8 @@ public:
void unsafe_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 {
return this->queue_.empty();
}

View File

@ -114,7 +114,7 @@ HttpClient::HttpClient()
_service->start([=](yasio::event_ptr&& e) { handleNetworkEvent(e.get()); });
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, "#");
@ -342,7 +342,7 @@ void HttpClient::handleNetworkEOF(HttpResponse* response, yasio::io_channel* cha
if (responseCode == 302)
response->getHttpRequest()->setRequestType(HttpRequest::Type::GET);
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);
response->release();
return;
@ -353,7 +353,7 @@ void HttpClient::handleNetworkEOF(HttpResponse* response, yasio::io_channel* cha
finishResponse(response);
// recycle channel
_availChannelQueue.push_back(channel->index());
_availChannelQueue.push_front(channel->index());
// try process pending response
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
yasio__min_wait_duration = std::thread::hardware_concurrency() > 1 ? 0LL : YASIO_MIN_WAIT_DURATION;
#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)
yasio__setbits(this->init_flags_, INITF_SSL);
#endif
# endif
#endif
#if defined(YASIO_HAVE_CARES)
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
*/
if (status == SSL_ERROR_WANT_READ || status == SSL_ERROR_WANT_WRITE)
return;
#if defined(SSL_ERROR_WANT_ASYNC)
if (status == SSL_ERROR_WANT_ASYNC) return;
#endif
return;
# if defined(SSL_ERROR_WANT_ASYNC)
if (status == SSL_ERROR_WANT_ASYNC)
return;
# endif
int error = static_cast<int>(ERR_get_error());
if (error)
{
@ -1512,7 +1513,6 @@ void io_service::process_ares_requests(fd_set* fds_array)
}
void io_service::recreate_ares_channel()
{
this->options_.dns_dirty_ = false;
if (ares_)
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)
{
update_dns_status();
if (yasio__testbits(ctx->properties_, YCPF_NEEDS_QUERIES))
{
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();
#else
if (this->options_.dns_dirty_)
recreate_ares_channel();
ares_addrinfo_hints hint;
memset(&hint, 0x0, sizeof(hint));
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);
#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)
{
if (yasio__testbits(this->ipsv_, ipsv_ipv4))

View File

@ -164,9 +164,7 @@ enum
// Set dns server dirty
// params: reserved : int(1)
// remarks:
// a. this option only works with c-ares enabled
// b. you should set this option after your mobile network changed
// remarks: you should set this option after your device network changed
YOPT_S_DNS_DIRTY,
// 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; }
YASIO__DECL void update_dns_status();
/* For log macro only */
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;
int dns_queries_tries_ = 5;
bool dns_dirty_ = true; // only for c-ares
bool dns_dirty_ = false;
bool deferred_event_ = true;
defer_event_cb_t on_defer_event_;