OSSIA
Open Scenario System for Interactive Application
Loading...
Searching...
No Matches
osc_generic_protocol.hpp
1#pragma once
2#include <ossia/detail/lockfree_queue.hpp>
4#include <ossia/detail/mutex.hpp>
5#include <ossia/network/base/listening.hpp>
6#include <ossia/network/base/parameter.hpp>
7#include <ossia/network/base/protocol.hpp>
8#include <ossia/network/context.hpp>
9#include <ossia/network/domain/domain.hpp>
10#include <ossia/network/exceptions.hpp>
11#include <ossia/network/generic/generic_device.hpp>
12#include <ossia/network/generic/generic_parameter.hpp>
13#include <ossia/network/osc/detail/osc_1_0_policy.hpp>
14#include <ossia/network/osc/detail/osc_1_1_extended_policy.hpp>
15#include <ossia/network/osc/detail/osc_1_1_policy.hpp>
16#include <ossia/network/osc/detail/osc_protocol_common.hpp>
17#include <ossia/network/sockets/configuration.hpp>
18#include <ossia/network/sockets/null_socket.hpp>
19#include <ossia/network/sockets/writers.hpp>
20#include <ossia/network/value/value.hpp>
21
22#include <ossia/detail/hash_map.hpp>
23
24#include <atomic>
25#include <string>
26
27namespace ossia::net
28{
29template <typename OscMode, typename SendSocket, typename RecvSocket>
30class osc_generic_bidir_protocol final : public can_learn<ossia::net::protocol_base>
31{
32public:
33 using osc_configuration = typename OscMode::osc_configuration;
34 static constexpr bool bundled = requires { typename osc_configuration::bundled; };
35 using writer_type = socket_writer<SendSocket>;
36
37 osc_generic_bidir_protocol(
38 network_context_ptr ctx, const send_fd_configuration& send_conf,
39 const receive_fd_configuration& recv_conf)
40 : can_learn<ossia::net::protocol_base>{flags{SupportsMultiplex}}
41 , m_ctx{std::move(ctx)}
42 , m_id{*this}
43 , from_client{recv_conf, m_ctx->context}
44 , to_client{send_conf, m_ctx->context}
45 {
46 from_client.open();
47 to_client.connect();
48
49 from_client.receive([this](const char* data, std::size_t sz) {
50 if(!m_device)
51 return;
52 auto on_message = [this](auto&& msg) { this->on_received_message(msg); };
53 osc_packet_processor<decltype(on_message)>{on_message}(data, sz);
54 });
55 }
56
57 osc_generic_bidir_protocol(
58 network_context_ptr ctx, const outbound_socket_configuration& send_conf,
59 const inbound_socket_configuration& recv_conf)
60 : can_learn<ossia::net::protocol_base>{flags{SupportsMultiplex}}
61 , m_ctx{std::move(ctx)}
62 , m_id{*this}
63 , from_client{recv_conf, m_ctx->context}
64 , to_client{send_conf, m_ctx->context}
65 {
66 from_client.open();
67 to_client.connect();
68
69 from_client.receive([this](const char* data, std::size_t sz) {
70 if(!m_device)
71 return;
72 auto on_message = [this](auto&& msg) { this->on_received_message(msg); };
73 osc_packet_processor<decltype(on_message)>{on_message}(data, sz);
74 });
75 }
76
77 osc_generic_bidir_protocol(
78 network_context_ptr ctx, const outbound_socket_configuration& send_conf)
79 : can_learn<ossia::net::protocol_base>{flags{SupportsMultiplex}}
80 , m_ctx{std::move(ctx)}
81 , m_id{*this}
82 , to_client{send_conf, m_ctx->context}
83 {
84 to_client.connect();
85 }
86
87 osc_generic_bidir_protocol(
88 network_context_ptr ctx, const inbound_socket_configuration& recv_conf)
89 : can_learn<ossia::net::protocol_base>{flags{SupportsMultiplex}}
90 , m_ctx{std::move(ctx)}
91 , m_id{*this}
92 , from_client{recv_conf, m_ctx->context}
93 {
94 from_client.open();
95
96 from_client.receive([this](const char* data, std::size_t sz) {
97 if(!m_device)
98 return;
99 auto on_message = [this](auto&& msg) { this->on_received_message(msg); };
100 osc_packet_processor<decltype(on_message)>{on_message}(data, sz);
101 });
102 }
103
104 osc_generic_bidir_protocol(
105 network_context_ptr ctx, const send_fd_configuration& send_conf)
106 : can_learn<ossia::net::protocol_base>{flags{SupportsMultiplex}}
107 , m_ctx{std::move(ctx)}
108 , m_id{*this}
109 , to_client{send_conf, m_ctx->context}
110 {
111 to_client.connect();
112 }
113
114 osc_generic_bidir_protocol(
115 network_context_ptr ctx, const receive_fd_configuration& recv_conf)
116 : can_learn<ossia::net::protocol_base>{flags{SupportsMultiplex}}
117 , m_ctx{std::move(ctx)}
118 , m_id{*this}
119 , from_client{recv_conf, m_ctx->context}
120 {
121 from_client.open();
122
123 from_client.receive([this](const char* data, std::size_t sz) {
124 if(!m_device)
125 return;
126 auto on_message = [this](auto&& msg) { this->on_received_message(msg); };
127 osc_packet_processor<decltype(on_message)>{on_message}(data, sz);
128 });
129 }
130
131 osc_generic_bidir_protocol(const osc_generic_bidir_protocol&) = delete;
132 osc_generic_bidir_protocol(osc_generic_bidir_protocol&&) = delete;
133 osc_generic_bidir_protocol& operator=(const osc_generic_bidir_protocol&) = delete;
134 osc_generic_bidir_protocol& operator=(osc_generic_bidir_protocol&&) = delete;
135
136 ~osc_generic_bidir_protocol() override = default;
137
138 bool update(ossia::net::node_base& node_base) override { return false; }
139
140 bool pull(ossia::net::parameter_base& parameter_base) override { return false; }
141
142 bool observe(ossia::net::parameter_base& parameter_base, bool enable) override
143 {
144 if constexpr(!std::is_same_v<RecvSocket, ossia::net::null_socket>)
145 {
146 return OscMode::observe(*this, parameter_base, enable);
147 }
148 else
149 {
150 return false;
151 }
152 }
153
154 bool echo_incoming_message(
155 const message_origin_identifier& id, const parameter_base& addr,
156 const value& val) override
157 {
158 if constexpr(!std::is_same_v<SendSocket, ossia::net::null_socket>)
159 {
160 // FIXME bundling ?
161 return OscMode::echo_incoming_message(*this, id, addr, val);
162 }
163 else
164 {
165 return false;
166 }
167 }
168
169 bool push(const ossia::net::parameter_base& addr, const ossia::value& v) override
170 {
171 if constexpr(!std::is_same_v<SendSocket, ossia::net::null_socket>)
172 {
173 if constexpr(bundled)
174 return OscMode::push_bundle(*this, writer(), addr, v);
175 else
176 return OscMode::push(*this, addr, v);
177 }
178 else
179 {
180 return false;
181 }
182 }
183
184 bool push(const ossia::net::parameter_base& addr, ossia::value&& v) override
185 {
186 if constexpr(!std::is_same_v<SendSocket, ossia::net::null_socket>)
187 {
188 if constexpr(bundled)
189 return OscMode::push_bundle(*this, writer(), addr, std::move(v));
190 else
191 return OscMode::push(*this, addr, std::move(v));
192 }
193 else
194 {
195 return false;
196 }
197 }
198
199 bool push_raw(const ossia::net::full_parameter_data& addr) override
200 {
201 if constexpr(!std::is_same_v<SendSocket, ossia::net::null_socket>)
202 {
203 if constexpr(bundled)
204 return OscMode::push_bundle(*this, writer(), addr);
205 else
206 return OscMode::push_raw(*this, addr);
207 }
208 else
209 {
210 return false;
211 }
212 }
213
214 bool push_bundle(const std::vector<const parameter_base*>& addresses) override
215 {
216 if constexpr(!std::is_same_v<SendSocket, ossia::net::null_socket>)
217 {
218 return OscMode::push_bundle(*this, writer(), addresses);
219 }
220 else
221 {
222 return false;
223 }
224 }
225
226 bool push_bundle(tcb::span<ossia::bundle_element> addresses) override
227 {
228 if constexpr(!std::is_same_v<SendSocket, ossia::net::null_socket>)
229 {
230 return OscMode::push_bundle(*this, writer(), addresses);
231 }
232 else
233 {
234 return false;
235 }
236 }
237
238 bool push_bundle_bounded(tcb::span<ossia::bundle_element> addresses) override
239 {
240 if constexpr(!std::is_same_v<SendSocket, ossia::net::null_socket>)
241 {
242 return OscMode::push_bundle_bounded(*this, writer(), addresses);
243 }
244 else
245 {
246 return false;
247 }
248 }
249
250 bool
251 push_raw_bundle(const std::vector<ossia::net::full_parameter_data>& addresses) override
252 {
253 if constexpr(!std::is_same_v<SendSocket, ossia::net::null_socket>)
254 {
255 return OscMode::push_bundle(*this, writer(), addresses);
256 }
257 else
258 {
259 return false;
260 }
261 }
262
263 void on_received_message(const oscpack::ReceivedMessage& m)
264 {
265 if constexpr(!std::is_same_v<RecvSocket, ossia::net::null_socket>)
266 {
267 return OscMode::on_received_message(*this, m);
268 }
269 }
270
271 void set_device(ossia::net::device_base& dev) override { m_device = &dev; }
272
273 auto writer() noexcept { return writer_type{to_client}; }
274
275 using ossia::net::protocol_base::m_logger;
276 ossia::net::network_context_ptr m_ctx;
277 message_origin_identifier m_id;
278 listened_parameters m_listening;
279
280 ossia::net::device_base* m_device{};
281
282 RecvSocket from_client;
283 SendSocket to_client;
284};
285
286template <typename OscMode, typename Socket>
287class osc_generic_server_protocol final : public can_learn<ossia::net::protocol_base>
288{
289public:
290 using osc_configuration = typename OscMode::osc_configuration;
291 static constexpr bool bundled = requires { typename osc_configuration::bundled; };
292 using socket_type = Socket;
293 using writer_type = socket_writer<socket_type>;
294
295 template <typename Configuration>
296 requires(requires(Configuration conf) { Socket{conf, network_context_ptr{}}; })
297 osc_generic_server_protocol(network_context_ptr ctx, const Configuration& conf)
298 : can_learn<ossia::net::protocol_base>{flags{SupportsMultiplex}}
299 , m_ctx{std::move(ctx)}
300 , m_id{*this}
301 , m_server{conf, m_ctx}
302 {
303 init();
304 }
305
306 void init()
307 {
308 m_server.listen([this](const unsigned char* data, std::size_t sz) {
309 auto on_message = [this](auto&& msg) { this->on_received_message(msg); };
310 osc_packet_processor<decltype(on_message)>{on_message}((const char*)data, sz);
311 });
312 }
313
314 osc_generic_server_protocol(const osc_generic_server_protocol&) = delete;
315 osc_generic_server_protocol(osc_generic_server_protocol&&) = delete;
316 osc_generic_server_protocol& operator=(const osc_generic_server_protocol&) = delete;
317 osc_generic_server_protocol& operator=(osc_generic_server_protocol&&) = delete;
318
319 ~osc_generic_server_protocol() override = default;
320
321 bool update(ossia::net::node_base& node_base) override { return false; }
322
323 bool pull(ossia::net::parameter_base& parameter_base) override { return false; }
324
325 bool observe(ossia::net::parameter_base& parameter_base, bool enable) override
326 {
327 return OscMode::observe(*this, parameter_base, enable);
328 }
329
330 bool echo_incoming_message(
331 const message_origin_identifier& id, const parameter_base& addr,
332 const value& val) override
333 {
334 return OscMode::echo_incoming_message(*this, id, addr, val);
335 }
336
337 bool push(const ossia::net::parameter_base& addr, const ossia::value& v) override
338 {
339 if constexpr(bundled)
340 return OscMode::push_bundle(*this, writer(), addr, v);
341 else
342 return OscMode::push(*this, addr, v);
343 }
344
345 bool push(const ossia::net::parameter_base& addr, ossia::value&& v) override
346 {
347 if constexpr(bundled)
348 return OscMode::push_bundle(*this, writer(), addr, std::move(v));
349 else
350 return OscMode::push(*this, addr, std::move(v));
351 }
352
353 bool push_raw(const ossia::net::full_parameter_data& addr) override
354 {
355 if constexpr(bundled)
356 return OscMode::push_bundle(*this, writer(), addr);
357 else
358 return OscMode::push_raw(*this, addr);
359 }
360
361 bool push_bundle(const std::vector<const parameter_base*>& addresses) override
362 {
363 return OscMode::push_bundle(*this, writer(), addresses);
364 }
365
366 bool push_bundle(tcb::span<ossia::bundle_element> addresses) override
367 {
368 return OscMode::push_bundle(*this, writer(), addresses);
369 }
370
371 bool push_bundle_bounded(tcb::span<ossia::bundle_element> addresses) override
372 {
373 return OscMode::push_bundle_bounded(*this, writer(), addresses);
374 }
375
376 bool
377 push_raw_bundle(const std::vector<ossia::net::full_parameter_data>& addresses) override
378 {
379 return OscMode::push_bundle(*this, writer(), addresses);
380 }
381
382 void on_received_message(const oscpack::ReceivedMessage& m)
383 {
384 return OscMode::on_received_message(*this, m);
385 }
386
387 void set_device(ossia::net::device_base& dev) override { m_device = &dev; }
388
389 auto writer() noexcept { return writer_type{m_server}; }
390
391 using ossia::net::protocol_base::m_logger;
392 ossia::net::network_context_ptr m_ctx;
393 message_origin_identifier m_id;
394 listened_parameters m_listening;
395
396 ossia::net::device_base* m_device{};
397
398 Socket m_server;
399};
400
401template <typename OscMode, typename Socket>
402class osc_generic_client_protocol : public can_learn<ossia::net::protocol_base>
403{
404public:
405 using osc_configuration = typename OscMode::osc_configuration;
406 static constexpr bool bundled = requires { typename osc_configuration::bundled; };
407 using socket_type = Socket;
408 using writer_type = socket_writer<socket_type>;
409
410 template <typename Configuration>
411 osc_generic_client_protocol(network_context_ptr ctx, const Configuration& conf)
412 : can_learn<ossia::net::protocol_base>{flags{SupportsMultiplex}}
413 , m_ctx{std::move(ctx)}
414 , m_id{*this}
415 , m_client{conf, m_ctx->context}
416 {
417 init();
418 }
419
420 void init()
421 {
422 m_client.on_open.connect(this->on_connection_open);
423 m_client.on_close.connect(this->on_connection_closed);
424 m_client.on_fail.connect(this->on_connection_failure);
425
426 m_client.connect();
427 m_client.receive([this](const unsigned char* data, std::size_t sz) {
428 auto on_message = [this](auto&& msg) { this->on_received_message(msg); };
429 osc_packet_processor<decltype(on_message)>{on_message}((const char*)data, sz);
430 });
431 }
432
433 osc_generic_client_protocol(const osc_generic_client_protocol&) = delete;
434 osc_generic_client_protocol(osc_generic_client_protocol&&) = delete;
435 osc_generic_client_protocol& operator=(const osc_generic_client_protocol&) = delete;
436 osc_generic_client_protocol& operator=(osc_generic_client_protocol&&) = delete;
437
438 ~osc_generic_client_protocol() override = default;
439
440 bool update(ossia::net::node_base& node_base) override { return false; }
441
442 bool pull(ossia::net::parameter_base& parameter_base) override { return false; }
443
444 bool observe(ossia::net::parameter_base& parameter_base, bool enable) override
445 {
446 return OscMode::observe(*this, parameter_base, enable);
447 }
448
449 bool echo_incoming_message(
450 const message_origin_identifier& id, const parameter_base& addr,
451 const value& val) override
452 {
453 return OscMode::echo_incoming_message(*this, id, addr, val);
454 }
455
456 bool push(const ossia::net::parameter_base& addr, const ossia::value& v) override
457 {
458 if constexpr(bundled)
459 return OscMode::push_bundle(*this, writer(), addr, v);
460 else
461 return OscMode::push(*this, addr, v);
462 }
463
464 bool push(const ossia::net::parameter_base& addr, ossia::value&& v) override
465 {
466 if constexpr(bundled)
467 return OscMode::push_bundle(*this, writer(), addr, std::move(v));
468 else
469 return OscMode::push(*this, addr, std::move(v));
470 }
471
472 bool push_raw(const ossia::net::full_parameter_data& addr) override
473 {
474 if constexpr(bundled)
475 return OscMode::push_bundle(*this, writer(), addr);
476 else
477 return OscMode::push_raw(*this, addr);
478 }
479
480 bool push_bundle(const std::vector<const parameter_base*>& addresses) override
481 {
482 return OscMode::push_bundle(*this, writer(), addresses);
483 }
484
485 bool push_bundle(tcb::span<ossia::bundle_element> addresses) override
486 {
487 return OscMode::push_bundle(*this, writer(), addresses);
488 }
489
490 bool push_bundle_bounded(tcb::span<ossia::bundle_element> addresses) override
491 {
492 return OscMode::push_bundle_bounded(*this, writer(), addresses);
493 }
494
495 bool
496 push_raw_bundle(const std::vector<ossia::net::full_parameter_data>& addresses) override
497 {
498 return OscMode::push_bundle(*this, writer(), addresses);
499 }
500
501 void on_received_message(const oscpack::ReceivedMessage& m)
502 {
503 return OscMode::on_received_message(*this, m);
504 }
505
506 void set_device(ossia::net::device_base& dev) override { m_device = &dev; }
507
508 auto writer() noexcept { return writer_type{m_client}; }
509
510 bool connected() const noexcept override { return m_client.connected(); }
511
512 void connect() override { return m_client.connect(); }
513
514 using ossia::net::protocol_base::m_logger;
515 ossia::net::network_context_ptr m_ctx;
516 message_origin_identifier m_id;
517 listened_parameters m_listening;
518
519 ossia::net::device_base* m_device{};
520
521 Socket m_client;
522};
523}
Root of a device tree.
Definition ossia/network/base/device.hpp:58
The node_base class.
Definition node.hpp:48
The parameter_base class.
Definition ossia/network/base/parameter.hpp:48
The value class.
Definition value.hpp:173
Definition git_info.h:7
If using the library, you should create this class at some point.
Definition context.hpp:27
context()
Most common case.
Definition context.cpp:87
Full information about a parameter.
Definition parameter_data.hpp:61