Clio  develop
The XRP Ledger API server.
Loading...
Searching...
No Matches
ConnectionHandler.hpp
1#pragma once
2
3#include "util/StopHelper.hpp"
4#include "util/StringHash.hpp"
5#include "util/Taggable.hpp"
6#include "util/log/Logger.hpp"
7#include "util/prometheus/Gauge.hpp"
8#include "util/prometheus/Label.hpp"
9#include "util/prometheus/Prometheus.hpp"
10#include "web/ProxyIpResolver.hpp"
11#include "web/SubscriptionContextInterface.hpp"
12#include "web/ng/Connection.hpp"
13#include "web/ng/Error.hpp"
14#include "web/ng/MessageHandler.hpp"
15#include "web/ng/ProcessingPolicy.hpp"
16#include "web/ng/Request.hpp"
17#include "web/ng/Response.hpp"
18
19#include <boost/asio/spawn.hpp>
20#include <boost/signals2/signal.hpp>
21#include <boost/signals2/variadic_signal.hpp>
22
23#include <atomic>
24#include <chrono>
25#include <cstddef>
26#include <functional>
27#include <memory>
28#include <optional>
29#include <string>
30#include <unordered_map>
31
32namespace web::ng::impl {
33
34class ConnectionHandler {
35public:
36 using OnDisconnectHook = std::function<void(Connection const&)>;
37 using OnIpChangeHook = std::function<void(std::string const&, std::string const&)>;
38 using TargetToHandlerMap =
39 std::unordered_map<std::string, MessageHandler, util::StringHash, std::equal_to<>>;
40
41private:
42 util::Logger log_{"WebServer"};
43 util::Logger perfLog_{"Performance"};
44
45 ProcessingPolicy processingPolicy_;
46 std::optional<size_t> maxParallelRequests_;
47
48 std::reference_wrapper<util::TagDecoratorFactory> tagFactory_;
49 std::optional<size_t> maxSubscriptionSendQueueSize_;
50
51 ProxyIpResolver proxyIpResolver_;
52
53 OnDisconnectHook onDisconnectHook_;
54 OnIpChangeHook onIpChangeHook_;
55
56 TargetToHandlerMap getHandlers_;
57 TargetToHandlerMap postHandlers_;
58 std::optional<MessageHandler> wsHandler_;
59
60 boost::signals2::signal<void()> onStop_;
61 std::unique_ptr<std::atomic_bool> stopping_ = std::make_unique<std::atomic_bool>(false);
62
63 std::reference_wrapper<util::prometheus::GaugeInt> connectionsCounter_ =
65 "connections_total_number",
66 util::prometheus::Labels{{{"status", "connected"}}}
67 );
68
69 util::StopHelper stopHelper_;
70
71public:
72 ConnectionHandler(
73 ProcessingPolicy processingPolicy,
74 std::optional<size_t> maxParallelRequests,
75 util::TagDecoratorFactory& tagFactory,
76 std::optional<size_t> maxSubscriptionSendQueueSize,
77 ProxyIpResolver proxyIpResolver,
78 OnDisconnectHook onDisconnectHook,
79 OnIpChangeHook onIpChangeHook
80 );
81
82 ConnectionHandler(ConnectionHandler&&) = delete;
83
84 static constexpr std::chrono::milliseconds kCLOSE_CONNECTION_TIMEOUT{500};
85
86 void
87 onGet(std::string const& target, MessageHandler handler);
88
89 void
90 onPost(std::string const& target, MessageHandler handler);
91
92 void
93 onWs(MessageHandler handler);
94
95 void
96 processConnection(ConnectionPtr connection, boost::asio::yield_context yield);
97
98 static void
99 stopConnection(Connection& connection, boost::asio::yield_context yield);
100
101 void
102 stop(boost::asio::yield_context yield);
103
104 bool
105 isStopping() const;
106
107private:
115 bool
116 handleError(Error const& error, Connection const& connection) const;
117
125 bool
126 sequentRequestResponseLoop(
127 Connection& connection,
128 SubscriptionContextPtr& subscriptionContext,
129 boost::asio::yield_context yield
130 );
131
132 bool
133 parallelRequestResponseLoop(
134 Connection& connection,
135 SubscriptionContextPtr& subscriptionContext,
136 boost::asio::yield_context yield
137 );
138
139 std::optional<bool>
140 processRequest(
141 Connection& connection,
142 SubscriptionContextPtr& subscriptionContext,
143 Request const& request,
144 boost::asio::yield_context yield
145 );
146
148 handleRequest(
149 ConnectionMetadata& connectionMetadata,
150 SubscriptionContextPtr& subscriptionContext,
151 Request const& request,
152 boost::asio::yield_context yield
153 );
154
155 void
156 resolveClientIp(Connection& connection, Request const& request) const;
157};
158
159} // namespace web::ng::impl
static util::prometheus::GaugeInt & gaugeInt(std::string name, util::prometheus::Labels labels, std::optional< std::string > description=std::nullopt)
Get an integer based gauge metric. It will be created if it doesn't exist.
Definition Prometheus.cpp:231
A simple thread-safe logger for the channel specified in the constructor.
Definition Logger.hpp:77
Helper class to stop a class asynchronously.
Definition StopHelper.hpp:15
A factory for TagDecorator instantiation.
Definition Taggable.hpp:165
Class representing a collection of Prometheus labels.
Definition Label.hpp:41
Resolves the client's IP address, considering proxy servers.
Definition ProxyIpResolver.hpp:25
An interface for a connection metadata class.
Definition Connection.hpp:25
A class representing a connection to a client.
Definition Connection.hpp:93
Represents an HTTP or WebSocket request.
Definition Request.hpp:18
Represents an HTTP or Websocket response.
Definition Response.hpp:21
std::shared_ptr< SubscriptionContextInterface > SubscriptionContextPtr
An alias for shared pointer to a SubscriptionContextInterface.
Definition SubscriptionContextInterface.hpp:64