OSSIA
Open Scenario System for Interactive Application
oscquery_server_asio.hpp
1 #pragma once
2 #include <ossia/detail/lockfree_queue.hpp>
3 #include <ossia/detail/mutex.hpp>
4 #include <ossia/network/base/listening.hpp>
5 #include <ossia/network/base/protocol.hpp>
6 #include <ossia/network/context_functions.hpp>
7 #include <ossia/network/generic/generic_device.hpp>
8 #include <ossia/network/sockets/websocket_reply.hpp>
9 #include <ossia/network/zeroconf/zeroconf.hpp>
10 
11 #include <ossia/detail/hash_map.hpp>
12 
13 #include <nano_signal_slot.hpp>
14 
15 #include <atomic>
16 namespace osc
17 {
18 template <typename T>
19 class sender;
20 class receiver;
21 }
22 namespace oscpack
23 {
24 class ReceivedMessage;
25 class IpEndpointName;
26 }
27 namespace ossia
28 {
29 namespace net
30 {
31 class websocket_server;
32 }
33 namespace oscquery
34 {
35 class query_answerer;
36 class get_query_answerer;
37 struct json_query_answerer;
38 }
39 namespace oscquery_asio
40 {
41 struct oscquery_client;
42 using clients = std::vector<std::unique_ptr<oscquery_client>>;
44 class OSSIA_EXPORT oscquery_server_protocol final : public ossia::net::protocol_base
45 {
46  friend struct oscquery_client;
47  friend class ossia::oscquery::query_answerer;
50 
51 public:
52  using connection_handler = std::weak_ptr<void>;
54  ossia::net::network_context_ptr ctx, uint16_t osc_port = 1234,
55  uint16_t ws_port = 5678);
56  ~oscquery_server_protocol() override;
57 
58  bool pull(net::parameter_base&) override;
59  std::future<void> pull_async(net::parameter_base&) override;
60  void request(net::parameter_base&) override;
61  bool push(const net::parameter_base&, const ossia::value& v) override;
62  bool push_raw(const ossia::net::full_parameter_data& parameter_base) override;
63  bool push_bundle(const std::vector<const ossia::net::parameter_base*>&) override;
64  bool push_raw_bundle(const std::vector<ossia::net::full_parameter_data>&) override;
65  bool echo_incoming_message(
66  const ossia::net::message_origin_identifier&, const ossia::net::parameter_base&,
67  const ossia::value& v) override;
68  bool observe(net::parameter_base&, bool) override;
69  bool observe_quietly(net::parameter_base&, bool) override;
70  bool update(net::node_base& b) override;
71 
72  void set_device(net::device_base& dev) override;
73  void stop() override;
74  ossia::net::device_base& get_device() const { return *m_device; }
75 
76  int get_osc_port() const { return m_oscPort; }
77 
78  int get_ws_port() const { return m_wsPort; }
79 
80  Nano::Signal<void(const std::string&)> onClientConnected;
81  Nano::Signal<void(const std::string&)> onClientDisconnected;
82 
83 private:
84  // List of connected clients
85  oscquery_client* find_client(const connection_handler& hdl);
86 
87  void add_node(std::string_view path, const string_map<std::string>& parameters);
88  void remove_node(std::string_view path, const std::string& node);
89  void rename_node(std::string_view node, const std::string& new_name);
90 
91  // OSC callback
92  void on_osc_message(const oscpack::ReceivedMessage& m);
93  void process_raw_osc_data(const char* data, std::size_t sz);
94 
95  // Websocket callbacks
96  void on_connectionOpen(const connection_handler& hdl);
97  void on_connectionClosed(const connection_handler& hdl);
98 
99  // Local device callback
100  void on_nodeCreated(const ossia::net::node_base&);
101  void on_nodeRemoved(const ossia::net::node_base&);
102  void on_parameterChanged(const ossia::net::parameter_base&);
103  void on_attributeChanged(const ossia::net::node_base&, std::string_view attr);
104  void on_nodeRenamed(const ossia::net::node_base& n, std::string oldname);
105 
106  template <typename T>
107  bool push_impl(const T& addr, const ossia::value& v);
108 
109  bool write_impl(std::string_view data, bool critical);
110 
111  void update_zeroconf();
112  // Exceptions here will be catched by the server
113  // which will set appropriate error codes.
114  ossia::net::server_reply
115  on_text_ws_message(const connection_handler& hdl, const std::string& message);
116  ossia::net::server_reply
117  on_binary_ws_message(const connection_handler& hdl, const std::string& message);
118 
119  ossia::net::network_context_ptr m_context;
120 
121  struct osc_receiver_impl;
122  std::unique_ptr<osc_receiver_impl> m_oscServer;
123  std::unique_ptr<ossia::net::websocket_server> m_websocketServer;
124 
125  net::zeroconf_server m_zeroconfServerWS;
126  net::zeroconf_server m_zeroconfServerOSC;
127 
128  // Listening status of the local software
129  net::listened_parameters m_listening;
130 
131  // The clients connected to this server
132  clients m_clients;
133  std::atomic_int m_clientCount{};
134 
135  ossia::net::device_base* m_device{};
136 
137  // To lock m_clients
138  mutex_t m_clientsMutex;
139 
140  // The local ports
141  uint16_t m_oscPort{};
142  uint16_t m_wsPort{};
143 };
144 }
145 }
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 protocol_base class.
Definition: protocol.hpp:40
OSCQuery get query-answering logic.
Definition: get_query_parser.hpp:26
Implementation of an oscquery server.
Definition: oscquery_server_asio.hpp:45
The value class.
Definition: value.hpp:173
Definition: git_info.h:7
The message struct.
Definition: message.hpp:29
Full information about a parameter.
Definition: parameter_data.hpp:61
OSCQuery JSON query-answering logic.
Definition: json_query_parser.hpp:16