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