Removing code repetition and fixing timer bug (#5891)

This commit is contained in:
uptycs-nishant 2019-10-26 22:04:55 +05:30 committed by Teddy Reed
parent 4927bf6877
commit bf25d02c86
2 changed files with 76 additions and 107 deletions

View File

@ -29,6 +29,24 @@ const std::string kProxyDefaultPort{"3128"};
const long kSSLShortReadError{0x140000dbL}; const long kSSLShortReadError{0x140000dbL};
void Client::callNetworkOperation(std::function<void()> callback) {
if (client_options_.timeout_) {
timer_.async_wait(
std::bind(&Client::timeoutHandler, this, std::placeholders::_1));
}
callback();
{
boost_system::error_code rc;
ioc_.run(rc);
ioc_.reset();
if (rc) {
ec_ = rc;
}
}
}
void Client::postResponseHandler(boost_system::error_code const& ec) { void Client::postResponseHandler(boost_system::error_code const& ec) {
if ((ec.category() == boost_asio::error::ssl_category) && if ((ec.category() == boost_asio::error::ssl_category) &&
(ec.value() == kSSLShortReadError)) { (ec.value() == kSSLShortReadError)) {
@ -131,25 +149,13 @@ void Client::createConnection() {
connect_host = connect_host.substr(0, pos); connect_host = connect_host.substr(0, pos);
} }
if (client_options_.timeout_) { callNetworkOperation([&]() {
timer_.async_wait(
[=](boost_system::error_code const& ec) { timeoutHandler(ec); });
}
r_.async_resolve(boost_asio::ip::tcp::resolver::query{connect_host, port}, r_.async_resolve(boost_asio::ip::tcp::resolver::query{connect_host, port},
std::bind(&Client::resolveHandler, std::bind(&Client::resolveHandler,
this, this,
std::placeholders::_1, std::placeholders::_1,
std::placeholders::_2)); std::placeholders::_2));
});
{
boost_system::error_code rc;
ioc_.run(rc);
ioc_.reset();
if (rc) {
ec_ = rc;
}
}
if (ec_) { if (ec_) {
std::string error("Failed to connect to "); std::string error("Failed to connect to ");
@ -175,26 +181,14 @@ void Client::createConnection() {
req.version(11); req.version(11);
req.prepare_payload(); req.prepare_payload();
if (client_options_.timeout_) { callNetworkOperation([&]() {
timer_.async_wait(
[=](boost_system::error_code const& ec) { timeoutHandler(ec); });
}
beast_http::async_write(sock_, beast_http::async_write(sock_,
req, req,
std::bind(&Client::writeHandler, std::bind(&Client::writeHandler,
this, this,
std::placeholders::_1, std::placeholders::_1,
std::placeholders::_2)); std::placeholders::_2));
});
{
boost_system::error_code rc;
ioc_.run(rc);
ioc_.reset();
if (rc) {
ec_ = rc;
}
}
if (ec_) { if (ec_) {
throw std::system_error(ec_); throw std::system_error(ec_);
@ -204,11 +198,7 @@ void Client::createConnection() {
beast_http_response_parser rp; beast_http_response_parser rp;
rp.skip(true); rp.skip(true);
if (client_options_.timeout_) { callNetworkOperation([&]() {
timer_.async_wait(
[=](boost_system::error_code const& ec) { timeoutHandler(ec); });
}
beast_http::async_read_header(sock_, beast_http::async_read_header(sock_,
b, b,
rp, rp,
@ -216,15 +206,7 @@ void Client::createConnection() {
this, this,
std::placeholders::_1, std::placeholders::_1,
std::placeholders::_2)); std::placeholders::_2));
});
{
boost_system::error_code rc;
ioc_.run(rc);
ioc_.reset();
if (rc) {
ec_ = rc;
}
}
if (ec_) { if (ec_) {
throw std::system_error(ec_); throw std::system_error(ec_);
@ -281,18 +263,11 @@ void Client::encryptConnection() {
client_options_.sni_hostname_->c_str()); client_options_.sni_hostname_->c_str());
} }
callNetworkOperation([&]() {
ssl_sock_->async_handshake( ssl_sock_->async_handshake(
boost_asio::ssl::stream_base::client, boost_asio::ssl::stream_base::client,
std::bind(&Client::handshakeHandler, this, std::placeholders::_1)); std::bind(&Client::handshakeHandler, this, std::placeholders::_1));
});
{
boost_system::error_code rc;
ioc_.run(rc);
ioc_.reset();
if (rc) {
ec_ = rc;
}
}
if (ec_) { if (ec_) {
throw std::system_error(ec_); throw std::system_error(ec_);
@ -327,33 +302,23 @@ void Client::sendRequest(STREAM_TYPE& stream,
} }
beast_http_request_serializer sr{req}; beast_http_request_serializer sr{req};
callNetworkOperation([&]() {
beast_http::async_write(stream, beast_http::async_write(stream,
sr, sr,
std::bind(&Client::writeHandler, std::bind(&Client::writeHandler,
this, this,
std::placeholders::_1, std::placeholders::_1,
std::placeholders::_2)); std::placeholders::_2));
});
{
boost_system::error_code rc;
ioc_.run(rc);
ioc_.reset();
if (rc) {
ec_ = rc;
}
}
if (ec_) { if (ec_) {
throw std::system_error(ec_); throw std::system_error(ec_);
} }
if (client_options_.timeout_) {
timer_.async_wait(
[=](boost_system::error_code const& ec) { timeoutHandler(ec); });
}
boost::beast::flat_buffer b; boost::beast::flat_buffer b;
callNetworkOperation([&]() {
beast_http::async_read(stream, beast_http::async_read(stream,
b, b,
resp, resp,
@ -361,15 +326,7 @@ void Client::sendRequest(STREAM_TYPE& stream,
this, this,
std::placeholders::_1, std::placeholders::_1,
std::placeholders::_2)); std::placeholders::_2));
});
{
boost_system::error_code rc;
ioc_.run(rc);
ioc_.reset();
if (rc) {
ec_ = rc;
}
}
if (ec_) { if (ec_) {
throw std::system_error(ec_); throw std::system_error(ec_);

View File

@ -310,6 +310,18 @@ class Client {
void closeSocket(); void closeSocket();
/**
* @brief Wrap actual network call.
*
* callNetworkOperation is a wrapper function which wraps following tasks
* 1. Start the timer for network call timeout.
* 2. Call provided call back which is actually an async network call.
* 3. Wait for timer and async network call simultaneously.
*
* This function sets ec_ in case of boost io service returns with an error.
*/
void callNetworkOperation(std::function<void()> callback);
private: private:
Options client_options_; Options client_options_;
boost_asio::io_context ioc_; boost_asio::io_context ioc_;