in src/WebProxyAdapter.cpp [105:169]
void WebProxyAdapter::on_http_connect_write() {
BOOST_LOG_SEV(*log, trace) << "Waiting for HTTP CONNECT response from the Web proxy";
char *response_buffer = new char[BUFFER_SIZE_IN_BYTES];
read_buffer = boost::asio::buffer(response_buffer, BUFFER_SIZE_IN_BYTES);
auto on_read = [this, response_buffer](error_code const &ec,
std::size_t bytes_transferred){
if (ec) {
BOOST_LOG_SEV(*log, error) << (boost::format(
"Could not read HTTP CONNECT response from the Web proxy: %1%") % ec.message()).str();
(*on_tcp_tunnel)(WebProxyAdapterErrc::ServerError);
}
BOOST_LOG_SEV(*log, trace) << "Parsing the HTTPS response from the Web proxy";
boost::ignore_unused(bytes_transferred);
error_code parser_ec{};
http::response_parser<http::string_body> parser{response};
parser.put(boost::asio::buffer(read_buffer),parser_ec);
response = parser.release();
const http::status_class status_class = http::to_status_class(response.result());
if (status_class != http::status_class::successful) {
BOOST_LOG_SEV(*log, error) << boost::format(
"HTTP CONNECT request failed with response code: %1%(%2%)") % response.result_int() %
response.result();
}
BOOST_LOG_SEV(*log, debug) << "Full response from the Web proxy:\n"
<< boost::beast::buffers_to_string(read_buffer);
switch (status_class) {
case http::status_class::successful:
if (response.result() == http::status::ok) {
BOOST_LOG_SEV(*log, info) << "TCP tunnel established successfully";
} else {
BOOST_LOG_SEV(*log, warning)
<< "TCP tunnel established but with unexpected response code from the Web proxy";
}
(*on_tcp_tunnel)(WebProxyAdapterErrc::Success);
break;
case http::status_class::redirection:
BOOST_LOG_SEV(*log, error) << "Make sure you're using the correct Web proxy address";
(*on_tcp_tunnel)(WebProxyAdapterErrc::RedirectionError);
break;
case http::status_class::client_error:
BOOST_LOG_SEV(*log, error) << "Make sure the Web proxy is configured properly";
(*on_tcp_tunnel)(WebProxyAdapterErrc::ClientError);
break;
case http::status_class::server_error:
BOOST_LOG_SEV(*log, error) << "Web proxy error, make sure to check your server's logs";
(*on_tcp_tunnel)(WebProxyAdapterErrc::ServerError);
break;
default:
BOOST_LOG_SEV(*log, error) << "Unexpected response code";
(*on_tcp_tunnel)(WebProxyAdapterErrc::OtherHttpError);
break;
}
delete[] response_buffer;
};
// Initially I tried to use boost::beast::http::async_read, but for some reason the beast implementation
// of that method disrupted the TCP connection causing "stream truncated" error during the SSL handshake
// with the proxy server. So I had to read from the TCP socket directly and parse the response. This could
// be something to test when we upgrade to a newer version of boost to see if boost::beast::http::async_read
// is fixed in it or not.
if (localproxy_config.is_web_proxy_using_tls) {
websocket_stream->get_web_proxy_ssl_stream()->async_read_some(read_buffer, on_read);
} else {
websocket_stream->get_tcp_socket().async_receive(read_buffer, on_read);
}
}