void WebProxyAdapter::on_http_connect_write()

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);
                }
            }