Clio  develop
The XRP Ledger API server.
Loading...
Searching...
No Matches
SslWsSession.hpp
1//------------------------------------------------------------------------------
2/*
3 This file is part of clio: https://github.com/XRPLF/clio
4 Copyright (c) 2023, the clio developers.
5
6 Permission to use, copy, modify, and distribute this software for any
7 purpose with or without fee is hereby granted, provided that the above
8 copyright notice and this permission notice appear in all copies.
9
10 THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17*/
18//==============================================================================
19
20#pragma once
21
22#include "util/Taggable.hpp"
23#include "web/dosguard/DOSGuardInterface.hpp"
24#include "web/impl/WsBase.hpp"
25#include "web/interface/ConnectionBase.hpp"
26
27#include <boost/beast/core/flat_buffer.hpp>
28#include <boost/beast/core/stream_traits.hpp>
29#include <boost/beast/core/tcp_stream.hpp>
30#include <boost/beast/http/message.hpp>
31#include <boost/beast/http/parser.hpp>
32#include <boost/beast/http/string_body.hpp>
33#include <boost/beast/ssl.hpp>
34#include <boost/beast/ssl/ssl_stream.hpp>
35#include <boost/beast/websocket/stream.hpp>
36#include <boost/optional/optional.hpp>
37
38#include <chrono>
39#include <cstdint>
40#include <functional>
41#include <memory>
42#include <string>
43#include <utility>
44
45namespace web {
46
52template <SomeServerHandler HandlerType>
53class SslWsSession : public impl::WsBase<SslWsSession, HandlerType> {
54 using StreamType =
55 boost::beast::websocket::stream<boost::asio::ssl::stream<boost::beast::tcp_stream>>;
56 StreamType ws_;
57
58public:
71 explicit SslWsSession(
72 boost::asio::ssl::stream<boost::beast::tcp_stream>&& stream,
73 std::string ip,
74 std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
75 std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard,
76 std::shared_ptr<HandlerType> const& handler,
77 boost::beast::flat_buffer&& buffer,
78 bool isAdmin,
79 std::uint32_t maxWsSendingQueueSize
80 )
81 : impl::WsBase<SslWsSession, HandlerType>(
82 ip,
83 tagFactory,
84 dosGuard,
85 handler,
86 std::move(buffer),
87 maxWsSendingQueueSize
88 )
89 , ws_(std::move(stream))
90 {
91 ConnectionBase::isAdmin_ = isAdmin; // NOLINT(cppcoreguidelines-prefer-member-initializer)
92 }
93
95 StreamType&
97 {
98 return ws_;
99 }
100};
101
107template <SomeServerHandler HandlerType>
108class SslWsUpgrader : public std::enable_shared_from_this<SslWsUpgrader<HandlerType>> {
109 using std::enable_shared_from_this<SslWsUpgrader<HandlerType>>::shared_from_this;
110
111 boost::asio::ssl::stream<boost::beast::tcp_stream> https_;
112 boost::optional<http::request_parser<http::string_body>> parser_;
113 boost::beast::flat_buffer buffer_;
114 std::string ip_;
115 std::reference_wrapper<util::TagDecoratorFactory const> tagFactory_;
116 std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard_;
117 std::shared_ptr<HandlerType> const handler_;
118 http::request<http::string_body> req_;
119 bool isAdmin_;
120 std::uint32_t maxWsSendingQueueSize_;
121
122public:
137 boost::asio::ssl::stream<boost::beast::tcp_stream> stream,
138 std::string ip,
139 std::reference_wrapper<util::TagDecoratorFactory const> tagFactory,
140 std::reference_wrapper<dosguard::DOSGuardInterface> dosGuard,
141 std::shared_ptr<HandlerType> handler,
142 boost::beast::flat_buffer&& buffer,
143 http::request<http::string_body> request,
144 bool isAdmin,
145 std::uint32_t maxWsSendingQueueSize
146 )
147 : https_(std::move(stream))
148 , buffer_(std::move(buffer))
149 , ip_(std::move(ip))
150 , tagFactory_(tagFactory)
151 , dosGuard_(dosGuard)
152 , handler_(std::move(handler))
153 , req_(std::move(request))
154 , isAdmin_(isAdmin)
155 , maxWsSendingQueueSize_(maxWsSendingQueueSize)
156 {
157 }
158
159 ~SslWsUpgrader() = default;
160
162 void
164 {
165 boost::beast::get_lowest_layer(https_).expires_after(std::chrono::seconds(30));
166
167 boost::asio::dispatch(
168 https_.get_executor(),
169 boost::beast::bind_front_handler(
170 &SslWsUpgrader<HandlerType>::doUpgrade, shared_from_this()
171 )
172 );
173 }
174
175private:
176 void
177 doUpgrade()
178 {
179 parser_.emplace();
180
181 // Apply a reasonable limit to the allowed size of the body in bytes to prevent abuse.
182 static constexpr auto kMAX_BODY_SIZE = 10000;
183 parser_->body_limit(kMAX_BODY_SIZE);
184
185 boost::beast::get_lowest_layer(https_).expires_after(std::chrono::seconds(30));
186 onUpgrade();
187 }
188
189 void
190 onUpgrade()
191 {
192 if (!boost::beast::websocket::is_upgrade(req_))
193 return;
194
195 // Disable the timeout. The websocket::stream uses its own timeout settings.
196 boost::beast::get_lowest_layer(https_).expires_never();
197
198 std::make_shared<SslWsSession<HandlerType>>(
199 std::move(https_),
200 ip_,
201 tagFactory_,
202 dosGuard_,
203 handler_,
204 std::move(buffer_),
205 isAdmin_,
206 maxWsSendingQueueSize_
207 )
208 ->run(std::move(req_));
209 }
210};
211} // namespace web
SslWsSession(boost::asio::ssl::stream< boost::beast::tcp_stream > &&stream, std::string ip, std::reference_wrapper< util::TagDecoratorFactory const > tagFactory, std::reference_wrapper< dosguard::DOSGuardInterface > dosGuard, std::shared_ptr< HandlerType > const &handler, boost::beast::flat_buffer &&buffer, bool isAdmin, std::uint32_t maxWsSendingQueueSize)
Create a new non-secure websocket session.
Definition SslWsSession.hpp:71
StreamType & ws()
Definition SslWsSession.hpp:96
The HTTPS upgrader class, upgrade from an HTTPS session to a secure websocket session.
Definition SslWsSession.hpp:108
void run()
Initiate the upgrade.
Definition SslWsSession.hpp:163
SslWsUpgrader(boost::asio::ssl::stream< boost::beast::tcp_stream > stream, std::string ip, std::reference_wrapper< util::TagDecoratorFactory const > tagFactory, std::reference_wrapper< dosguard::DOSGuardInterface > dosGuard, std::shared_ptr< HandlerType > handler, boost::beast::flat_buffer &&buffer, http::request< http::string_body > request, bool isAdmin, std::uint32_t maxWsSendingQueueSize)
Create a new upgrader to secure websocket.
Definition SslWsSession.hpp:136
Web socket implementation. This class is the base class of the web socket session,...
Definition WsBase.hpp:76
This namespace implements the web server and related components.
Definition Types.hpp:43
bool isAdmin() const
Indicates whether the connection has admin privileges.
Definition ConnectionBase.hpp:118