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( r_.async_resolve(boost_asio::ip::tcp::resolver::query{connect_host, port},
[=](boost_system::error_code const& ec) { timeoutHandler(ec); }); std::bind(&Client::resolveHandler,
} this,
std::placeholders::_1,
r_.async_resolve(boost_asio::ip::tcp::resolver::query{connect_host, port}, std::placeholders::_2));
std::bind(&Client::resolveHandler, });
this,
std::placeholders::_1,
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( beast_http::async_write(sock_,
[=](boost_system::error_code const& ec) { timeoutHandler(ec); }); req,
} std::bind(&Client::writeHandler,
this,
beast_http::async_write(sock_, std::placeholders::_1,
req, std::placeholders::_2));
std::bind(&Client::writeHandler, });
this,
std::placeholders::_1,
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,27 +198,15 @@ 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( beast_http::async_read_header(sock_,
[=](boost_system::error_code const& ec) { timeoutHandler(ec); }); b,
} rp,
std::bind(&Client::readHandler,
beast_http::async_read_header(sock_, this,
b, std::placeholders::_1,
rp, std::placeholders::_2));
std::bind(&Client::readHandler, });
this,
std::placeholders::_1,
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());
} }
ssl_sock_->async_handshake( callNetworkOperation([&]() {
boost_asio::ssl::stream_base::client, ssl_sock_->async_handshake(
std::bind(&Client::handshakeHandler, this, std::placeholders::_1)); boost_asio::ssl::stream_base::client,
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,49 +302,31 @@ void Client::sendRequest(STREAM_TYPE& stream,
} }
beast_http_request_serializer sr{req}; beast_http_request_serializer sr{req};
beast_http::async_write(stream,
sr,
std::bind(&Client::writeHandler,
this,
std::placeholders::_1,
std::placeholders::_2));
{ callNetworkOperation([&]() {
boost_system::error_code rc; beast_http::async_write(stream,
ioc_.run(rc); sr,
ioc_.reset(); std::bind(&Client::writeHandler,
if (rc) { this,
ec_ = rc; std::placeholders::_1,
} std::placeholders::_2));
} });
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;
beast_http::async_read(stream, callNetworkOperation([&]() {
b, beast_http::async_read(stream,
resp, b,
std::bind(&Client::readHandler, resp,
this, std::bind(&Client::readHandler,
std::placeholders::_1, this,
std::placeholders::_2)); std::placeholders::_1,
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_;