Hi all, I am using boost 1.76.0 version. I have slightly modified the example program http_server_sync_ssl.cpp to just dump the payload it receives and i have used certificates with ssl context. When I run the program with valgrind, the "still reachable" memory keeps increasing with time. This is one example:
==17719== 38,880 bytes in 60 blocks are still reachable in loss record 740 of 740 ==17719== at 0x4C312EF: malloc (in /usr/lib64/valgrind/vgpreload_memcheck-amd64-linux.so) ==17719== by 0x567F438: CRYPTO_zalloc (in /usr/lib64/libcrypto.so.1.1) ==17719== by 0x52AA5CA: SSL_SESSION_new (in /usr/lib64/libssl.so.1.1) ==17719== by 0x52AAE22: ??? (in /usr/lib64/libssl.so.1.1) ==17719== by 0x52C8A06: ??? (in /usr/lib64/libssl.so.1.1) ==17719== by 0x52B7FF6: ??? (in /usr/lib64/libssl.so.1.1) ==17719== by 0x52A3F43: SSL_do_handshake (in /usr/lib64/libssl.so.1.1) ==17719== by 0x419630: boost::asio::ssl::detail::engine::do_accept(void*, unsigned long) (engine.ipp:316) ==17719== by 0x4193E3: boost::asio::ssl::detail::engine::perform(int (boost::asio::ssl::detail::engine::*)(void*, unsigned long), void*, unsigned long, boost::system::error_code&, unsigned long*) (engine.ipp:248) ==17719== by 0x418F6D: boost::asio::ssl::detail::engine::handshake(boost::asio::ssl::stream_base::handshake_type, boost::system::error_code&) (engine.ipp:148) ==17719== by 0x419778: boost::asio::ssl::detail::handshake_op::operator()(boost::asio::ssl::detail::engine&, boost::system::error_code&, unsigned long&) const (handshake_op.hpp:47) ==17719== by 0x424DB8: unsigned long boost::asio::ssl::detail::io<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::any_io_executor>, boost::asio::ssl::detail::handshake_op>(boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::any_io_executor>&, boost::asio::ssl::detail::stream_core&, boost::asio::ssl::detail::handshake_op const&, boost::system::error_code&) (io.hpp:38) ==17719== by 0x421332: boost::asio::ssl::stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::any_io_executor>&>::handshake(boost::asio::ssl::stream_base::handshake_type, boost::system::error_code&) (stream.hpp:389) ==17719== by 0x41D5FC: boost::beast::ssl_stream<boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::any_io_executor>&>::handshake(boost::asio::ssl::stream_base::handshake_type, boost::system::error_code&) (ssl_stream.hpp:344) ==17719== by 0x406971: do_session(boost::asio::basic_stream_socket<boost::asio::ip::tcp, boost::asio::any_io_executor>&, boost::asio::ssl::context&, std::shared_ptr<std::__cxx11::basic_string<char, std::char_traits<char>, std::allocator<char> > const> const&) (boost_server.cpp:219) I have attached the test program. Can anyone point out what needs to be done here? Thanks & Regards, Sandeep
// // Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) // // Official repository: https://github.com/boostorg/beast // //------------------------------------------------------------------------------ // // Example: HTTP SSL server, synchronous // //------------------------------------------------------------------------------ //#include "example/common/server_certificate.hpp" #include <boost/beast/core.hpp> #include <boost/beast/http.hpp> #include <boost/beast/ssl.hpp> #include <boost/beast/version.hpp> #include <boost/asio/ip/tcp.hpp> #include <boost/asio/ssl/stream.hpp> #include <boost/config.hpp> #include <cstdlib> #include <iostream> #include <memory> #include <string> #include <thread> namespace beast = boost::beast; // from <boost/beast.hpp> namespace http = beast::http; // from <boost/beast/http.hpp> namespace net = boost::asio; // from <boost/asio.hpp> namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp> using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp> // Return a reasonable mime type based on the extension of a file. beast::string_view mime_type(beast::string_view path) { using beast::iequals; auto const ext = [&path] { auto const pos = path.rfind("."); if(pos == beast::string_view::npos) return beast::string_view{}; return path.substr(pos); }(); if(iequals(ext, ".htm")) return "text/html"; if(iequals(ext, ".html")) return "text/html"; if(iequals(ext, ".php")) return "text/html"; if(iequals(ext, ".css")) return "text/css"; if(iequals(ext, ".txt")) return "text/plain"; if(iequals(ext, ".js")) return "application/javascript"; if(iequals(ext, ".json")) return "application/json"; if(iequals(ext, ".xml")) return "application/xml"; if(iequals(ext, ".swf")) return "application/x-shockwave-flash"; if(iequals(ext, ".flv")) return "video/x-flv"; if(iequals(ext, ".png")) return "image/png"; if(iequals(ext, ".jpe")) return "image/jpeg"; if(iequals(ext, ".jpeg")) return "image/jpeg"; if(iequals(ext, ".jpg")) return "image/jpeg"; if(iequals(ext, ".gif")) return "image/gif"; if(iequals(ext, ".bmp")) return "image/bmp"; if(iequals(ext, ".ico")) return "image/vnd.microsoft.icon"; if(iequals(ext, ".tiff")) return "image/tiff"; if(iequals(ext, ".tif")) return "image/tiff"; if(iequals(ext, ".svg")) return "image/svg+xml"; if(iequals(ext, ".svgz")) return "image/svg+xml"; return "application/text"; } // Append an HTTP rel-path to a local filesystem path. // The returned path is normalized for the platform. std::string path_cat( beast::string_view base, beast::string_view path) { if(base.empty()) return std::string(path); std::string result(base); #ifdef BOOST_MSVC char constexpr path_separator = '\\'; if(result.back() == path_separator) result.resize(result.size() - 1); result.append(path.data(), path.size()); for(auto& c : result) if(c == '/') c = path_separator; #else char constexpr path_separator = '/'; if(result.back() == path_separator) result.resize(result.size() - 1); result.append(path.data(), path.size()); #endif return result; } // This function produces an HTTP response for the given // request. The type of the response object depends on the // contents of the request, so the interface requires the // caller to pass a generic lambda for receiving the response. template< class Body, class Allocator, class Send> void handle_request( http::request<Body, http::basic_fields<Allocator>>&& req, Send&& send, int payloadProcessStatus) { // Returns a bad request response auto const bad_request = [&req](beast::string_view why) { http::response<http::string_body> res; res.version(11); res.result(http::status::bad_request); res.set(http::field::server, BOOST_BEAST_VERSION_STRING); res.set(http::field::content_type, "text/html"); res.keep_alive(req.keep_alive()); res.body() = std::string(why); res.prepare_payload(); return res; }; // Returns a server error response auto const server_error = [&req](beast::string_view what) { http::response<http::string_body> res; res.version(11); res.result(http::status::internal_server_error); res.set(http::field::server, BOOST_BEAST_VERSION_STRING); res.set(http::field::content_type, "text/html"); res.keep_alive(req.keep_alive()); res.body() = "An error occurred: '" + std::string(what) + "'"; res.prepare_payload(); return res; }; // Make sure we can handle the method if( req.method() != http::verb::post ) return send(bad_request("Unknown HTTP-method")); if (payloadProcessStatus == -1) return send(server_error("Internal server error")); http::response<http::string_body> res; res.version(11); res.result(http::status::ok); res.set(http::field::server, BOOST_BEAST_VERSION_STRING); res.set(http::field::content_type, "application/text"); res.keep_alive(req.keep_alive()); res.body() = "Collection request succeeded"; res.prepare_payload(); return send(std::move(res)); } //------------------------------------------------------------------------------ // Report a failure void fail(beast::error_code ec, char const* what) { std::cerr << what << ": " << ec.message() << "\n"; } // This is the C++11 equivalent of a generic lambda. // The function object is used to send an HTTP message. template<class Stream> struct send_lambda { Stream& stream_; bool& close_; beast::error_code& ec_; explicit send_lambda( Stream& stream, bool& close, beast::error_code& ec) : stream_(stream) , close_(close) , ec_(ec) { } template<bool isRequest, class Body, class Fields> void operator()(http::message<isRequest, Body, Fields>&& msg) const { // Determine if we should close the connection after close_ = msg.need_eof(); // We need the serializer here because the serializer requires // a non-const file_body, and the message oriented version of // http::write only works with const messages. http::serializer<isRequest, Body, Fields> sr{msg}; http::write(stream_, sr, ec_); } }; // Handles an HTTP server connection void do_session( tcp::socket& socket, ssl::context& ctx, std::shared_ptr<std::string const> const& doc_root) { bool close = false; beast::error_code ec; // Construct the stream around the socket beast::ssl_stream<tcp::socket&> stream{socket, ctx}; // Perform the SSL handshake stream.handshake(ssl::stream_base::server, ec); if(ec) return fail(ec, "handshake"); // This buffer is required to persist across reads beast::flat_buffer buffer; // This lambda is used to send messages send_lambda<beast::ssl_stream<tcp::socket&>> lambda{stream, close, ec}; for(;;) { // Read a request http::request<http::string_body> req; http::read(stream, buffer, req, ec); if(ec == http::error::end_of_stream) break; if(ec) return fail(ec, "read"); std::string payload = req.body(); std::cout<<"Payload : "<<payload<<std::endl; int r = 0; // Send the response handle_request(std::move(req), lambda, r); if(ec) return fail(ec, "write"); if(close) { // This means we should close the connection, usually because // the response indicated the "Connection: close" semantic. break; } } // Perform the SSL shutdown std::cout<<"Shutting down stream"<<std::endl; stream.shutdown(ec); if(ec) return fail(ec, "shutdown"); OPENSSL_thread_stop(); // At this point the connection is closed gracefully } //------------------------------------------------------------------------------ int main(int argc, char* argv[]) { try { // Check command line arguments. if (argc != 4) { std::cerr << "Usage: http-server-sync-ssl <address> <port> <doc_root>\n" << "Example:\n" << " http-server-sync-ssl 0.0.0.0 8080 .\n"; return EXIT_FAILURE; } auto const address = net::ip::make_address(argv[1]); auto const port = static_cast<unsigned short>(std::atoi(argv[2])); auto const doc_root = std::make_shared<std::string>(argv[3]); // The io_context is required for all I/O net::io_context ioc{1}; // The SSL context is required, and holds certificates ssl::context ctx{ssl::context::tlsv12}; ctx.load_verify_file("/tmp/ca.crt"); ctx.use_certificate_file("/tmp/server.crt", ssl::context::file_format::pem); ctx.use_rsa_private_key_file("/tmp/server.key", ssl::context::file_format::pem); // The acceptor receives incoming connections tcp::acceptor acceptor{ioc, {address, port}}; for(;;) { // This will receive the new connection tcp::socket socket{ioc}; // Block until we get a connection acceptor.accept(socket); // Launch the session, transferring ownership of the socket std::thread{std::bind( &do_session, std::move(socket), std::ref(ctx), doc_root)}.detach(); } } catch (const std::exception& e) { std::cerr << "Error: " << e.what() << std::endl; return EXIT_FAILURE; } }
_______________________________________________ Boost-users mailing list Boost-users@lists.boost.org https://lists.boost.org/mailman/listinfo.cgi/boost-users