From e05d90f1b39b343c6a5a0a31cbee7944e9ac9a84 Mon Sep 17 00:00:00 2001 From: luocai Date: Wed, 17 Jan 2024 11:56:24 +0800 Subject: [PATCH] make Universal PIC. --- HttpProxy/NetworkUtility.cpp | 110 ++++++++++++++++++++++++----------- HttpProxy/NetworkUtility.h | 81 ++++++++++++++------------ Universal/CMakeLists.txt | 4 ++ 3 files changed, 123 insertions(+), 72 deletions(-) diff --git a/HttpProxy/NetworkUtility.cpp b/HttpProxy/NetworkUtility.cpp index eef05cb..698d35e 100644 --- a/HttpProxy/NetworkUtility.cpp +++ b/HttpProxy/NetworkUtility.cpp @@ -96,7 +96,14 @@ std::vector parseFormData(const std::string_view &buffer) { return ret; } -Client::Client(boost::asio::io_context &ioContext, Type type, Version version) : m_ioContext(ioContext) { +class ClientPrivate { +public: + std::unique_ptr> sslStream; + std::unique_ptr tcpStream; +}; + +Client::Client(boost::asio::io_context &ioContext, Type type, Version version) + : m_d(new ClientPrivate()), m_ioContext(ioContext) { m_request.version(static_cast(version)); using namespace boost::asio; using namespace boost::beast; @@ -107,6 +114,15 @@ Client::Client(boost::asio::io_context &ioContext, Type type, Version version) : } } +Client::~Client() { + boost::system::error_code error; + shutdown(error); + if (error) { + LOG(error) << error.message(); + } + if (m_d != nullptr) delete m_d; +} + void Client::loadRootCertificates(boost::system::error_code &error) { if (m_sslContext) { load_root_certificates(*m_sslContext, error); @@ -153,57 +169,81 @@ void Client::addRequestField(boost::beast::http::field name, const std::string & std::string Client::execute(const std::string &host, const std::string &port, const Request &request, boost::system::error_code &error) { - using namespace boost::asio::ip; using namespace boost::beast; - tcp::resolver resolver(m_ioContext); - auto const results = resolver.resolve(host, port, error); - if (error) { - return std::string(); - } - - std::unique_ptr> sslStream; - std::unique_ptr tcpStream; - if (m_sslContext) { - if (m_certificateLocation == CertificateLocation::None) { - m_sslContext->set_default_verify_paths(error); - if (!error) m_certificateLocation = CertificateLocation::SystemDependent; + if ((m_host != host) || (m_port != port) || (!m_d->sslStream && !m_d->tcpStream)) { + if (m_d->sslStream || m_d->tcpStream) { + boost::system::error_code errorCode; + shutdown(errorCode); + if (errorCode) { + LOG(error) << errorCode.message(); + } } - sslStream = std::make_unique>(m_ioContext, *m_sslContext); - get_lowest_layer(*sslStream).connect(results, error); + connect(host, port, error); if (error) { return std::string(); } - sslStream->handshake(ssl::stream_base::client, error); - } else { - tcpStream = std::make_unique(m_ioContext); - tcpStream->connect(results, error); - } - if (error) { - return std::string(); } - if (sslStream) { - http::write(*sslStream, request, error); - } else if (tcpStream) { - http::write(*tcpStream, request, error); + if (m_d->sslStream) { + http::write(*m_d->sslStream, request, error); + } else if (m_d->tcpStream) { + http::write(*m_d->tcpStream, request, error); } http::response response; if (!error) { flat_buffer buffer; - if (sslStream) { - http::read(*sslStream, buffer, response, error); - error_code ec; - sslStream->shutdown(ec); - } else if (tcpStream) { - http::read(*tcpStream, buffer, response, error); - error_code ec; - tcpStream->socket().shutdown(tcp::socket::shutdown_both, ec); + if (m_d->sslStream) { + http::read(*m_d->sslStream, buffer, response, error); + } else if (m_d->tcpStream) { + http::read(*m_d->tcpStream, buffer, response, error); } } return boost::beast::buffers_to_string(response.body().data()); } +void Client::connect(const std::string &host, const std::string &port, boost::system::error_code &error) { + using namespace boost::asio::ip; + using namespace boost::beast; + tcp::resolver resolver(m_ioContext); + auto const results = resolver.resolve(host, port, error); + if (error) { + return; + } + + if (m_sslContext) { + if (m_certificateLocation == CertificateLocation::None) { + m_sslContext->set_default_verify_paths(error); + if (!error) m_certificateLocation = CertificateLocation::SystemDependent; + } + m_d->sslStream = std::make_unique>(m_ioContext, *m_sslContext); + get_lowest_layer(*m_d->sslStream).connect(results, error); + if (error) { + return; + } + m_d->sslStream->handshake(ssl::stream_base::client, error); + } else { + m_d->tcpStream = std::make_unique(m_ioContext); + m_d->tcpStream->connect(results, error); + } + if (error) { + return; + } + m_host = host; + m_port = port; +} + +void Client::shutdown(boost::system::error_code &error) { + using namespace boost::asio::ip; + if (m_d->sslStream) { + m_d->sslStream->shutdown(error); + m_d->sslStream.reset(); + } else if (m_d->tcpStream) { + m_d->tcpStream->socket().shutdown(tcp::socket::shutdown_both, error); + m_d->tcpStream.reset(); + } +} + } // namespace Http diff --git a/HttpProxy/NetworkUtility.h b/HttpProxy/NetworkUtility.h index 3f8319e..51c8c30 100644 --- a/HttpProxy/NetworkUtility.h +++ b/HttpProxy/NetworkUtility.h @@ -52,47 +52,54 @@ struct ParseItem { size_t end; }; - /** - * @brief - * - * @param buffer - * @return std::vector - * @example auto items = parseFormData(request.body()); - * for (auto &item : items) { - * std::string filename("E:/"); - * filename += item.filename; - * std::ofstream ofs(filename.c_str(), std::ios::binary); - * ofs.write(buffer.data() + item.begin, item.end - item.begin); - * ofs.close(); - * } - */ - static std::vector parseFormData(const std::string_view &buffer); +/** + * @brief + * + * @param buffer + * @return std::vector + * @example auto items = parseFormData(request.body()); + * for (auto &item : items) { + * std::string filename("E:/"); + * filename += item.filename; + * std::ofstream ofs(filename.c_str(), std::ios::binary); + * ofs.write(buffer.data() + item.begin, item.end - item.begin); + * ofs.close(); + * } + */ +static std::vector parseFormData(const std::string_view &buffer); - class Client { - public: - Client(boost::asio::io_context &ioContext, Type type, Version version = Version_1_1); - void loadRootCertificates(boost::system::error_code &error); - std::string get(const std::string &host, const std::string &port, const std::string &url, +class ClientPrivate; +class Client { +public: + Client(boost::asio::io_context &ioContext, Type type, Version version = Version_1_1); + ~Client(); + void loadRootCertificates(boost::system::error_code &error); + std::string get(const std::string &host, const std::string &port, const std::string &url, + boost::system::error_code &error); + std::string post(const std::string &host, const std::string &port, const std::string &url, const std::string &body, + boost::system::error_code &error); + std::string put(const std::string &host, const std::string &port, const std::string &url, const std::string &body, + boost::system::error_code &error); + + void addRequestField(boost::beast::http::field name, const std::string &value); + +protected: + std::string execute(const std::string &host, const std::string &port, const Request &request, boost::system::error_code &error); - std::string post(const std::string &host, const std::string &port, const std::string &url, - const std::string &body, boost::system::error_code &error); - std::string put(const std::string &host, const std::string &port, const std::string &url, - const std::string &body, boost::system::error_code &error); + void connect(const std::string &host, const std::string &port, boost::system::error_code &error); + void shutdown(boost::system::error_code &error); - void addRequestField(boost::beast::http::field name, const std::string &value); +private: + ClientPrivate *m_d = nullptr; + boost::asio::io_context &m_ioContext; + std::shared_ptr m_sslContext; + CertificateLocation m_certificateLocation = CertificateLocation::None; + std::string m_host; + std::string m_port; + Request m_request; +}; - protected: - std::string execute(const std::string &host, const std::string &port, const Request &request, - boost::system::error_code &error); - - private: - boost::asio::io_context &m_ioContext; - std::shared_ptr m_sslContext; - CertificateLocation m_certificateLocation = CertificateLocation::None; - Request m_request; - }; - - } // namespace Http +} // namespace Http class Https { public: diff --git a/Universal/CMakeLists.txt b/Universal/CMakeLists.txt index 2840ff1..c733c52 100644 --- a/Universal/CMakeLists.txt +++ b/Universal/CMakeLists.txt @@ -15,6 +15,10 @@ add_library(Universal StringUtility.h StringUtility.cpp ) +set_property(TARGET Universal + PROPERTY POSITION_INDEPENDENT_CODE ON +) + if(CMAKE_VERSION VERSION_LESS 3.20) get_filename_component(KYLIN_CORE_INCLUDE_PATH ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) if(NOT Boost_USE_STATIC_LIBS)