Network System 0.1.1
High-performance modular networking library for scalable client-server applications
Loading...
Searching...
No Matches
quic_server_adapter.cpp
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
6
9
10// Enable experimental API for QUIC
11#ifndef NETWORK_USE_EXPERIMENTAL
12#define NETWORK_USE_EXPERIMENTAL
13#endif
14
16
20
22
23// =========================================================================
24// quic_session_wrapper implementation
25// =========================================================================
26
28 std::string_view session_id,
29 std::shared_ptr<session::quic_session> session)
30 : session_id_(session_id)
31 , session_(std::move(session))
32{
33}
34
35auto quic_session_wrapper::id() const -> std::string_view
36{
37 return session_id_;
38}
39
41{
42 return is_connected_.load(std::memory_order_acquire) &&
43 session_ && session_->is_active();
44}
45
46auto quic_session_wrapper::send(std::vector<uint8_t>&& data) -> VoidResult
47{
48 if (!is_connected_.load(std::memory_order_acquire))
49 {
50 return error_void(
52 "Session is not connected",
53 "quic_session_wrapper::send"
54 );
55 }
56
57 if (!session_)
58 {
59 return error_void(
61 "Session not initialized",
62 "quic_session_wrapper::send"
63 );
64 }
65
66 // Send using the interface send method
67 return session_->send(std::move(data));
68}
69
71{
72 is_connected_.store(false, std::memory_order_release);
73 if (session_)
74 {
75 (void)session_->close(0); // 0 = no error
76 }
77}
78
79// =========================================================================
80// quic_server_adapter implementation
81// =========================================================================
82
84 : server_id_(server_id)
85 , server_(std::make_shared<core::messaging_quic_server>(server_id))
86{
88}
89
91{
92 if (server_ && is_running_.load(std::memory_order_acquire))
93 {
94 (void)server_->stop();
95 }
96}
97
98// =========================================================================
99// QUIC-specific Configuration
100// =========================================================================
101
102auto quic_server_adapter::set_cert_path(std::string_view path) -> void
103{
104 cert_path_ = std::string(path);
105}
106
107auto quic_server_adapter::set_key_path(std::string_view path) -> void
108{
109 key_path_ = std::string(path);
110}
111
112auto quic_server_adapter::set_alpn_protocols(const std::vector<std::string>& protocols) -> void
113{
114 alpn_protocols_ = protocols;
115}
116
117auto quic_server_adapter::set_ca_cert_path(std::string_view path) -> void
118{
119 ca_cert_path_ = std::string(path);
120}
121
123{
124 require_client_cert_ = require;
125}
126
127auto quic_server_adapter::set_max_idle_timeout(uint64_t timeout_ms) -> void
128{
129 max_idle_timeout_ms_ = timeout_ms;
130}
131
133{
134 max_connections_ = max;
135}
136
137// =========================================================================
138// i_network_component interface implementation
139// =========================================================================
140
142{
143 return is_running_.load(std::memory_order_acquire);
144}
145
147{
148 if (server_)
149 {
150 server_->wait_for_stop();
151 }
152}
153
154// =========================================================================
155// i_protocol_server interface implementation
156// =========================================================================
157
159{
160 if (!server_)
161 {
162 return error_void(
164 "Server not initialized",
165 "quic_server_adapter::start"
166 );
167 }
168
169 // Build configuration
171 config.cert_file = cert_path_;
172 config.key_file = key_path_;
173 config.ca_cert_file = ca_cert_path_;
174 config.require_client_cert = require_client_cert_;
175 config.alpn_protocols = alpn_protocols_;
176 config.max_idle_timeout_ms = max_idle_timeout_ms_;
177 config.max_connections = max_connections_;
178
179 auto result = server_->start_server(port, config);
180 if (result.is_ok())
181 {
182 is_running_.store(true, std::memory_order_release);
183 }
184 return result;
185}
186
188{
189 if (!server_)
190 {
191 return error_void(
193 "Server not initialized",
194 "quic_server_adapter::stop"
195 );
196 }
197
198 auto result = server_->stop_server();
199 is_running_.store(false, std::memory_order_release);
200
201 // Clear tracked sessions on stop
202 {
203 std::lock_guard<std::mutex> lock(sessions_mutex_);
204 sessions_.clear();
205 }
206
207 return result;
208}
209
211{
212 std::lock_guard<std::mutex> lock(sessions_mutex_);
213 return sessions_.size();
214}
215
217{
218 std::lock_guard<std::mutex> lock(callbacks_mutex_);
219 connection_callback_ = std::move(callback);
220}
221
223{
224 std::lock_guard<std::mutex> lock(callbacks_mutex_);
225 disconnection_callback_ = std::move(callback);
226}
227
229{
230 std::lock_guard<std::mutex> lock(callbacks_mutex_);
231 receive_callback_ = std::move(callback);
232}
233
235{
236 std::lock_guard<std::mutex> lock(callbacks_mutex_);
237 error_callback_ = std::move(callback);
238}
239
240// =========================================================================
241// Internal methods
242// =========================================================================
243
245{
246 if (!server_)
247 {
248 return;
249 }
250
251 // Bridge connection callback using the legacy callback type (takes quic_session directly)
253 [this](std::shared_ptr<session::quic_session> quic_sess) {
254 if (!quic_sess)
255 {
256 return;
257 }
258
259 auto wrapper = get_or_create_wrapper(quic_sess);
260
261 connection_callback_t callback_copy;
262 {
263 std::lock_guard<std::mutex> lock(callbacks_mutex_);
264 callback_copy = connection_callback_;
265 }
266
267 if (callback_copy)
268 {
269 callback_copy(wrapper);
270 }
271 };
272 server_->set_connection_callback(conn_cb);
273
274 // Bridge disconnection callback
275 server_->set_disconnection_callback(
276 [this](std::string_view session_id) {
277 disconnection_callback_t callback_copy;
278 {
279 std::lock_guard<std::mutex> lock(callbacks_mutex_);
280 callback_copy = disconnection_callback_;
281 }
282
283 if (callback_copy)
284 {
285 callback_copy(session_id);
286 }
287
288 remove_wrapper(std::string(session_id));
289 });
290
291 // Bridge receive callback
292 server_->set_receive_callback(
293 [this](std::string_view session_id, const std::vector<uint8_t>& data) {
294 receive_callback_t callback_copy;
295 {
296 std::lock_guard<std::mutex> lock(callbacks_mutex_);
297 callback_copy = receive_callback_;
298 }
299
300 if (callback_copy)
301 {
302 callback_copy(session_id, data);
303 }
304 });
305
306 // Bridge error callback
307 server_->set_error_callback(
308 [this](std::string_view session_id, std::error_code ec) {
309 error_callback_t callback_copy;
310 {
311 std::lock_guard<std::mutex> lock(callbacks_mutex_);
312 callback_copy = error_callback_;
313 }
314
315 if (callback_copy)
316 {
317 callback_copy(session_id, ec);
318 }
319 });
320}
321
322auto quic_server_adapter::get_or_create_wrapper(std::shared_ptr<session::quic_session> session)
323 -> std::shared_ptr<quic_session_wrapper>
324{
325 const std::string session_id = session->session_id();
326
327 std::lock_guard<std::mutex> lock(sessions_mutex_);
328
329 auto it = sessions_.find(session_id);
330 if (it != sessions_.end())
331 {
332 return it->second;
333 }
334
335 auto wrapper = std::make_shared<quic_session_wrapper>(session_id, session);
336 sessions_[session_id] = wrapper;
337 return wrapper;
338}
339
340auto quic_server_adapter::remove_wrapper(const std::string& session_id) -> void
341{
342 std::lock_guard<std::mutex> lock(sessions_mutex_);
343 sessions_.erase(session_id);
344}
345
346} // namespace kcenon::network::internal::adapters
std::function< void(std::shared_ptr< session::quic_session >)> connection_callback_t
Callback type for new connections.
std::function< void(std::string_view)> disconnection_callback_t
Callback type for disconnections (session_id)
std::function< void(std::string_view, const std::vector< uint8_t > &)> receive_callback_t
Callback type for received data (session_id, data)
std::function< void(std::string_view, std::error_code)> error_callback_t
Callback type for errors (session_id, error)
std::function< void(std::shared_ptr< i_session >)> connection_callback_t
Callback type for new connections.
auto start(uint16_t port) -> VoidResult override
Starts the server and begins listening for connections.
std::unordered_map< std::string, std::shared_ptr< quic_session_wrapper > > sessions_
auto set_error_callback(error_callback_t callback) -> void override
Sets the callback for errors.
~quic_server_adapter() override
Destructor ensures proper cleanup.
auto set_ca_cert_path(std::string_view path) -> void
Sets CA certificate path for client verification.
auto set_key_path(std::string_view path) -> void
Sets the server private key path.
std::shared_ptr< core::messaging_quic_server > server_
auto is_running() const -> bool override
Checks if the component is currently running.
auto wait_for_stop() -> void override
Blocks until the component has stopped.
auto remove_wrapper(const std::string &session_id) -> void
Removes a session wrapper.
auto set_disconnection_callback(disconnection_callback_t callback) -> void override
Sets the callback for disconnections.
auto set_require_client_cert(bool require) -> void
Sets whether to require client certificate (mutual TLS)
auto stop() -> VoidResult override
Stops the server and closes all connections.
auto setup_internal_callbacks() -> void
Sets up internal callbacks to bridge QUIC callbacks to i_protocol_server callbacks.
auto set_connection_callback(connection_callback_t callback) -> void override
Sets the callback for new connections.
auto set_alpn_protocols(const std::vector< std::string > &protocols) -> void
Sets the ALPN protocols for negotiation.
auto get_or_create_wrapper(std::shared_ptr< session::quic_session > session) -> std::shared_ptr< quic_session_wrapper >
Creates or retrieves a session wrapper for a QUIC session.
quic_server_adapter(std::string_view server_id)
Constructs an adapter with a unique server ID.
auto set_max_idle_timeout(uint64_t timeout_ms) -> void
Sets max idle timeout in milliseconds.
auto set_receive_callback(receive_callback_t callback) -> void override
Sets the callback for received data.
auto set_cert_path(std::string_view path) -> void
Sets the server certificate path.
auto connection_count() const -> size_t override
Gets the number of active client connections.
auto set_max_connections(size_t max) -> void
Sets maximum number of concurrent connections.
auto is_connected() const -> bool override
Checks if the session is currently connected.
quic_session_wrapper(std::string_view session_id, std::shared_ptr< session::quic_session > session)
Constructs a session wrapper.
auto send(std::vector< uint8_t > &&data) -> VoidResult override
Sends data to the client.
auto id() const -> std::string_view override
Gets the unique identifier for this session.
tracing_config config
Definition exporters.cpp:29
VoidResult error_void(int code, const std::string &message, const std::string &source="network_system", const std::string &details="")
VoidResult ok()
QUIC-specific session with stream multiplexing.
Network-specific error and result type definitions.
Configuration options for QUIC server.
Definition quic_server.h:63