#include "NetworkUtility.h" #include "BoostLog.h" #include #include #include #include #include static std::optional> makeSslStream(boost::asio::io_context &ioContext, const std::string_view &host, const std::string_view &port, boost::system::error_code &error); std::string Https::get(boost::asio::io_context &ioContext, const std::string_view &host, const std::string_view &port, const std::string_view &url, boost::system::error_code &error, Http::Version version) { namespace beast = boost::beast; namespace http = boost::beast::http; auto stream = makeSslStream(ioContext, host, port, error); if (!stream) return std::string(); http::request req{http::verb::get, url, static_cast(version)}; req.set(http::field::host, host); req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); http::write(*stream, req, error); if (error) { // LOG(error) << error.message(); return std::string(); } beast::flat_buffer buffer; http::response_parser parser; parser.body_limit(std::numeric_limits::max()); http::read(*stream, buffer, parser, error); if (error) { LOG(error) << error.message(); return std::string(); } beast::error_code ec; stream->shutdown(ec); return boost::beast::buffers_to_string(parser.get().body().data()); } std::string Https::post(boost::asio::io_context &ioContext, const std::string_view &host, const std::string_view &port, const std::string_view &url, const std::string_view &body, boost::system::error_code &error, Http::Version version) { namespace beast = boost::beast; namespace http = boost::beast::http; auto stream = makeSslStream(ioContext, host, port, error); if (!stream) return std::string(); http::request req{http::verb::post, url.data(), static_cast(version)}; req.set(http::field::host, host); req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); req.body() = body; req.prepare_payload(); http::write(*stream, req, error); if (error) { LOG(error) << error.message(); return std::string(); } beast::flat_buffer buffer; http::response response; http::read(*stream, buffer, response, error); if (error) { LOG(error) << error.message(); return std::string(); } beast::error_code ec; stream->shutdown(ec); return boost::beast::buffers_to_string(response.body().data()); } std::string Https::put(boost::asio::io_context &ioContext, const std::string &host, const std::string &port, const std::string &url, const std::string &body, boost::system::error_code &error, Http::Version version) { namespace beast = boost::beast; namespace http = boost::beast::http; auto stream = makeSslStream(ioContext, host, port, error); if (!stream) return std::string(); http::request req{http::verb::put, url.data(), static_cast(version)}; req.set(http::field::host, host); req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING); req.body() = body; req.prepare_payload(); http::write(*stream, req, error); if (error) { LOG(error) << error.message(); return std::string(); } beast::flat_buffer buffer; http::response response; http::read(*stream, buffer, response, error); if (error) { LOG(error) << error.message(); return std::string(); } beast::error_code ec; stream->shutdown(ec); return boost::beast::buffers_to_string(response.body().data()); } static std::optional> makeSslStream(boost::asio::io_context &ioContext, const std::string_view &host, const std::string_view &port, boost::system::error_code &error) { namespace beast = boost::beast; namespace http = boost::beast::http; namespace asio = boost::asio; // from using tcp = asio::ip::tcp; namespace ssl = asio::ssl; ssl::context sslContext(ssl::context::sslv23_client); sslContext.set_default_verify_paths(error); if (error) { LOG(error) << error.message(); return std::nullopt; } boost::asio::ip::tcp::resolver resolver(ioContext); beast::ssl_stream stream(ioContext, sslContext); auto const results = resolver.resolve(host, port, error); if (error) { LOG(error) << error.message(); return std::nullopt; } beast::get_lowest_layer(stream).connect(results); stream.handshake(ssl::stream_base::client); return std::make_optional(std::move(stream)); } std::vector Http::parseFormData(const std::string_view &buffer) { std::vector ret; auto pos = buffer.find("\r\n"); std::string_view m_spliter = buffer.substr(0, pos); size_t m_end = buffer.rfind(m_spliter); pos = 0; while (pos != m_end) { pos = buffer.find(m_spliter, pos); if (pos == m_end) break; ParseItem item; auto dataSpliterPos = buffer.find("\r\n\r\n", pos); item.begin = dataSpliterPos + 4; item.end = buffer.find(m_spliter, pos + 1) - 2; auto meta = buffer.substr(pos, dataSpliterPos - pos); auto beginPos = meta.find("filename=\"") + 10; auto endPos = meta.find("\"", beginPos); item.filename = meta.substr(beginPos, endPos - beginPos); pos++; ret.push_back(item); } return ret; } uint64_t Network::htonll(uint64_t val) { return (static_cast(htonl(static_cast(val))) << 32) + htonl(val >> 32); } uint64_t Network::ntohll(uint64_t val) { return (static_cast(ntohl(static_cast(val))) << 32) + ntohl(val >> 32); } bool Network::isConnected(const std::string_view &host, size_t size) { std::ostringstream oss; #ifdef __linux__ oss << "ping " << host << " -q -W2 -c" << size; #else oss << "ping -n " << size << " " << host; #endif auto ret = std::system(oss.str().data()); return ret == 0; } #ifdef WIN32 #include #endif Network::Network(int argc, char *argv[]) { #ifdef WIN32 WORD wVersionRequested = MAKEWORD(2, 2); WSADATA wsaData; ::WSAStartup(wVersionRequested, &wsaData); LOG(info) << "WinSock initialized complete."; #endif } Network::~Network() { #ifdef WIN32 ::WSACleanup(); #endif }