Network System 0.1.1
High-performance modular networking library for scalable client-server applications
Loading...
Searching...
No Matches
http_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
11#include <sstream>
12
16
18
20 std::string_view client_id,
21 std::chrono::milliseconds timeout)
22 : client_id_(client_id)
23 , timeout_(timeout)
24 , client_(std::make_shared<core::http_client>(timeout))
25{
26}
27
29{
30 is_running_.store(false, std::memory_order_release);
31}
32
33// =========================================================================
34// Path Configuration
35// =========================================================================
36
37auto http_client_adapter::set_path(std::string_view path) -> void
38{
39 path_ = std::string(path);
40}
41
42auto http_client_adapter::set_use_ssl(bool use_ssl) -> void
43{
44 use_ssl_ = use_ssl;
45}
46
47// =========================================================================
48// i_network_component interface implementation
49// =========================================================================
50
52{
53 return is_running_.load(std::memory_order_acquire);
54}
55
57{
58 // HTTP client is stateless, nothing to wait for
59}
60
61// =========================================================================
62// i_protocol_client interface implementation
63// =========================================================================
64
65auto http_client_adapter::start(std::string_view host, uint16_t port) -> VoidResult
66{
67 if (!client_)
68 {
69 return error_void(
71 "Client not initialized",
72 "http_client_adapter::start"
73 );
74 }
75
76 // Store the connection details for building URLs
77 host_ = std::string(host);
78 port_ = port;
79 is_running_.store(true, std::memory_order_release);
80
81 // Notify connected callback (HTTP is "connected" when we have a target)
82 {
83 std::shared_ptr<interfaces::connection_observer> observer_copy;
84 connected_callback_t callback_copy;
85 {
86 std::lock_guard<std::mutex> lock(callbacks_mutex_);
87 observer_copy = observer_;
88 callback_copy = connected_callback_;
89 }
90
91 if (observer_copy)
92 {
93 observer_copy->on_connected();
94 }
95 if (callback_copy)
96 {
97 callback_copy();
98 }
99 }
100
101 return ok();
102}
103
105{
106 if (!is_running_.load(std::memory_order_acquire))
107 {
108 return error_void(
110 "Client is not running",
111 "http_client_adapter::stop"
112 );
113 }
114
115 is_running_.store(false, std::memory_order_release);
116
117 // Notify disconnected callback
118 {
119 std::shared_ptr<interfaces::connection_observer> observer_copy;
120 disconnected_callback_t callback_copy;
121 {
122 std::lock_guard<std::mutex> lock(callbacks_mutex_);
123 observer_copy = observer_;
124 callback_copy = disconnected_callback_;
125 }
126
127 if (observer_copy)
128 {
129 observer_copy->on_disconnected();
130 }
131 if (callback_copy)
132 {
133 callback_copy();
134 }
135 }
136
137 return ok();
138}
139
140auto http_client_adapter::send(std::vector<uint8_t>&& data) -> VoidResult
141{
142 if (!client_)
143 {
144 return error_void(
146 "Client not initialized",
147 "http_client_adapter::send"
148 );
149 }
150
151 if (!is_running_.load(std::memory_order_acquire))
152 {
153 return error_void(
155 "Client is not running - call start() first",
156 "http_client_adapter::send"
157 );
158 }
159
160 // Build the full URL
161 const std::string url = build_url();
162
163 // Perform HTTP POST request with the binary data
164 auto result = client_->post(url, data);
165 if (result.is_err())
166 {
167 notify_error(std::make_error_code(std::errc::io_error));
168 return error_void(
170 "HTTP POST request failed: " + result.error().message,
171 "http_client_adapter::send"
172 );
173 }
174
175 // Notify receive callback with response body
176 const auto& response = result.value();
177 notify_receive(response.body);
178
179 return ok();
180}
181
183{
184 return is_running_.load(std::memory_order_acquire) && !host_.empty();
185}
186
187auto http_client_adapter::set_observer(std::shared_ptr<interfaces::connection_observer> observer) -> void
188{
189 std::lock_guard<std::mutex> lock(callbacks_mutex_);
190 observer_ = std::move(observer);
191}
192
194{
195 std::lock_guard<std::mutex> lock(callbacks_mutex_);
196 receive_callback_ = std::move(callback);
197}
198
200{
201 std::lock_guard<std::mutex> lock(callbacks_mutex_);
202 connected_callback_ = std::move(callback);
203}
204
206{
207 std::lock_guard<std::mutex> lock(callbacks_mutex_);
208 disconnected_callback_ = std::move(callback);
209}
210
212{
213 std::lock_guard<std::mutex> lock(callbacks_mutex_);
214 error_callback_ = std::move(callback);
215}
216
217// =========================================================================
218// Internal methods
219// =========================================================================
220
221auto http_client_adapter::build_url() const -> std::string
222{
223 std::ostringstream oss;
224 oss << (use_ssl_ ? "https://" : "http://")
225 << host_ << ":" << port_ << path_;
226 return oss.str();
227}
228
229auto http_client_adapter::notify_receive(const std::vector<uint8_t>& data) -> void
230{
231 std::shared_ptr<interfaces::connection_observer> observer_copy;
232 receive_callback_t callback_copy;
233 {
234 std::lock_guard<std::mutex> lock(callbacks_mutex_);
235 observer_copy = observer_;
236 callback_copy = receive_callback_;
237 }
238
239 if (observer_copy)
240 {
241 observer_copy->on_receive(data);
242 }
243 if (callback_copy)
244 {
245 callback_copy(data);
246 }
247}
248
249auto http_client_adapter::notify_error(std::error_code ec) -> void
250{
251 std::shared_ptr<interfaces::connection_observer> observer_copy;
252 error_callback_t callback_copy;
253 {
254 std::lock_guard<std::mutex> lock(callbacks_mutex_);
255 observer_copy = observer_;
256 callback_copy = error_callback_;
257 }
258
259 if (observer_copy)
260 {
261 observer_copy->on_error(ec);
262 }
263 if (callback_copy)
264 {
265 callback_copy(ec);
266 }
267}
268
269} // 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 notify_error(std::error_code ec) -> void
Notifies observers/callbacks of errors.
auto set_receive_callback(receive_callback_t callback) -> void override
Sets the callback for received data.
auto wait_for_stop() -> void override
Blocks until the component has stopped.
auto send(std::vector< uint8_t > &&data) -> VoidResult override
Sends data to the connected server.
auto notify_receive(const std::vector< uint8_t > &data) -> void
Notifies observers/callbacks of received data.
auto set_use_ssl(bool use_ssl) -> void
Sets whether to use HTTPS.
auto set_error_callback(error_callback_t callback) -> void override
Sets the callback for errors.
auto build_url() const -> std::string
Builds the full URL from stored components.
auto set_path(std::string_view path) -> void
Sets the HTTP path for requests.
http_client_adapter(std::string_view client_id, std::chrono::milliseconds timeout=std::chrono::seconds(30))
Constructs an adapter with timeout configuration.
auto is_connected() const -> bool override
Checks if the client is connected to the server.
auto set_disconnected_callback(disconnected_callback_t callback) -> void override
Sets the callback for disconnection.
auto stop() -> VoidResult override
Stops the client and closes the connection.
auto start(std::string_view host, uint16_t port) -> VoidResult override
Starts the client and connects to the specified server.
~http_client_adapter() override
Destructor ensures proper cleanup.
auto is_running() const -> bool override
Checks if the component is currently running.
auto set_connected_callback(connected_callback_t callback) -> void override
Sets the callback for connection established.
auto set_observer(std::shared_ptr< interfaces::connection_observer > observer) -> void override
Sets the connection observer for unified event handling.
VoidResult error_void(int code, const std::string &message, const std::string &source="network_system", const std::string &details="")
VoidResult ok()
Network-specific error and result type definitions.