Network System 0.1.1
High-performance modular networking library for scalable client-server applications
Loading...
Searching...
No Matches
udp_client_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
8
10
11udp_client_adapter::udp_client_adapter(std::string_view client_id)
12 : client_id_(client_id)
13 , client_(std::make_shared<core::messaging_udp_client>(std::string(client_id)))
14{
16}
17
19{
20 if (client_ && client_->is_running())
21 {
22 (void)client_->stop();
23 }
24}
25
26// =========================================================================
27// i_network_component interface implementation
28// =========================================================================
29
31{
32 return client_ && client_->is_running();
33}
34
36{
37 if (client_)
38 {
39 client_->wait_for_stop();
40 }
41}
42
43// =========================================================================
44// i_protocol_client interface implementation
45// =========================================================================
46
47auto udp_client_adapter::start(std::string_view host, uint16_t port) -> VoidResult
48{
49 if (!client_)
50 {
51 return error_void(
53 "Client not initialized",
54 "udp_client_adapter::start"
55 );
56 }
57
58 auto result = client_->start(host, port);
59 if (result.is_ok())
60 {
61 is_connected_.store(true, std::memory_order_release);
62
63 // Invoke connected callback/observer since we've "connected" to the target
64 std::shared_ptr<interfaces::connection_observer> observer_copy;
65 connected_callback_t callback_copy;
66 {
67 std::lock_guard<std::mutex> lock(callbacks_mutex_);
68 observer_copy = observer_;
69 callback_copy = connected_callback_;
70 }
71
72 if (observer_copy)
73 {
74 observer_copy->on_connected();
75 }
76 if (callback_copy)
77 {
78 callback_copy();
79 }
80 }
81
82 return result;
83}
84
86{
87 if (!client_)
88 {
89 return error_void(
91 "Client not initialized",
92 "udp_client_adapter::stop"
93 );
94 }
95
96 bool was_connected = is_connected_.exchange(false, std::memory_order_acq_rel);
97 auto result = client_->stop();
98
99 // Invoke disconnected callback/observer if we were connected
100 if (was_connected)
101 {
102 std::shared_ptr<interfaces::connection_observer> observer_copy;
103 disconnected_callback_t callback_copy;
104 {
105 std::lock_guard<std::mutex> lock(callbacks_mutex_);
106 observer_copy = observer_;
107 callback_copy = disconnected_callback_;
108 }
109
110 if (observer_copy)
111 {
112 observer_copy->on_disconnected();
113 }
114 if (callback_copy)
115 {
116 callback_copy();
117 }
118 }
119
120 return result;
121}
122
123auto udp_client_adapter::send(std::vector<uint8_t>&& data) -> VoidResult
124{
125 if (!client_)
126 {
127 return error_void(
129 "Client not initialized",
130 "udp_client_adapter::send"
131 );
132 }
133
134 if (!is_connected_.load(std::memory_order_acquire))
135 {
136 return error_void(
138 "Client is not connected - call start() first",
139 "udp_client_adapter::send"
140 );
141 }
142
143 return client_->send(std::move(data));
144}
145
147{
148 return is_connected_.load(std::memory_order_acquire);
149}
150
151auto udp_client_adapter::set_observer(std::shared_ptr<interfaces::connection_observer> observer) -> void
152{
153 std::lock_guard<std::mutex> lock(callbacks_mutex_);
154 observer_ = std::move(observer);
155}
156
158{
159 std::lock_guard<std::mutex> lock(callbacks_mutex_);
160 receive_callback_ = std::move(callback);
161}
162
164{
165 std::lock_guard<std::mutex> lock(callbacks_mutex_);
166 connected_callback_ = std::move(callback);
167}
168
170{
171 std::lock_guard<std::mutex> lock(callbacks_mutex_);
172 disconnected_callback_ = std::move(callback);
173}
174
176{
177 std::lock_guard<std::mutex> lock(callbacks_mutex_);
178 error_callback_ = std::move(callback);
179}
180
181// =========================================================================
182// Internal methods
183// =========================================================================
184
186{
187 if (!client_)
188 {
189 return;
190 }
191
192 // Bridge UDP receive callback to i_protocol_client callback
193 // Note: UDP receive includes endpoint info which we discard for the unified interface
194 client_->set_receive_callback(
195 [this](const std::vector<uint8_t>& data,
196 const interfaces::i_udp_client::endpoint_info& /* endpoint */)
197 {
198 std::shared_ptr<interfaces::connection_observer> observer_copy;
199 receive_callback_t callback_copy;
200 {
201 std::lock_guard<std::mutex> lock(callbacks_mutex_);
202 observer_copy = observer_;
203 callback_copy = receive_callback_;
204 }
205
206 if (observer_copy)
207 {
208 observer_copy->on_receive(data);
209 }
210 if (callback_copy)
211 {
212 callback_copy(data);
213 }
214 });
215
216 // Bridge UDP error callback
217 client_->set_error_callback(
218 [this](std::error_code ec)
219 {
220 std::shared_ptr<interfaces::connection_observer> observer_copy;
221 error_callback_t callback_copy;
222 {
223 std::lock_guard<std::mutex> lock(callbacks_mutex_);
224 observer_copy = observer_;
225 callback_copy = error_callback_;
226 }
227
228 if (observer_copy)
229 {
230 observer_copy->on_error(ec);
231 }
232 if (callback_copy)
233 {
234 callback_copy(ec);
235 }
236 });
237}
238
239} // namespace kcenon::network::internal::adapters
std::function< void(const std::vector< uint8_t > &)> receive_callback_t
Callback type for received data.
std::function< void()> connected_callback_t
Callback type for connection established.
std::function< void(std::error_code)> error_callback_t
Callback type for errors.
std::function< void()> disconnected_callback_t
Callback type for disconnection.
auto is_connected() const -> bool override
Checks if the client is connected to the server.
auto stop() -> VoidResult override
Stops the client and closes the connection.
auto set_disconnected_callback(disconnected_callback_t callback) -> void override
Sets the callback for disconnection.
auto start(std::string_view host, uint16_t port) -> VoidResult override
Starts the client and connects to the specified server.
auto is_running() const -> bool override
Checks if the component is currently running.
auto send(std::vector< uint8_t > &&data) -> VoidResult override
Sends data to the connected server.
~udp_client_adapter() override
Destructor ensures proper cleanup.
auto set_error_callback(error_callback_t callback) -> void override
Sets the callback for errors.
auto set_receive_callback(receive_callback_t callback) -> void override
Sets the callback for received data.
auto set_connected_callback(connected_callback_t callback) -> void override
Sets the callback for connection established.
udp_client_adapter(std::string_view client_id)
Constructs an adapter with a unique client ID.
auto wait_for_stop() -> void override
Blocks until the component has stopped.
auto setup_internal_callbacks() -> void
Sets up internal callbacks to bridge UDP callbacks to i_protocol_client callbacks.
auto set_observer(std::shared_ptr< interfaces::connection_observer > observer) -> void override
Sets the connection observer for unified event handling.
std::shared_ptr< core::messaging_udp_client > client_
UDP client class.
VoidResult error_void(int code, const std::string &message, const std::string &source="network_system", const std::string &details="")
Endpoint information for UDP datagrams.