Network System 0.1.1
High-performance modular networking library for scalable client-server applications
Loading...
Searching...
No Matches
http2_server.h
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2024, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
5#pragma once
6
7#include "frame.h"
8#include "hpack.h"
9#include "http2_client.h"
10#include "http2_request.h"
11#include "http2_server_stream.h"
13
14#include <asio.hpp>
15#include <asio/ssl.hpp>
16
17#include <atomic>
18#include <chrono>
19#include <cstdint>
20#include <functional>
21#include <future>
22#include <map>
23#include <memory>
24#include <mutex>
25#include <optional>
26#include <string>
27#include <string_view>
28#include <vector>
29
31{
32 // Forward declaration
33 class http2_server_connection;
34
40 {
41 std::string cert_file;
42 std::string key_file;
43 std::string ca_file;
44 bool verify_client = false;
45 };
46
92 class http2_server : public std::enable_shared_from_this<http2_server>
93 {
94 public:
96 using request_handler_t = std::function<void(
97 http2_server_stream& stream,
98 const http2_request& request)>;
99
101 using error_handler_t = std::function<void(
102 const std::string& error_message)>;
103
108 explicit http2_server(std::string_view server_id);
109
114
115 // Non-copyable
116 http2_server(const http2_server&) = delete;
118
119 // Non-movable (contains std::atomic members)
122
130 auto start(unsigned short port) -> VoidResult;
131
140 auto start_tls(unsigned short port, const tls_config& config) -> VoidResult;
141
148 auto stop() -> VoidResult;
149
154 [[nodiscard]] auto is_running() const -> bool;
155
161 auto wait() -> void;
162
170 auto set_request_handler(request_handler_t handler) -> void;
171
176 auto set_error_handler(error_handler_t handler) -> void;
177
182 auto set_settings(const http2_settings& settings) -> void;
183
188 [[nodiscard]] auto get_settings() const -> http2_settings;
189
194 [[nodiscard]] auto active_connections() const -> size_t;
195
200 [[nodiscard]] auto active_streams() const -> size_t;
201
206 [[nodiscard]] auto server_id() const -> std::string_view;
207
208 private:
209 // Internal connection handling
210 auto do_accept() -> void;
211 auto do_accept_tls() -> void;
212 auto handle_accept(std::error_code ec, asio::ip::tcp::socket socket) -> void;
213 auto handle_accept_tls(std::error_code ec, asio::ip::tcp::socket socket) -> void;
214
215 // Connection management
216 auto add_connection(std::shared_ptr<http2_server_connection> conn) -> void;
217 auto remove_connection(uint64_t connection_id) -> void;
218 auto cleanup_dead_connections() -> void;
219 auto start_cleanup_timer() -> void;
220
221 // I/O thread management
222 auto run_io() -> void;
223 auto stop_io() -> void;
224
225 // Member variables
226 std::string server_id_;
227
228 // ASIO context
229 std::unique_ptr<asio::io_context> io_context_;
230 std::unique_ptr<asio::ssl::context> ssl_context_;
231 std::unique_ptr<asio::ip::tcp::acceptor> acceptor_;
232 std::unique_ptr<asio::executor_work_guard<asio::io_context::executor_type>> work_guard_;
233 std::future<void> io_future_;
234
235 // Server state
236 std::atomic<bool> is_running_{false};
237 std::atomic<bool> use_tls_{false};
238 std::promise<void> stop_promise_;
239 std::future<void> stop_future_;
240
241 // Handlers
244
245 // Connection management
247 std::map<uint64_t, std::shared_ptr<http2_server_connection>> connections_;
248 std::atomic<uint64_t> next_connection_id_{1};
249
250 // Settings
252
253 // HPACK encoder for all connections
254 std::shared_ptr<hpack_encoder> encoder_;
255 std::shared_ptr<hpack_decoder> decoder_;
256
257 // Cleanup timer
258 std::unique_ptr<asio::steady_timer> cleanup_timer_;
259
260 // Constants
261 static constexpr std::string_view CONNECTION_PREFACE =
262 "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
263 static constexpr size_t FRAME_HEADER_SIZE = 9;
264 };
265
273 class http2_server_connection : public std::enable_shared_from_this<http2_server_connection>
274 {
275 public:
285 asio::ip::tcp::socket socket,
287 http2_server::request_handler_t request_handler,
288 http2_server::error_handler_t error_handler);
289
299 std::unique_ptr<asio::ssl::stream<asio::ip::tcp::socket>> socket,
301 http2_server::request_handler_t request_handler,
302 http2_server::error_handler_t error_handler);
303
308
309 // Non-copyable, non-movable
314
319 auto start() -> VoidResult;
320
325 auto stop() -> VoidResult;
326
331 [[nodiscard]] auto is_alive() const -> bool;
332
337 [[nodiscard]] auto connection_id() const -> uint64_t;
338
343 [[nodiscard]] auto stream_count() const -> size_t;
344
345 private:
346 // Connection setup
347 auto read_connection_preface() -> void;
348 auto send_settings() -> VoidResult;
351
352 // Frame I/O
353 auto start_reading() -> void;
354 auto read_frame_header() -> void;
355 auto read_frame_payload(uint32_t length) -> void;
356 auto send_frame(const frame& f) -> VoidResult;
357 auto process_frame(std::unique_ptr<frame> f) -> VoidResult;
358
359 // Stream management
360 auto get_or_create_stream(uint32_t stream_id) -> http2_stream*;
361 auto close_stream(uint32_t stream_id) -> void;
362
363 // Frame handlers
365 auto handle_data_frame(const data_frame& f) -> VoidResult;
367 auto handle_ping_frame(const ping_frame& f) -> VoidResult;
370
371 // Request completion
372 auto dispatch_request(uint32_t stream_id) -> void;
373
374 uint64_t connection_id_;
375 bool use_tls_;
376
377 // Socket (one of these is used)
378 std::unique_ptr<asio::ip::tcp::socket> plain_socket_;
379 std::unique_ptr<asio::ssl::stream<asio::ip::tcp::socket>> tls_socket_;
380
381 // Connection state
382 std::atomic<bool> is_alive_{true};
383 std::atomic<bool> preface_received_{false};
384 std::atomic<bool> goaway_sent_{false};
385
386 // Stream management
387 std::mutex streams_mutex_;
388 std::map<uint32_t, http2_stream> streams_;
389 uint32_t last_stream_id_{0};
390
391 // Settings
394
395 // HPACK
398
399 // Flow control
401
402 // Handlers
405
406 // Read buffer
407 std::vector<uint8_t> read_buffer_;
408 std::array<uint8_t, 9> frame_header_buffer_;
409 };
410
411} // namespace kcenon::network::protocols::http2
DATA frame (RFC 7540 Section 6.1)
Definition frame.h:139
Base class for HTTP/2 frames.
Definition frame.h:82
GOAWAY frame (RFC 7540 Section 6.8)
Definition frame.h:387
HEADERS frame (RFC 7540 Section 6.2)
Definition frame.h:189
HPACK header decoder (RFC 7541)
Definition hpack.h:209
HPACK header encoder (RFC 7541)
Definition hpack.h:159
Represents a single HTTP/2 connection on the server side.
http2_server_connection(uint64_t connection_id, asio::ip::tcp::socket socket, const http2_settings &settings, http2_server::request_handler_t request_handler, http2_server::error_handler_t error_handler)
Construct server connection with plain socket.
auto handle_data_frame(const data_frame &f) -> VoidResult
auto get_or_create_stream(uint32_t stream_id) -> http2_stream *
std::unique_ptr< asio::ip::tcp::socket > plain_socket_
auto start() -> VoidResult
Start connection handling.
auto stream_count() const -> size_t
Get number of active streams.
auto handle_goaway_frame(const goaway_frame &f) -> VoidResult
auto connection_id() const -> uint64_t
Get connection identifier.
auto handle_window_update_frame(const window_update_frame &f) -> VoidResult
auto process_frame(std::unique_ptr< frame > f) -> VoidResult
http2_server_connection(http2_server_connection &&)=delete
auto handle_settings_frame(const settings_frame &frame) -> VoidResult
auto handle_rst_stream_frame(const rst_stream_frame &f) -> VoidResult
std::unique_ptr< asio::ssl::stream< asio::ip::tcp::socket > > tls_socket_
http2_server_connection & operator=(http2_server_connection &&)=delete
auto handle_headers_frame(const headers_frame &f) -> VoidResult
auto is_alive() const -> bool
Check if connection is alive.
http2_server_connection & operator=(const http2_server_connection &)=delete
http2_server_connection(const http2_server_connection &)=delete
auto handle_ping_frame(const ping_frame &f) -> VoidResult
Server-side HTTP/2 stream for sending responses.
auto active_streams() const -> size_t
Get total number of active streams across all connections.
auto remove_connection(uint64_t connection_id) -> void
http2_server(std::string_view server_id)
Construct HTTP/2 server.
auto set_error_handler(error_handler_t handler) -> void
Set error handler.
http2_server & operator=(http2_server &&)=delete
std::unique_ptr< asio::io_context > io_context_
http2_server(const http2_server &)=delete
std::function< void( const std::string &error_message)> error_handler_t
Error handler function type.
auto server_id() const -> std::string_view
Get server identifier.
std::shared_ptr< hpack_encoder > encoder_
auto set_settings(const http2_settings &settings) -> void
Set server settings.
auto handle_accept(std::error_code ec, asio::ip::tcp::socket socket) -> void
std::shared_ptr< hpack_decoder > decoder_
auto get_settings() const -> http2_settings
Get current settings.
~http2_server()
Destructor - stops server gracefully.
auto stop() -> VoidResult
Stop the server.
http2_server & operator=(const http2_server &)=delete
auto active_connections() const -> size_t
Get number of active connections.
auto is_running() const -> bool
Check if server is running.
auto add_connection(std::shared_ptr< http2_server_connection > conn) -> void
static constexpr std::string_view CONNECTION_PREFACE
auto handle_accept_tls(std::error_code ec, asio::ip::tcp::socket socket) -> void
std::map< uint64_t, std::shared_ptr< http2_server_connection > > connections_
auto set_request_handler(request_handler_t handler) -> void
Set request handler.
auto start(unsigned short port) -> VoidResult
Start HTTP/2 server without TLS (h2c - HTTP/2 cleartext)
auto start_tls(unsigned short port, const tls_config &config) -> VoidResult
Start HTTP/2 server with TLS.
std::function< void( http2_server_stream &stream, const http2_request &request)> request_handler_t
Request handler function type.
std::unique_ptr< asio::steady_timer > cleanup_timer_
auto wait() -> void
Wait for server to stop.
std::unique_ptr< asio::ssl::context > ssl_context_
std::unique_ptr< asio::executor_work_guard< asio::io_context::executor_type > > work_guard_
std::unique_ptr< asio::ip::tcp::acceptor > acceptor_
PING frame (RFC 7540 Section 6.7)
Definition frame.h:344
RST_STREAM frame (RFC 7540 Section 6.4)
Definition frame.h:307
SETTINGS frame (RFC 7540 Section 6.5)
Definition frame.h:265
WINDOW_UPDATE frame (RFC 7540 Section 6.9)
Definition frame.h:438
error_code
HTTP/2 error codes (RFC 7540 Section 7)
Definition frame.h:471
Result< std::monostate > VoidResult
Network-specific error and result type definitions.
TLS configuration for HTTP/2 server.
bool verify_client
Require client certificate.
std::string ca_file
Path to CA certificate file (optional)
std::string cert_file
Path to certificate file (PEM)
std::string key_file
Path to private key file (PEM)