Line data Source code
1 : #ifndef THINGER_SERVER_HTTP_SERVER_CONNECTION_HPP
2 : #define THINGER_SERVER_HTTP_SERVER_CONNECTION_HPP
3 :
4 : #include <queue>
5 : #include <atomic>
6 : #include <mutex>
7 : #include "request_factory.hpp"
8 : #include "../common/http_frame.hpp"
9 : #include "../common/http_request.hpp"
10 : #include "../common/http_response.hpp"
11 : #include "http_stream.hpp"
12 : #include "request_handler.hpp"
13 : #include "../../util/types.hpp"
14 :
15 : namespace thinger::http {
16 :
17 : class request;
18 :
19 : class server_connection : public std::enable_shared_from_this<server_connection>, public boost::noncopyable {
20 :
21 : static constexpr size_t MAX_BUFFER_SIZE = 4096;
22 : static constexpr auto DEFAULT_TIMEOUT = std::chrono::seconds{120};
23 : static constexpr size_t DEFAULT_MAX_BODY_SIZE = 8 * 1024 * 1024; // 8MB
24 :
25 : public:
26 : static std::atomic<unsigned long> connections;
27 :
28 : explicit server_connection(std::shared_ptr<asio::socket> socket);
29 : virtual ~server_connection();
30 :
31 : // Start processing requests (spawns the read loop coroutine)
32 : void start(std::chrono::seconds timeout = DEFAULT_TIMEOUT);
33 :
34 : // Release the socket for upgrades (WebSocket, etc.)
35 : std::shared_ptr<asio::socket> release_socket();
36 :
37 : // Release this instance without touching the socket
38 : void release();
39 :
40 : // Get the raw socket
41 : std::shared_ptr<asio::socket> get_socket();
42 :
43 : // Handle a response frame (can be called from any thread)
44 : void handle_stream(std::shared_ptr<http_stream> stream, std::shared_ptr<http_frame> frame);
45 :
46 : // Update connection timeout
47 : void update_connection_timeout(std::chrono::seconds timeout);
48 :
49 : // Set request handler (awaitable — dispatch coroutine)
50 846 : void set_handler(std::function<awaitable<void>(std::shared_ptr<request>)> handler) {
51 846 : handler_ = std::move(handler);
52 846 : }
53 :
54 : // Set maximum allowed body size
55 : void set_max_body_size(size_t size) {
56 : max_body_size_ = size;
57 : }
58 :
59 : private:
60 : // Main read loop coroutine
61 : awaitable<void> read_loop();
62 :
63 : // Write output queue
64 : awaitable<void> write_frame(std::shared_ptr<http_stream> stream, std::shared_ptr<http_frame> frame);
65 :
66 : // Process the output queue
67 : void process_output_queue();
68 :
69 : // Handle stock error responses
70 : void handle_stock_error(std::shared_ptr<http_stream> stream, http_response::status status);
71 :
72 : // Reset timeout timer
73 : void reset_timeout();
74 :
75 : // Close connection
76 : void close();
77 :
78 : private:
79 : std::shared_ptr<asio::socket> socket_;
80 : boost::asio::steady_timer timeout_timer_;
81 : std::chrono::seconds timeout_{DEFAULT_TIMEOUT};
82 :
83 : uint8_t buffer_[MAX_BUFFER_SIZE];
84 : request_factory request_parser_;
85 :
86 : // Queue for HTTP pipelining
87 : std::queue<std::shared_ptr<http_stream>> request_queue_;
88 : std::mutex queue_mutex_;
89 :
90 : // Request handler callback (awaitable coroutine)
91 : std::function<awaitable<void>(std::shared_ptr<request>)> handler_;
92 :
93 : // State
94 : bool writing_{false};
95 : bool running_{false};
96 : stream_id request_id_{0};
97 : size_t max_body_size_{DEFAULT_MAX_BODY_SIZE};
98 : };
99 :
100 : }
101 :
102 : #endif
|