Network System 0.1.1
High-performance modular networking library for scalable client-server applications
Loading...
Searching...
No Matches
http2_client.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"
10
11#include <asio.hpp>
12#include <asio/ssl.hpp>
13
14#include <atomic>
15#include <chrono>
16#include <condition_variable>
17#include <cstdint>
18#include <functional>
19#include <future>
20#include <map>
21#include <memory>
22#include <mutex>
23#include <optional>
24#include <string>
25#include <vector>
26
28{
33 enum class stream_state
34 {
35 idle,
36 open,
39 closed
40 };
41
47 {
48 int status_code = 0;
49 std::vector<http_header> headers;
50 std::vector<uint8_t> body;
51
57 auto get_header(const std::string& name) const -> std::optional<std::string>;
58
63 auto get_body_string() const -> std::string;
64 };
65
71 {
72 uint32_t stream_id = 0;
74 std::vector<http_header> request_headers;
75 std::vector<http_header> response_headers;
76 std::vector<uint8_t> request_body;
77 std::vector<uint8_t> response_body;
78 int32_t window_size = 65535;
79 std::promise<http2_response> promise;
80 bool headers_complete = false;
81 bool body_complete = false;
82
84 bool is_streaming = false;
85 std::function<void(std::vector<uint8_t>)> on_data;
86 std::function<void(std::vector<http_header>)> on_headers;
87 std::function<void(int)> on_complete;
88
89 http2_stream() = default;
92 };
93
99 {
100 uint32_t header_table_size = 4096;
101 bool enable_push = false;
102 uint32_t max_concurrent_streams = 100;
103 uint32_t initial_window_size = 65535;
104 uint32_t max_frame_size = 16384;
105 uint32_t max_header_list_size = 8192;
106 };
107
154 class http2_client : public std::enable_shared_from_this<http2_client>
155 {
156 public:
161 explicit http2_client(std::string_view client_id);
162
167
168 // Non-copyable
169 http2_client(const http2_client&) = delete;
171
172 // Non-movable (contains std::atomic members)
175
185 auto connect(const std::string& host, unsigned short port = 443) -> VoidResult;
186
193 auto disconnect() -> VoidResult;
194
199 auto is_connected() const -> bool;
200
207 auto get(const std::string& path,
208 const std::vector<http_header>& headers = {})
210
218 auto post(const std::string& path,
219 const std::string& body,
220 const std::vector<http_header>& headers = {})
222
230 auto post(const std::string& path,
231 const std::vector<uint8_t>& body,
232 const std::vector<http_header>& headers = {})
234
242 auto put(const std::string& path,
243 const std::string& body,
244 const std::vector<http_header>& headers = {})
245 -> Result<http2_response>;
246
253 auto del(const std::string& path,
254 const std::vector<http_header>& headers = {})
255 -> Result<http2_response>;
256
261 auto set_timeout(std::chrono::milliseconds timeout) -> void;
262
267 auto get_timeout() const -> std::chrono::milliseconds;
268
280 auto start_stream(const std::string& path,
281 const std::vector<http_header>& headers,
282 std::function<void(std::vector<uint8_t>)> on_data,
283 std::function<void(std::vector<http_header>)> on_headers,
284 std::function<void(int)> on_complete)
285 -> Result<uint32_t>;
286
294 auto write_stream(uint32_t stream_id,
295 const std::vector<uint8_t>& data,
296 bool end_stream = false) -> VoidResult;
297
303 auto close_stream_writer(uint32_t stream_id) -> VoidResult;
304
310 auto cancel_stream(uint32_t stream_id) -> VoidResult;
311
316 auto get_settings() const -> http2_settings;
317
322 auto set_settings(const http2_settings& settings) -> void;
323
324 private:
325 // Connection management
326 auto send_connection_preface() -> VoidResult;
327 auto send_settings() -> VoidResult;
328 auto handle_settings_frame(const settings_frame& frame) -> VoidResult;
329 auto send_settings_ack() -> VoidResult;
330
331 // Frame I/O
332 auto send_frame(const frame& f) -> VoidResult;
333 auto read_frame() -> Result<std::unique_ptr<frame>>;
334 auto process_frame(std::unique_ptr<frame> f) -> VoidResult;
335
336 // Stream management
337 auto allocate_stream_id() -> uint32_t;
338 auto get_stream(uint32_t stream_id) -> http2_stream*;
339 auto create_stream() -> http2_stream&;
340 auto close_stream(uint32_t stream_id) -> void;
341
342 // Request handling
343 auto send_request(const std::string& method,
344 const std::string& path,
345 const std::vector<http_header>& headers,
346 const std::vector<uint8_t>& body)
347 -> Result<http2_response>;
348 auto build_headers(const std::string& method,
349 const std::string& path,
350 const std::vector<http_header>& additional) -> std::vector<http_header>;
351
352 // Response handling
353 auto handle_headers_frame(const headers_frame& f) -> VoidResult;
354 auto handle_data_frame(const data_frame& f) -> VoidResult;
355 auto handle_rst_stream_frame(const rst_stream_frame& f) -> VoidResult;
356 auto handle_goaway_frame(const goaway_frame& f) -> VoidResult;
357 auto handle_window_update_frame(const window_update_frame& f) -> VoidResult;
358 auto handle_ping_frame(const ping_frame& f) -> VoidResult;
359
360 // I/O thread
361 auto run_io() -> void;
362 auto stop_io() -> void;
363
364 // Member variables
365 std::string client_id_;
366 std::string host_;
367 unsigned short port_ = 443;
368
369 // ASIO context
370 std::unique_ptr<asio::io_context> io_context_;
371 std::unique_ptr<asio::ssl::context> ssl_context_;
372 std::unique_ptr<asio::ssl::stream<asio::ip::tcp::socket>> socket_;
373 std::unique_ptr<asio::executor_work_guard<asio::io_context::executor_type>> work_guard_;
374 std::future<void> io_future_;
375
376 // Connection state
377 std::atomic<bool> is_connected_{false};
378 std::atomic<bool> is_running_{false};
379 std::atomic<bool> goaway_received_{false};
380
381 // Stream management
382 std::mutex streams_mutex_;
383 std::map<uint32_t, http2_stream> streams_;
384 std::atomic<uint32_t> next_stream_id_{1};
385 int32_t connection_window_size_ = 65535;
386
387 // Settings (must be declared before encoder_/decoder_ for initialization order)
390
391 // HPACK (uses local_settings_.header_table_size in constructor)
394
395 // Timeout
396 std::chrono::milliseconds timeout_{30000};
397
398 // Read buffer
399 std::vector<uint8_t> read_buffer_;
400
401 // Constants
402 static constexpr std::string_view CONNECTION_PREFACE =
403 "PRI * HTTP/2.0\r\n\r\nSM\r\n\r\n";
404 static constexpr size_t FRAME_HEADER_SIZE = 9;
405 static constexpr size_t DEFAULT_WINDOW_SIZE = 65535;
406 };
407
408} // namespace kcenon::network::protocols::http2
HPACK header decoder (RFC 7541)
Definition hpack.h:209
HPACK header encoder (RFC 7541)
Definition hpack.h:159
http2_client & operator=(http2_client &&)=delete
http2_client & operator=(const http2_client &)=delete
http2_client(const http2_client &)=delete
std::map< uint32_t, http2_stream > streams_
@ max_header_list_size
SETTINGS_MAX_HEADER_LIST_SIZE.
@ max_concurrent_streams
SETTINGS_MAX_CONCURRENT_STREAMS.
@ initial_window_size
SETTINGS_INITIAL_WINDOW_SIZE.
stream_state
HTTP/2 stream state (RFC 7540 Section 5.1)
@ half_closed_remote
Remote end closed, local can send.
@ half_closed_local
Local end closed, remote can send.
Network-specific error and result type definitions.
std::vector< uint8_t > body
Response body.
auto get_header(const std::string &name) const -> std::optional< std::string >
Get header value by name.
auto get_body_string() const -> std::string
Get body as string.
std::vector< http_header > headers
Response headers.
std::vector< uint8_t > request_body
Request body.
std::vector< http_header > response_headers
Response headers.
http2_stream & operator=(http2_stream &&)=default
std::promise< http2_response > promise
Response promise.
std::vector< http_header > request_headers
Request headers.
std::function< void(std::vector< uint8_t >)> on_data
Callback for streaming data.
std::function< void(std::vector< http_header >)> on_headers
Callback for headers.
std::function< void(int)> on_complete
Callback when stream ends (status code)
std::vector< uint8_t > response_body
Response body.
HTTP header name-value pair.
Definition hpack.h:24