63 std::optional<boost::beast::http::request<boost::beast::http::string_body>> request_;
66 using MessageType = boost::beast::http::response<boost::beast::http::string_body>;
73 boost::asio::ip::tcp::socket socket,
75 boost::beast::flat_buffer buffer,
77 size_t maxSendingQueueSize
81 , stream_{std::move(socket)}
83 [
this](MessageType
const& message,
auto&& yield) {
84 boost::beast::get_lowest_layer(stream_).expires_after(timeout_);
85 boost::beast::http::async_write(stream_, message, yield);
93 boost::asio::ip::tcp::socket socket,
95 boost::beast::flat_buffer buffer,
96 boost::asio::ssl::context& sslCtx,
98 size_t maxSendingQueueSize
102 , stream_{std::move(socket), sslCtx}
104 [
this](MessageType
const& message,
auto&& yield) {
105 boost::beast::get_lowest_layer(stream_).expires_after(timeout_);
106 boost::beast::http::async_write(stream_, message, yield);
113 HttpConnection(HttpConnection&& other) =
delete;
115 operator=(HttpConnection&& other) =
delete;
116 HttpConnection(HttpConnection
const& other) =
delete;
118 operator=(HttpConnection
const& other) =
delete;
120 std::expected<void, Error>
121 sslHandshake(boost::asio::yield_context yield)
124 boost::system::error_code error;
125 boost::beast::get_lowest_layer(stream_).expires_after(timeout_);
126 auto const bytesUsed = stream_.async_handshake(
127 boost::asio::ssl::stream_base::server, buffer_.cdata(), yield[error]
130 return std::unexpected{error};
132 buffer_.consume(bytesUsed);
143 std::expected<void, Error>
145 boost::beast::http::response<boost::beast::http::string_body> response,
146 boost::asio::yield_context yield
149 return sendingQueue_.send(std::move(response), yield);
153 setTimeout(std::chrono::steady_clock::duration newTimeout)
override
155 timeout_ = newTimeout;
158 std::expected<void, Error>
161 auto httpResponse = std::move(response).intoHttpResponse();
162 return sendRaw(std::move(httpResponse), yield);
165 std::expected<Request, Error>
166 receive(boost::asio::yield_context yield)
override
168 if (request_.has_value()) {
169 Request result{*std::move(request_)};
173 auto expectedRequest = fetch(yield);
174 if (expectedRequest.has_value())
175 return Request{std::move(expectedRequest).value()};
177 return std::unexpected{std::move(expectedRequest).error()};
181 close(boost::asio::yield_context yield)
override
190 [[maybe_unused]] boost::system::error_code error;
192 boost::beast::get_lowest_layer(stream_).expires_after(timeout_);
193 stream_.async_shutdown(yield[error]);
195 boost::beast::get_lowest_layer(stream_).socket().shutdown(
196 boost::asio::ip::tcp::socket::shutdown_type::shutdown_both, error
200 std::expected<bool, Error>
201 isUpgradeRequested(boost::asio::yield_context yield)
override
203 auto expectedRequest = fetch(yield);
204 if (not expectedRequest.has_value())
205 return std::unexpected{std::move(expectedRequest).error()};
207 request_ = std::move(expectedRequest).value();
209 return boost::beast::websocket::is_upgrade(*request_);
212 std::expected<ConnectionPtr, Error>
215 size_t maxSendingQueueSize,
216 boost::asio::yield_context yield
219 ASSERT(request_.has_value(),
"Request must be present to upgrade the connection");
221 return makeWsConnection(
225 std::move(*request_),
233 std::expected<boost::beast::http::request<boost::beast::http::string_body>, Error>
234 fetch(boost::asio::yield_context yield)
236 boost::beast::http::request<boost::beast::http::string_body> request{};
237 boost::system::error_code error;
238 boost::beast::get_lowest_layer(stream_).expires_after(timeout_);
239 boost::beast::http::async_read(stream_, buffer_, request, yield[error]);
241 return std::unexpected{error};