22#include "util/Taggable.hpp"
23#include "util/build/Build.hpp"
24#include "web/ng/Connection.hpp"
25#include "web/ng/Error.hpp"
26#include "web/ng/Request.hpp"
27#include "web/ng/Response.hpp"
28#include "web/ng/impl/Concepts.hpp"
30#include <boost/asio/buffer.hpp>
31#include <boost/asio/ip/tcp.hpp>
32#include <boost/asio/spawn.hpp>
33#include <boost/asio/ssl/context.hpp>
34#include <boost/asio/ssl/stream.hpp>
35#include <boost/beast/core/buffers_to_string.hpp>
36#include <boost/beast/core/flat_buffer.hpp>
37#include <boost/beast/core/role.hpp>
38#include <boost/beast/core/tcp_stream.hpp>
39#include <boost/beast/http/field.hpp>
40#include <boost/beast/http/message.hpp>
41#include <boost/beast/http/string_body.hpp>
42#include <boost/beast/ssl.hpp>
43#include <boost/beast/websocket/rfc6455.hpp>
44#include <boost/beast/websocket/stream.hpp>
45#include <boost/beast/websocket/stream_base.hpp>
53namespace web::ng::impl {
59 virtual std::optional<Error>
60 sendBuffer(boost::asio::const_buffer buffer, boost::asio::yield_context yield) = 0;
63template <
typename StreamType>
65 boost::beast::websocket::stream<StreamType> stream_;
66 boost::beast::http::request<boost::beast::http::string_body> initialRequest_;
71 boost::asio::ip::tcp::socket socket,
73 boost::beast::flat_buffer buffer,
74 boost::beast::http::request<boost::beast::http::string_body> initialRequest,
79 , stream_(std::move(socket))
80 , initialRequest_(std::move(initialRequest))
86 boost::asio::ip::tcp::socket socket,
88 boost::beast::flat_buffer buffer,
89 boost::asio::ssl::context& sslContext,
90 boost::beast::http::request<boost::beast::http::string_body> initialRequest,
95 , stream_(std::move(socket), sslContext)
96 , initialRequest_(std::move(initialRequest))
102 performHandshake(boost::asio::yield_context yield)
105 stream_.async_accept(initialRequest_, yield[error]);
118 sendBuffer(boost::asio::const_buffer buffer, boost::asio::yield_context yield)
override
120 boost::beast::websocket::stream_base::timeout timeoutOption{};
121 stream_.get_option(timeoutOption);
123 boost::system::error_code error;
124 stream_.async_write(buffer, yield[error]);
131 setTimeout(std::chrono::steady_clock::duration newTimeout)
override
133 boost::beast::websocket::stream_base::timeout wsTimeout =
134 boost::beast::websocket::stream_base::timeout::suggested(boost::beast::role_type::server);
135 wsTimeout.idle_timeout = newTimeout;
136 wsTimeout.handshake_timeout = newTimeout;
137 stream_.set_option(wsTimeout);
146 std::expected<Request, Error>
147 receive(boost::asio::yield_context yield)
override
150 stream_.async_read(buffer_, yield[error]);
152 return std::unexpected{error};
154 auto request = boost::beast::buffers_to_string(buffer_.data());
155 buffer_.consume(buffer_.size());
157 return Request{std::move(request), initialRequest_};
161 close(boost::asio::yield_context yield)
override
170 boost::system::error_code error;
171 stream_.async_close(boost::beast::websocket::close_code::normal, yield[error]);
179 boost::beast::get_lowest_layer(stream_).expires_never();
182 boost::beast::websocket::stream_base::decorator([](boost::beast::websocket::response_type& res) {
183 res.set(boost::beast::http::field::server, util::build::getClioFullVersionString());
189using PlainWsConnection = WsConnection<boost::beast::tcp_stream>;
190using SslWsConnection = WsConnection<boost::asio::ssl::stream<boost::beast::tcp_stream>>;
192std::expected<std::unique_ptr<PlainWsConnection>, Error>
193makePlainWsConnection(
194 boost::asio::ip::tcp::socket socket,
196 boost::beast::flat_buffer buffer,
197 boost::beast::http::request<boost::beast::http::string_body> request,
199 boost::asio::yield_context yield
202std::expected<std::unique_ptr<SslWsConnection>, Error>
204 boost::asio::ip::tcp::socket socket,
206 boost::beast::flat_buffer buffer,
207 boost::beast::http::request<boost::beast::http::string_body> request,
208 boost::asio::ssl::context& sslContext,
210 boost::asio::yield_context yield
A factory for TagDecorator instantiation.
Definition Taggable.hpp:169
A class representing a connection to a client.
Definition Connection.hpp:100
Connection(std::string ip, boost::beast::flat_buffer buffer, util::TagDecoratorFactory const &tagDecoratorFactory)
Construct a new Connection object.
Definition Connection.cpp:48
static constexpr std::chrono::steady_clock::duration kDEFAULT_TIMEOUT
The default timeout for send, receive, and close operations.
Definition Connection.hpp:109
Represents an HTTP or WebSocket request.
Definition Request.hpp:37
Represents an HTTP or Websocket response.
Definition Response.hpp:40
boost::asio::const_buffer asWsResponse() const &
Get the message of the response as a const buffer.
Definition Response.cpp:188
Definition WsConnection.hpp:55
Definition WsConnection.hpp:64
std::optional< Error > send(Response response, boost::asio::yield_context yield) override
Send a response to the client.
Definition WsConnection.hpp:141
std::expected< Request, Error > receive(boost::asio::yield_context yield) override
Receive a request from the client.
Definition WsConnection.hpp:147
void close(boost::asio::yield_context yield) override
Gracefully close the connection.
Definition WsConnection.hpp:161
void setTimeout(std::chrono::steady_clock::duration newTimeout) override
Get the timeout for send, receive, and close operations. For WebSocket connections,...
Definition WsConnection.hpp:131
bool wasUpgraded() const override
Whether the connection was upgraded. Upgraded connections are websocket connections.
Definition WsConnection.hpp:112
Definition Concepts.hpp:33
Definition Concepts.hpp:30