Skip to content

Commit

Permalink
Update SSL context variable names
Browse files Browse the repository at this point in the history
  • Loading branch information
riccardodebenedictis committed Feb 8, 2024
1 parent f40fc29 commit 27954ce
Show file tree
Hide file tree
Showing 8 changed files with 211 additions and 13 deletions.
4 changes: 2 additions & 2 deletions include/async_server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -151,7 +151,7 @@ namespace network::async
class session_detector : public network::session_detector, public std::enable_shared_from_this<session_detector>
{
public:
session_detector(network::server &srv, boost::asio::ip::tcp::socket &&socket, boost::asio::ssl::context &ctx) : network::session_detector(srv, std::move(socket), ctx) {}
session_detector(network::server &srv, boost::asio::ip::tcp::socket &&socket, boost::asio::ssl::context &ssl_ctx) : network::session_detector(srv, std::move(socket), ssl_ctx) {}

void run() override;

Expand All @@ -163,7 +163,7 @@ namespace network::async
class ssl_session : public network::ssl_session, public std::enable_shared_from_this<ssl_session>
{
public:
ssl_session(network::server &srv, boost::beast::tcp_stream &&str, boost::asio::ssl::context &ctx, boost::beast::flat_buffer &&buffer) : network::ssl_session(srv, std::move(str), ctx, std::move(buffer)) {}
ssl_session(network::server &srv, boost::beast::tcp_stream &&str, boost::asio::ssl::context &ssl_ctx, boost::beast::flat_buffer &&buffer) : network::ssl_session(srv, std::move(str), ssl_ctx, std::move(buffer)) {}

void run() override;
void do_eof() override;
Expand Down
183 changes: 183 additions & 0 deletions include/client.hpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,183 @@
#pragma once

#include <boost/beast.hpp>
#include <boost/asio.hpp>
#ifdef USE_SSL
#include <boost/asio/ssl.hpp>
#include <boost/beast/ssl.hpp>
#endif

namespace network
{
template <class Derived>
class base_client
{
Derived &derived() { return static_cast<Derived &>(*this); }

public:
base_client(const std::string &host, const std::string &port) : host(host), port(port), resolver(ioc)
{
boost::beast::error_code ec;
auto results = resolver.resolve(host, port, ec);
if (ec)
throw boost::beast::system_error{ec};
}
virtual ~base_client() = default;

virtual void connect() = 0;

/**
* @brief Send a GET request.
*
* @param target The target of the request.
* @param fields The fields to send with the request.
*/
template <class Body>
boost::beast::http::response<Body> get(const std::string &target, const std::unordered_map<boost::beast::http::field, std::string> &fields = {})
{
boost::beast::http::request<boost::beast::http::string_body> req{boost::beast::http::verb::get, target, 11};
req.set(boost::beast::http::field::host, host);
req.set(boost::beast::http::field::user_agent, "ratioNet");
for (auto &field : fields)
req.set(field.first, field.second);
return send<boost::beast::http::string_body, Body>(std::move(req));
}

/**
* @brief Send a POST request.
*
* @param target The target of the request.
* @param body The body of the request.
* @param fields The fields to send with the request.
*/
template <class Body>
boost::beast::http::response<Body> post(const std::string &target, const std::string &body, const std::unordered_map<boost::beast::http::field, std::string> &fields = {})
{
boost::beast::http::request<boost::beast::http::string_body> req{boost::beast::http::verb::post, target, 11};
req.set(boost::beast::http::field::host, host);
req.set(boost::beast::http::field::user_agent, "ratioNet");
for (auto &field : fields)
req.set(field.first, field.second);
req.body() = body;
return send<boost::beast::http::string_body, Body>(std::move(req));
}

/**
* @brief Send a PUT request.
*
* @param target The target of the request.
* @param body The body of the request.
* @param fields The fields to send with the request.
*/
template <class Body>
boost::beast::http::response<Body> put(const std::string &target, const std::string &body, const std::unordered_map<boost::beast::http::field, std::string> &fields = {})
{
boost::beast::http::request<boost::beast::http::string_body> req{boost::beast::http::verb::put, target, 11};
req.set(boost::beast::http::field::host, host);
req.set(boost::beast::http::field::user_agent, "ratioNet");
for (auto &field : fields)
req.set(field.first, field.second);
req.body() = body;
return send<boost::beast::http::string_body, Body>(std::move(req));
}

/**
* @brief Send a PATCH request.
*
* @param target The target of the request.
* @param body The body of the request.
* @param fields The fields to send with the request.
*/
template <class Body>
boost::beast::http::response<Body> patch(const std::string &target, const std::string &body, const std::unordered_map<boost::beast::http::field, std::string> &fields = {})
{
boost::beast::http::request<boost::beast::http::string_body> req{boost::beast::http::verb::patch, target, 11};
req.set(boost::beast::http::field::host, host);
req.set(boost::beast::http::field::user_agent, "ratioNet");
for (auto &field : fields)
req.set(field.first, field.second);
req.body() = body;
return send<boost::beast::http::string_body, Body>(std::move(req));
}

/**
* @brief Send a DELETE request.
*
* @param target The target of the request.
* @param fields The fields to send with the request.
*/
template <class Body>
boost::beast::http::response<Body> del(const std::string &target, const std::unordered_map<boost::beast::http::field, std::string> &fields = {})
{
boost::beast::http::request<boost::beast::http::empty_body> req{boost::beast::http::verb::delete_, target, 11};
req.set(boost::beast::http::field::host, host);
req.set(boost::beast::http::field::user_agent, "ratioNet");
for (auto &field : fields)
req.set(field.first, field.second);
return send<boost::beast::http::empty_body, Body>(std::move(req));
}

template <class ReqBody, class ResBody>
boost::beast::http::response<ResBody> send(boost::beast::http::request<ReqBody> &&req)
{
req.prepare_payload();
boost::beast::http::response<ResBody> res;
boost::beast::get_lowest_layer(derived().get_stream()).expires_after(std::chrono::seconds(30));
boost::beast::error_code ec;
boost::beast::http::write(derived().get_stream(), req, ec);
if (ec)
throw boost::beast::system_error{ec};
boost::beast::flat_buffer buffer;
boost::beast::http::read(derived().get_stream(), buffer, res, ec);
if (ec)
throw boost::beast::system_error{ec};
return res;
}

virtual void disconnect() = 0;

protected:
std::string host;
std::string port;
boost::asio::io_context ioc;
boost::asio::ip::tcp::resolver resolver;
boost::beast::flat_buffer buffer;
};

class client : public base_client<client>
{
public:
client(const std::string &host, const std::string &port) : base_client(host, port) { connect(); }
~client() { disconnect(); }

boost::beast::tcp_stream &get_stream() { return stream; }

void connect() override { stream.connect(resolver.resolve(host, port)); }
void disconnect() override { stream.socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both); }

protected:
boost::beast::tcp_stream stream{ioc};
};

#ifdef USE_SSL
class ssl_client : public base_client<ssl_client>
{
public:
ssl_client(const std::string &host, const std::string &port) : base_client(host, port) { connect(); }
~ssl_client() { disconnect(); }

boost::beast::ssl_stream<boost::beast::tcp_stream> &get_stream() { return stream; }

void connect() override
{
stream.next_layer().connect(resolver.resolve(host, port));
stream.handshake(boost::asio::ssl::stream_base::client);
}
void disconnect() override { stream.next_layer().socket().shutdown(boost::asio::ip::tcp::socket::shutdown_both); }

protected:
boost::asio::ssl::context ssl_ctx{boost::asio::ssl::context::TLS_VERSION};
boost::beast::ssl_stream<boost::beast::tcp_stream> stream{ioc, ssl_ctx};
};
#endif
} // namespace network
6 changes: 3 additions & 3 deletions include/http_session.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,7 @@ namespace network
class session_detector
{
public:
session_detector(server &srv, boost::asio::ip::tcp::socket &&socket, boost::asio::ssl::context &ctx) : srv(srv), stream(std::move(socket)), ctx(ctx) {}
session_detector(server &srv, boost::asio::ip::tcp::socket &&socket, boost::asio::ssl::context &ssl_ctx) : srv(srv), stream(std::move(socket)), ssl_ctx(ssl_ctx) {}

virtual void run() = 0;

Expand All @@ -95,14 +95,14 @@ namespace network
protected:
server &srv;
boost::beast::tcp_stream stream;
boost::asio::ssl::context &ctx;
boost::asio::ssl::context &ssl_ctx;
boost::beast::flat_buffer buffer;
};

class ssl_session : public http_session
{
public:
ssl_session(server &srv, boost::beast::tcp_stream &&str, boost::asio::ssl::context &ctx, boost::beast::flat_buffer &&buffer) : http_session(srv, std::move(buffer)), stream(std::move(str), ctx) {}
ssl_session(server &srv, boost::beast::tcp_stream &&str, boost::asio::ssl::context &ssl_ctx, boost::beast::flat_buffer &&buffer) : http_session(srv, std::move(buffer)), stream(std::move(str), ssl_ctx) {}

protected:
boost::beast::ssl_stream<boost::beast::tcp_stream> stream;
Expand Down
2 changes: 1 addition & 1 deletion include/server.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -58,7 +58,7 @@ namespace network
std::unordered_map<boost::beast::http::verb, std::vector<std::pair<std::regex, std::unique_ptr<http_handler>>>> http_routes;
std::vector<std::pair<std::regex, std::unique_ptr<websocket_handler>>> ws_routes;
#ifdef USE_SSL
boost::asio::ssl::context ctx{boost::asio::ssl::context::TLS_VERSION}; // The SSL context is required, and holds certificates
boost::asio::ssl::context ssl_ctx{boost::asio::ssl::context::TLS_VERSION}; // The SSL context is required, and holds certificates
std::unordered_map<boost::beast::http::verb, std::vector<std::pair<std::regex, std::unique_ptr<http_handler>>>> https_routes;
std::vector<std::pair<std::regex, std::unique_ptr<websocket_handler>>> wss_routes;
#endif
Expand Down
4 changes: 2 additions & 2 deletions src/async_server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ namespace network::async
{
log_handler("Accepted connection from " + socket.remote_endpoint().address().to_string());
#ifdef USE_SSL
std::make_shared<session_detector>(*this, std::move(socket), ctx)->run();
std::make_shared<session_detector>(*this, std::move(socket), ssl_ctx)->run();
#else
boost::beast::tcp_stream stream(std::move(socket));
boost::beast::flat_buffer buffer;
Expand Down Expand Up @@ -145,7 +145,7 @@ namespace network::async
if (ec)
return fire_on_error(ec);
else if (result)
std::make_shared<ssl_session>(srv, std::move(stream), ctx, std::move(buffer))->run();
std::make_shared<ssl_session>(srv, std::move(stream), ssl_ctx, std::move(buffer))->run();
else
std::make_shared<plain_session>(srv, std::move(stream), std::move(buffer))->run();
}
Expand Down
8 changes: 4 additions & 4 deletions src/server.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -66,10 +66,10 @@ namespace network
#ifdef USE_SSL
void server::set_ssl_context(const std::string &cert_chain_file, const std::string &private_key_file, const std::string &tmp_dh_file)
{
ctx.set_options(boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::no_sslv3 | boost::asio::ssl::context::single_dh_use);
ctx.use_certificate_chain_file(cert_chain_file);
ctx.use_private_key_file(private_key_file, boost::asio::ssl::context::pem);
ctx.use_tmp_dh_file(tmp_dh_file);
ssl_ctx.set_options(boost::asio::ssl::context::default_workarounds | boost::asio::ssl::context::no_sslv2 | boost::asio::ssl::context::no_sslv3 | boost::asio::ssl::context::single_dh_use);
ssl_ctx.use_certificate_chain_file(cert_chain_file);
ssl_ctx.use_private_key_file(private_key_file, boost::asio::ssl::context::pem);
ssl_ctx.use_tmp_dh_file(tmp_dh_file);
}

websocket_handler &server::wss(const std::string &target)
Expand Down
6 changes: 5 additions & 1 deletion tests/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
add_executable(server_tests test_server.cpp)
target_link_libraries(server_tests PRIVATE ratioNet)

add_test(NAME serverTest00 COMMAND server_tests WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
add_executable(client_tests test_client.cpp)
target_link_libraries(client_tests PRIVATE ratioNet)

add_test(NAME serverTest00 COMMAND server_tests WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
add_test(NAME clientTest00 COMMAND client_tests WORKING_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR})
11 changes: 11 additions & 0 deletions tests/test_client.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
#include <iostream>
#include "client.hpp"

int main(int argc, char const *argv[])
{
network::client client{"localhost", "8080"};
auto res = client.get<boost::beast::http::string_body>("/");
std::cout << res << std::endl;

return 0;
}

0 comments on commit 27954ce

Please sign in to comment.