Network System 0.1.1
High-performance modular networking library for scalable client-server applications
Loading...
Searching...
No Matches
udp_connection_adapter.cpp
Go to the documentation of this file.
1// BSD 3-Clause License
2// Copyright (c) 2025, 🍀☀🌕🌥 🌊
3// See the LICENSE file in the project root for full license information.
4
6
7#include <algorithm>
8#include <cstring>
9
11
13 : connection_id_(connection_id)
14 , client_(std::make_shared<core::messaging_udp_client>(connection_id))
15{
17}
18
23
24auto udp_connection_adapter::send(std::span<const std::byte> data) -> VoidResult
25{
26 if (!client_ || !client_->is_running()) {
27 return error_void(
28 static_cast<int>(std::errc::not_connected),
29 "UDP client is not running"
30 );
31 }
32
33 std::vector<uint8_t> buffer(data.size());
34 std::memcpy(buffer.data(), data.data(), data.size());
35
36 return client_->send(std::move(buffer));
37}
38
39auto udp_connection_adapter::send(std::vector<uint8_t>&& data) -> VoidResult
40{
41 if (!client_ || !client_->is_running()) {
42 return error_void(
43 static_cast<int>(std::errc::not_connected),
44 "UDP client is not running"
45 );
46 }
47
48 return client_->send(std::move(data));
49}
50
51auto udp_connection_adapter::is_connected() const noexcept -> bool
52{
53 // For UDP, "connected" means the client is running with a target endpoint
54 return client_ && client_->is_running();
55}
56
57auto udp_connection_adapter::id() const noexcept -> std::string_view
58{
59 return connection_id_;
60}
61
63{
64 std::lock_guard lock(endpoint_mutex_);
65 return remote_endpoint_;
66}
67
69{
70 std::lock_guard lock(endpoint_mutex_);
71 return local_endpoint_;
72}
73
75{
76 if (!client_) {
77 return error_void(
78 static_cast<int>(std::errc::invalid_argument),
79 "Client is not initialized"
80 );
81 }
82
83 if (client_->is_running()) {
84 return error_void(
85 static_cast<int>(std::errc::already_connected),
86 "Already running"
87 );
88 }
89
90 {
91 std::lock_guard lock(endpoint_mutex_);
92 remote_endpoint_ = endpoint;
93 }
94
95 is_connecting_ = true;
96 auto result = client_->start_client(endpoint.host, endpoint.port);
97
98 if (result.is_ok()) {
99 is_connecting_ = false;
100 // For UDP, we're immediately "connected" once started
101 std::lock_guard lock(callbacks_mutex_);
102 if (callbacks_.on_connected) {
103 callbacks_.on_connected();
104 }
105 } else {
106 is_connecting_ = false;
107 }
108
109 return result;
110}
111
112auto udp_connection_adapter::connect(std::string_view url) -> VoidResult
113{
114 // Parse URL for UDP: expect format "udp://host:port" or just "host:port"
115 std::string url_str(url);
116
117 // Remove udp:// prefix if present
118 const std::string udp_prefix = "udp://";
119 if (url_str.substr(0, udp_prefix.size()) == udp_prefix) {
120 url_str = url_str.substr(udp_prefix.size());
121 }
122
123 // Find the last colon for port separation
124 auto colon_pos = url_str.rfind(':');
125 if (colon_pos == std::string::npos) {
126 return error_void(
127 static_cast<int>(std::errc::invalid_argument),
128 "URL must contain port number (format: host:port)"
129 );
130 }
131
132 std::string host = url_str.substr(0, colon_pos);
133 std::string port_str = url_str.substr(colon_pos + 1);
134
135 uint16_t port = 0;
136 try {
137 port = static_cast<uint16_t>(std::stoi(port_str));
138 } catch (...) {
139 return error_void(
140 static_cast<int>(std::errc::invalid_argument),
141 "Invalid port number in URL"
142 );
143 }
144
145 return connect(endpoint_info{host, port});
146}
147
148auto udp_connection_adapter::close() noexcept -> void
149{
150 if (client_ && client_->is_running()) {
151 (void)client_->stop_client();
152
153 std::lock_guard lock(callbacks_mutex_);
156 }
157 }
158 is_connecting_ = false;
159}
160
162{
163 {
164 std::lock_guard lock(callbacks_mutex_);
165 callbacks_ = std::move(callbacks);
166 }
167
168 // Re-setup internal callbacks to use the new user callbacks
169 setup_internal_callbacks();
170}
171
173{
174 options_ = options;
175}
176
177auto udp_connection_adapter::set_timeout(std::chrono::milliseconds timeout) -> void
178{
179 options_.connect_timeout = timeout;
180}
181
182auto udp_connection_adapter::is_connecting() const noexcept -> bool
183{
184 return is_connecting_.load();
185}
186
188{
189 if (client_) {
190 client_->wait_for_stop();
191 }
192}
193
195{
196 if (!client_) {
197 return;
198 }
199
200 // Bridge receive callback
201 client_->set_receive_callback(
202 [this](const std::vector<uint8_t>& data,
204 // Update local endpoint information if we receive from the expected target
205 {
206 std::lock_guard ep_lock(endpoint_mutex_);
207 // Note: local_endpoint_ would require socket info which isn't easily available
208 }
209
210 std::lock_guard lock(callbacks_mutex_);
211 if (callbacks_.on_data) {
212 std::span<const std::byte> byte_span(
213 reinterpret_cast<const std::byte*>(data.data()),
214 data.size()
215 );
216 callbacks_.on_data(byte_span);
217 }
218 });
219
220 // Bridge error callback
221 client_->set_error_callback([this](std::error_code ec) {
222 is_connecting_ = false;
223
224 std::lock_guard lock(callbacks_mutex_);
225 if (callbacks_.on_error) {
226 callbacks_.on_error(ec);
227 }
228 });
229}
230
231} // namespace kcenon::network::unified::adapters
auto send(std::span< const std::byte > data) -> VoidResult override
Sends raw data to the remote endpoint.
auto id() const noexcept -> std::string_view override
Gets the unique identifier for this transport/connection.
auto is_connected() const noexcept -> bool override
Checks if the transport is currently connected.
auto local_endpoint() const noexcept -> endpoint_info override
Gets the local endpoint information.
auto set_callbacks(connection_callbacks callbacks) -> void override
Sets all connection callbacks at once.
auto connect(const endpoint_info &endpoint) -> VoidResult override
Connects to a remote endpoint using host/port.
auto set_options(connection_options options) -> void override
Sets connection options.
auto setup_internal_callbacks() -> void
Sets up internal callbacks to bridge to unified callbacks.
auto set_timeout(std::chrono::milliseconds timeout) -> void override
Sets the connection timeout.
udp_connection_adapter(std::string_view connection_id)
Constructs an adapter with a unique connection ID.
auto close() noexcept -> void override
Closes the connection gracefully.
auto wait_for_stop() -> void override
Blocks until the component has stopped.
std::shared_ptr< core::messaging_udp_client > client_
auto remote_endpoint() const noexcept -> endpoint_info override
Gets the remote endpoint information.
auto is_connecting() const noexcept -> bool override
Checks if the connection is in the process of connecting.
~udp_connection_adapter() override
Destructor ensures proper cleanup.
VoidResult error_void(int code, const std::string &message, const std::string &source="network_system", const std::string &details="")
Endpoint information for UDP datagrams.
Callback functions for connection events.
Definition types.h:154
std::function< void()> on_disconnected
Called when connection is closed.
Definition types.h:162
Configuration options for connections.
Definition types.h:198
Network endpoint information (host/port or URL)
Definition types.h:56