3#include "data/LedgerCacheInterface.hpp"
4#include "util/Taggable.hpp"
5#include "util/log/Logger.hpp"
6#include "web/AdminVerificationStrategy.hpp"
7#include "web/HttpSession.hpp"
8#include "web/ProxyIpResolver.hpp"
9#include "web/SslHttpSession.hpp"
10#include "web/dosguard/DOSGuardInterface.hpp"
11#include "web/interface/Concepts.hpp"
12#include "web/ng/impl/ServerSslContext.hpp"
14#include <boost/asio/io_context.hpp>
15#include <boost/asio/ip/address.hpp>
16#include <boost/asio/ip/tcp.hpp>
17#include <boost/asio/socket_base.hpp>
18#include <boost/asio/spawn.hpp>
19#include <boost/asio/ssl/context.hpp>
20#include <boost/asio/ssl/error.hpp>
21#include <boost/asio/strand.hpp>
22#include <boost/beast/core/error.hpp>
23#include <boost/beast/core/flat_buffer.hpp>
24#include <boost/beast/core/stream_traits.hpp>
25#include <boost/beast/core/tcp_stream.hpp>
26#include <fmt/format.h>
60 template <
typename>
class PlainSessionType,
61 template <
typename>
class SslSessionType,
64 :
public std::enable_shared_from_this<Detector<PlainSessionType, SslSessionType, HandlerType>> {
65 using std::enable_shared_from_this<
69 boost::beast::tcp_stream stream_;
70 std::optional<std::reference_wrapper<boost::asio::ssl::context>> ctx_;
71 std::reference_wrapper<util::TagDecoratorFactory const> tagFactory_;
72 std::reference_wrapper<dosguard::DOSGuardInterface>
const dosGuard_;
73 std::shared_ptr<HandlerType>
const handler_;
74 std::reference_wrapper<data::LedgerCacheInterface const> cache_;
75 boost::beast::flat_buffer buffer_;
76 std::shared_ptr<AdminVerificationStrategy>
const adminVerification_;
77 std::uint32_t maxWsSendingQueueSize_;
78 std::shared_ptr<ProxyIpResolver> proxyIpResolver_;
96 std::optional<std::reference_wrapper<boost::asio::ssl::context>> ctx,
97 std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
98 std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard,
99 std::shared_ptr<HandlerType> handler,
100 std::reference_wrapper<data::LedgerCacheInterface const> cache,
101 std::shared_ptr<AdminVerificationStrategy> adminVerification,
102 std::uint32_t maxWsSendingQueueSize,
103 std::shared_ptr<ProxyIpResolver> proxyIpResolver
105 : stream_(std::move(socket))
107 , tagFactory_(std::cref(tagFactory))
108 , dosGuard_(dosGuard)
109 , handler_(std::move(handler))
111 , adminVerification_(std::move(adminVerification))
112 , maxWsSendingQueueSize_(maxWsSendingQueueSize)
113 , proxyIpResolver_(std::move(proxyIpResolver))
124 fail(boost::system::error_code ec,
char const* message)
126 if (ec == boost::asio::ssl::error::stream_truncated)
129 LOG(log_.info()) <<
"Detector failed (" << message <<
"): " << ec.message();
136 boost::beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
154 return fail(ec,
"detect");
158 ip = stream_.socket().remote_endpoint().address().to_string();
159 }
catch (std::exception
const&) {
160 return fail(ec,
"cannot get remote endpoint");
165 return fail(ec,
"SSL is not supported by this server");
167 std::make_shared<SslSessionType<HandlerType>>(
168 stream_.release_socket(),
178 maxWsSendingQueueSize_
184 std::make_shared<PlainSessionType<HandlerType>>(
185 stream_.release_socket(),
194 maxWsSendingQueueSize_
211 template <
typename>
class PlainSessionType,
212 template <
typename>
class SslSessionType,
213 SomeServerHandler HandlerType>
216 public std::enable_shared_from_this<Server<PlainSessionType, SslSessionType, HandlerType>> {
217 using std::enable_shared_from_this<
221 std::reference_wrapper<boost::asio::io_context> ioc_;
222 std::optional<boost::asio::ssl::context> ctx_;
224 std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard_;
225 std::shared_ptr<HandlerType> handler_;
226 std::reference_wrapper<data::LedgerCacheInterface const> cache_;
227 tcp::acceptor acceptor_;
228 std::shared_ptr<AdminVerificationStrategy> adminVerification_;
229 std::uint32_t maxWsSendingQueueSize_;
230 std::shared_ptr<ProxyIpResolver> proxyIpResolver_;
231 std::atomic_bool isStopped_{
false};
249 boost::asio::io_context& ioc,
250 std::optional<boost::asio::ssl::context> ctx,
251 tcp::endpoint endpoint,
254 std::shared_ptr<HandlerType> handler,
255 std::reference_wrapper<data::LedgerCacheInterface const> cache,
256 std::shared_ptr<AdminVerificationStrategy> adminVerification,
257 std::uint32_t maxWsSendingQueueSize,
260 : ioc_(std::ref(ioc))
261 , ctx_(std::move(ctx))
262 , tagFactory_(tagFactory)
263 , dosGuard_(std::ref(dosGuard))
264 , handler_(std::move(handler))
266 , acceptor_(boost::asio::make_strand(ioc))
267 , adminVerification_(std::move(adminVerification))
268 , maxWsSendingQueueSize_(maxWsSendingQueueSize)
269 , proxyIpResolver_(std::make_shared<
ProxyIpResolver>(std::move(proxyIpResolver)))
271 boost::beast::error_code ec;
273 acceptor_.open(endpoint.protocol(), ec);
277 acceptor_.set_option(boost::asio::socket_base::reuse_address(
true), ec);
281 acceptor_.bind(endpoint, ec);
283 LOG(log_.error()) <<
"Failed to bind to endpoint: " << endpoint
284 <<
". message: " << ec.message();
285 throw std::runtime_error(
287 "Failed to bind to endpoint: {}:{}",
288 endpoint.address().to_string(),
294 acceptor_.listen(boost::asio::socket_base::max_listen_connections, ec);
296 LOG(log_.error()) <<
"Failed to listen at endpoint: " << endpoint
297 <<
". message: " << ec.message();
298 throw std::runtime_error(
300 "Failed to listen at endpoint: {}:{}",
301 endpoint.address().to_string(),
317 stop(boost::asio::yield_context)
326 acceptor_.async_accept(
327 boost::asio::make_strand(ioc_.get()),
328 boost::beast::bind_front_handler(&Server::onAccept, shared_from_this())
333 onAccept(boost::beast::error_code ec, tcp::socket socket)
341 ? std::optional<std::reference_wrapper<boost::asio::ssl::context>>{ctx_.value()}
344 std::make_shared<Detector<PlainSessionType, SslSessionType, HandlerType>>(
347 std::cref(tagFactory_),
352 maxWsSendingQueueSize_,
363template <
typename HandlerType>
377template <
typename HandlerType>
378static std::shared_ptr<HttpServer<HandlerType>>
381 boost::asio::io_context& ioc,
383 std::shared_ptr<HandlerType>
const& handler,
384 std::reference_wrapper<data::LedgerCacheInterface const> cache
389 auto expectedSslContext = ng::impl::makeServerSslContext(config);
390 if (not expectedSslContext) {
391 LOG(log.
error()) <<
"Failed to create SSL context: " << expectedSslContext.error();
395 auto const serverConfig = config.
getObject(
"server");
396 auto const address = boost::asio::ip::make_address(serverConfig.get<std::string>(
"ip"));
397 auto const port = serverConfig.get<
unsigned short>(
"port");
400 if (not expectedAdminVerification.has_value()) {
401 LOG(log.
error()) << expectedAdminVerification.error();
402 throw std::logic_error{expectedAdminVerification.error()};
407 auto const maxWsSendingQueueSize = serverConfig.get<uint32_t>(
"ws_max_sending_queue_size");
411 auto server = std::make_shared<HttpServer<HandlerType>>(
413 std::move(expectedSslContext).value(),
414 boost::asio::ip::tcp::endpoint{address, port},
419 std::move(expectedAdminVerification).value(),
420 maxWsSendingQueueSize,
421 std::move(proxyIpResolver)
A simple thread-safe logger for the channel specified in the constructor.
Definition Logger.hpp:77
Pump error(SourceLocationType const &loc=CURRENT_SRC_LOCATION) const
Interface for logging at Severity::ERR severity.
Definition Logger.cpp:498
A factory for TagDecorator instantiation.
Definition Taggable.hpp:165
All the config data will be stored and extracted from this class.
Definition ConfigDefinition.hpp:31
ObjectView getObject(std::string_view prefix, std::optional< std::size_t > idx=std::nullopt) const
Returns the ObjectView specified with the prefix.
Definition ConfigDefinition.cpp:44
void onDetect(boost::beast::error_code ec, bool result)
Handles detection result.
Definition Server.hpp:151
void run()
Initiate the detection.
Definition Server.hpp:134
Detector(tcp::socket &&socket, std::optional< std::reference_wrapper< boost::asio::ssl::context > > ctx, std::reference_wrapper< util::TagDecoratorFactory const > tagFactory, std::reference_wrapper< dosguard::DOSGuardInterface > dosGuard, std::shared_ptr< HandlerType > handler, std::reference_wrapper< data::LedgerCacheInterface const > cache, std::shared_ptr< AdminVerificationStrategy > adminVerification, std::uint32_t maxWsSendingQueueSize, std::shared_ptr< ProxyIpResolver > proxyIpResolver)
Create a new detector.
Definition Server.hpp:94
void fail(boost::system::error_code ec, char const *message)
A helper function that is called when any error occurs.
Definition Server.hpp:124
Resolves the client's IP address, considering proxy servers.
Definition ProxyIpResolver.hpp:25
static ProxyIpResolver fromConfig(util::config::ClioConfigDefinition const &config)
Creates a ProxyIpResolver from a configuration.
Definition ProxyIpResolver.cpp:32
The WebServer class. It creates server socket and start listening on it.
Definition Server.hpp:216
void run()
Start accepting incoming connections.
Definition Server.hpp:310
void stop(boost::asio::yield_context)
Stop accepting new connections.
Definition Server.hpp:317
Server(boost::asio::io_context &ioc, std::optional< boost::asio::ssl::context > ctx, tcp::endpoint endpoint, util::TagDecoratorFactory tagFactory, dosguard::DOSGuardInterface &dosGuard, std::shared_ptr< HandlerType > handler, std::reference_wrapper< data::LedgerCacheInterface const > cache, std::shared_ptr< AdminVerificationStrategy > adminVerification, std::uint32_t maxWsSendingQueueSize, ProxyIpResolver proxyIpResolver)
Create a new instance of the web server.
Definition Server.hpp:248
The interface of a denial of service guard.
Definition DOSGuardInterface.hpp:27
Specifies the requirements a Webserver handler must fulfill.
Definition Concepts.hpp:18
This namespace implements the web server and related components.
Definition Types.hpp:24
static std::shared_ptr< HttpServer< HandlerType > > makeHttpServer(util::config::ClioConfigDefinition const &config, boost::asio::io_context &ioc, dosguard::DOSGuardInterface &dosGuard, std::shared_ptr< HandlerType > const &handler, std::reference_wrapper< data::LedgerCacheInterface const > cache)
A factory function that spawns a ready to use HTTP server.
Definition Server.hpp:379
Server< HttpSession, SslHttpSession, HandlerType > HttpServer
The final type of the HttpServer used by Clio.
Definition Server.hpp:364
std::shared_ptr< AdminVerificationStrategy > makeAdminVerificationStrategy(std::optional< std::string > password)
Factory function for creating an admin verification strategy.
Definition AdminVerificationStrategy.cpp:48
A tag class for server to help identify Server in templated code.
Definition Concepts.hpp:31