make Universal PIC.

This commit is contained in:
luocai 2024-01-17 11:56:24 +08:00
parent edeb230c46
commit e05d90f1b3
3 changed files with 123 additions and 72 deletions

View File

@ -96,7 +96,14 @@ std::vector<ParseItem> parseFormData(const std::string_view &buffer) {
return ret; return ret;
} }
Client::Client(boost::asio::io_context &ioContext, Type type, Version version) : m_ioContext(ioContext) { class ClientPrivate {
public:
std::unique_ptr<boost::beast::ssl_stream<boost::beast::tcp_stream>> sslStream;
std::unique_ptr<boost::beast::tcp_stream> tcpStream;
};
Client::Client(boost::asio::io_context &ioContext, Type type, Version version)
: m_d(new ClientPrivate()), m_ioContext(ioContext) {
m_request.version(static_cast<unsigned>(version)); m_request.version(static_cast<unsigned>(version));
using namespace boost::asio; using namespace boost::asio;
using namespace boost::beast; 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) { void Client::loadRootCertificates(boost::system::error_code &error) {
if (m_sslContext) { if (m_sslContext) {
load_root_certificates(*m_sslContext, error); 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, std::string Client::execute(const std::string &host, const std::string &port, const Request &request,
boost::system::error_code &error) { boost::system::error_code &error) {
using namespace boost::asio::ip;
using namespace boost::beast; using namespace boost::beast;
tcp::resolver resolver(m_ioContext); if ((m_host != host) || (m_port != port) || (!m_d->sslStream && !m_d->tcpStream)) {
auto const results = resolver.resolve(host, port, error); if (m_d->sslStream || m_d->tcpStream) {
boost::system::error_code errorCode;
shutdown(errorCode);
if (errorCode) {
LOG(error) << errorCode.message();
}
}
connect(host, port, error);
if (error) { if (error) {
return std::string(); return std::string();
} }
}
std::unique_ptr<ssl_stream<tcp_stream>> sslStream; if (m_d->sslStream) {
std::unique_ptr<tcp_stream> tcpStream; http::write(*m_d->sslStream, request, error);
if (m_sslContext) { } else if (m_d->tcpStream) {
if (m_certificateLocation == CertificateLocation::None) { http::write(*m_d->tcpStream, request, error);
m_sslContext->set_default_verify_paths(error);
if (!error) m_certificateLocation = CertificateLocation::SystemDependent;
}
sslStream = std::make_unique<ssl_stream<tcp_stream>>(m_ioContext, *m_sslContext);
get_lowest_layer(*sslStream).connect(results, error);
if (error) {
return std::string();
}
sslStream->handshake(ssl::stream_base::client, error);
} else {
tcpStream = std::make_unique<tcp_stream>(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);
} }
http::response<http::dynamic_body> response; http::response<http::dynamic_body> response;
if (!error) { if (!error) {
flat_buffer buffer; flat_buffer buffer;
if (sslStream) { if (m_d->sslStream) {
http::read(*sslStream, buffer, response, error); http::read(*m_d->sslStream, buffer, response, error);
error_code ec; } else if (m_d->tcpStream) {
sslStream->shutdown(ec); http::read(*m_d->tcpStream, buffer, response, error);
} else if (tcpStream) {
http::read(*tcpStream, buffer, response, error);
error_code ec;
tcpStream->socket().shutdown(tcp::socket::shutdown_both, ec);
} }
} }
return boost::beast::buffers_to_string(response.body().data()); 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<ssl_stream<tcp_stream>>(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<tcp_stream>(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 } // namespace Http

View File

@ -68,27 +68,34 @@ struct ParseItem {
*/ */
static std::vector<ParseItem> parseFormData(const std::string_view &buffer); static std::vector<ParseItem> parseFormData(const std::string_view &buffer);
class ClientPrivate;
class Client { class Client {
public: public:
Client(boost::asio::io_context &ioContext, Type type, Version version = Version_1_1); Client(boost::asio::io_context &ioContext, Type type, Version version = Version_1_1);
~Client();
void loadRootCertificates(boost::system::error_code &error); void loadRootCertificates(boost::system::error_code &error);
std::string get(const std::string &host, const std::string &port, const std::string &url, std::string get(const std::string &host, const std::string &port, const std::string &url,
boost::system::error_code &error); boost::system::error_code &error);
std::string post(const std::string &host, const std::string &port, const std::string &url, std::string post(const std::string &host, const std::string &port, const std::string &url, const std::string &body,
const std::string &body, boost::system::error_code &error); boost::system::error_code &error);
std::string put(const std::string &host, const std::string &port, const std::string &url, std::string put(const std::string &host, const std::string &port, const std::string &url, const std::string &body,
const std::string &body, boost::system::error_code &error); boost::system::error_code &error);
void addRequestField(boost::beast::http::field name, const std::string &value); void addRequestField(boost::beast::http::field name, const std::string &value);
protected: protected:
std::string execute(const std::string &host, const std::string &port, const Request &request, std::string execute(const std::string &host, const std::string &port, const Request &request,
boost::system::error_code &error); 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);
private: private:
ClientPrivate *m_d = nullptr;
boost::asio::io_context &m_ioContext; boost::asio::io_context &m_ioContext;
std::shared_ptr<boost::asio::ssl::context> m_sslContext; std::shared_ptr<boost::asio::ssl::context> m_sslContext;
CertificateLocation m_certificateLocation = CertificateLocation::None; CertificateLocation m_certificateLocation = CertificateLocation::None;
std::string m_host;
std::string m_port;
Request m_request; Request m_request;
}; };

View File

@ -15,6 +15,10 @@ add_library(Universal
StringUtility.h StringUtility.cpp StringUtility.h StringUtility.cpp
) )
set_property(TARGET Universal
PROPERTY POSITION_INDEPENDENT_CODE ON
)
if(CMAKE_VERSION VERSION_LESS 3.20) if(CMAKE_VERSION VERSION_LESS 3.20)
get_filename_component(KYLIN_CORE_INCLUDE_PATH ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY) get_filename_component(KYLIN_CORE_INCLUDE_PATH ${CMAKE_CURRENT_SOURCE_DIR} DIRECTORY)
if(NOT Boost_USE_STATIC_LIBS) if(NOT Boost_USE_STATIC_LIBS)