Network System 0.1.1
High-performance modular networking library for scalable client-server applications
Loading...
Searching...
No Matches
secure_session.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
8
10
11secure_session::secure_session(asio::ip::tcp::socket socket,
12 asio::ssl::context &ssl_context,
13 std::string_view server_id)
14 : server_id_(server_id) {
15 // Create the secure_tcp_socket wrapper
16 socket_ = std::make_shared<internal::secure_tcp_socket>(std::move(socket),
17 ssl_context);
18}
19
21 try {
22 // Call stop_session to clean up resources
24 } catch (...) {
25 // Destructor must not throw - swallow all exceptions
26 }
27}
28
30 if (is_stopped_.load()) {
31 return;
32 }
33
34 // Perform SSL handshake first
35 auto self = shared_from_this();
36 socket_->async_handshake(
37 asio::ssl::stream_base::server, [this, self](std::error_code ec) {
38 if (ec) {
39 NETWORK_LOG_ERROR("[secure_session] SSL handshake failed: " +
40 ec.message());
41 stop_session();
42 return;
43 }
44
45 NETWORK_LOG_INFO("[secure_session] SSL handshake completed");
46
47 // Set up callbacks after successful handshake
48 socket_->set_receive_callback(
49 [this, self](const std::vector<uint8_t> &data) {
50 on_receive(data);
51 });
52 socket_->set_error_callback(
53 [this, self](std::error_code ec) { on_error(ec); });
54
55 // Begin reading
56 socket_->start_read();
57
58 NETWORK_LOG_INFO("[secure_session] Started secure session on server: " +
59 server_id_);
60 });
61}
62
64 if (is_stopped_.exchange(true)) {
65 return;
66 }
67 // Close socket safely using atomic close() method
68 // This prevents data races between close and async read operations
69 if (socket_) {
70 socket_->close();
71 }
72
73 // Invoke disconnection callback if set
74 {
75 std::lock_guard<std::mutex> lock(callback_mutex_);
76 if (disconnection_callback_) {
77 try {
78 disconnection_callback_(server_id_);
79 } catch (const std::exception &e) {
81 "[secure_session] Exception in disconnection callback: " +
82 std::string(e.what()));
83 }
84 }
85 }
86
87 NETWORK_LOG_INFO("[secure_session] Stopped.");
88}
89
90auto secure_session::send_packet(std::vector<uint8_t> &&data) -> void {
91 if (is_stopped_.load()) {
92 return;
93 }
94
95 // Send data directly over the secure connection
96 socket_->async_send(
97 std::move(data), [](std::error_code ec, std::size_t bytes_transferred) {
98 if (ec) {
99 NETWORK_LOG_ERROR("[secure_session] Send error: " + ec.message());
100 } else {
101 NETWORK_LOG_DEBUG("[secure_session] Sent " +
102 std::to_string(bytes_transferred) + " bytes");
103 }
104 });
105}
106
107auto secure_session::on_receive(const std::vector<uint8_t> &data) -> void {
108 if (is_stopped_.load()) {
109 return;
110 }
111
112 NETWORK_LOG_DEBUG("[secure_session] Received " + std::to_string(data.size()) +
113 " bytes.");
114
115 // Check queue size before adding
116 {
117 std::lock_guard<std::mutex> lock(queue_mutex_);
118 size_t queue_size = pending_messages_.size();
119
120 // Apply backpressure if queue is getting full
121 if (queue_size >= max_pending_messages_) {
122 NETWORK_LOG_WARN("[secure_session] Queue size (" +
123 std::to_string(queue_size) + ") reached limit (" +
124 std::to_string(max_pending_messages_) +
125 "). Applying backpressure.");
126
127 // If queue is severely overflowing, disconnect the session
128 if (queue_size >= max_pending_messages_ * 2) {
129 NETWORK_LOG_ERROR("[secure_session] Queue overflow (" +
130 std::to_string(queue_size) +
131 "). Disconnecting abusive client.");
132 stop_session();
133 return;
134 }
135 }
136
137 // Add message to queue
138 pending_messages_.push_back(data);
139 }
140
141 // Process messages from queue
142 process_next_message();
143}
144
145auto secure_session::on_error(std::error_code ec) -> void {
146 NETWORK_LOG_ERROR("[secure_session] Socket error: " + ec.message());
147
148 // Invoke error callback if set
149 {
150 std::lock_guard<std::mutex> lock(callback_mutex_);
151 if (error_callback_) {
152 try {
153 error_callback_(ec);
154 } catch (const std::exception &e) {
155 NETWORK_LOG_ERROR("[secure_session] Exception in error callback: " +
156 std::string(e.what()));
157 }
158 }
159 }
160
161 stop_session();
162}
163
165 std::vector<uint8_t> message;
166
167 // Dequeue one message
168 {
169 std::lock_guard<std::mutex> lock(queue_mutex_);
170 if (pending_messages_.empty()) {
171 return;
172 }
173
174 message = std::move(pending_messages_.front());
175 pending_messages_.pop_front();
176 }
177
178 // Process the message
180 "[secure_session] Processing message of " +
181 std::to_string(message.size()) +
182 " bytes. Queue remaining: " + std::to_string(pending_messages_.size()));
183
184 // Invoke receive callback if set
185 {
186 std::lock_guard<std::mutex> lock(callback_mutex_);
187 if (receive_callback_) {
188 try {
189 receive_callback_(message);
190 } catch (const std::exception &e) {
191 NETWORK_LOG_ERROR("[secure_session] Exception in receive callback: " +
192 std::string(e.what()));
193 }
194 }
195 }
196
197 // If there are more messages, process them asynchronously
198 // to avoid blocking the receive thread
199 std::lock_guard<std::mutex> lock(queue_mutex_);
200 if (!pending_messages_.empty()) {
201 // In a production system, you might want to post this to a thread pool
202 // or use a work queue to process messages asynchronously
203 // For now, we just process one message per call
204 }
205}
206
208 std::function<void(const std::vector<uint8_t> &)> callback) -> void {
209 std::lock_guard<std::mutex> lock(callback_mutex_);
210 receive_callback_ = std::move(callback);
211}
212
214 std::function<void(const std::string &)> callback) -> void {
215 std::lock_guard<std::mutex> lock(callback_mutex_);
216 disconnection_callback_ = std::move(callback);
217}
218
220 std::function<void(std::error_code)> callback) -> void {
221 std::lock_guard<std::mutex> lock(callback_mutex_);
222 error_callback_ = std::move(callback);
223}
224
225} // namespace kcenon::network::session
auto stop_session() -> void
Stops the session by closing the socket and marking the session as inactive.
auto process_next_message() -> void
Processes pending messages from the queue.
std::shared_ptr< internal::secure_tcp_socket > socket_
~secure_session() noexcept
Destructor; calls stop_session() if not already stopped.
auto set_error_callback(std::function< void(std::error_code)> callback) -> void
Sets the callback for errors.
auto set_disconnection_callback(std::function< void(const std::string &)> callback) -> void
Sets the callback for disconnection.
auto set_receive_callback(std::function< void(const std::vector< uint8_t > &)> callback) -> void
Sets the callback for received data.
auto start_session() -> void
Starts the session: performs SSL handshake, sets up read/error callbacks, and begins reading data.
auto on_error(std::error_code ec) -> void
Callback for handling socket errors from secure_tcp_socket.
secure_session(asio::ip::tcp::socket socket, asio::ssl::context &ssl_context, std::string_view server_id)
Constructs a secure session with a given socket, SSL context, and server_id.
auto send_packet(std::vector< uint8_t > &&data) -> void
Sends data to the connected client with encryption.
auto on_receive(const std::vector< uint8_t > &data) -> void
Callback for when encrypted data arrives from the client.
Logger system integration interface for network_system.
#define NETWORK_LOG_WARN(msg)
#define NETWORK_LOG_INFO(msg)
#define NETWORK_LOG_ERROR(msg)
#define NETWORK_LOG_DEBUG(msg)
TLS-secured session wrapper for encrypted communication.