OSSIA
Open Scenario System for Interactive Application
oscquery_server.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/generic/generic_device.hpp>
7 #include <ossia/network/sockets/websocket_reply.hpp>
8 #include <ossia/network/zeroconf/zeroconf.hpp>
9 
10 #include <ossia/detail/hash_map.hpp>
11 
12 #include <nano_signal_slot.hpp>
13 
14 #include <atomic>
15 namespace osc
16 {
17 template <typename T>
18 class sender;
19 class receiver;
20 }
21 namespace oscpack
22 {
23 class ReceivedMessage;
24 class IpEndpointName;
25 }
26 namespace ossia
27 {
28 namespace net
29 {
30 class websocket_server;
31 }
32 namespace oscquery
33 {
34 struct oscquery_client;
35 using clients = std::vector<std::unique_ptr<oscquery_client>>;
37 class OSSIA_EXPORT oscquery_server_protocol final : public ossia::net::protocol_base
38 {
39  friend class query_answerer;
40  friend class get_query_answerer;
41  friend struct json_query_answerer;
42 
43 public:
44  using connection_handler = std::weak_ptr<void>;
45  oscquery_server_protocol(uint16_t osc_port = 1234, uint16_t ws_port = 5678);
46  ~oscquery_server_protocol() override;
47 
48  bool pull(net::parameter_base&) override;
49  std::future<void> pull_async(net::parameter_base&) override;
50  void request(net::parameter_base&) override;
51  bool push(const net::parameter_base&, const ossia::value& v) override;
52  bool push_raw(const ossia::net::full_parameter_data& parameter_base) override;
53  bool push_bundle(const std::vector<const ossia::net::parameter_base*>&) override;
54  bool push_raw_bundle(const std::vector<ossia::net::full_parameter_data>&) override;
55  bool echo_incoming_message(
56  const ossia::net::message_origin_identifier&, const ossia::net::parameter_base&,
57  const ossia::value& v) override;
58  bool observe(net::parameter_base&, bool) override;
59  bool observe_quietly(net::parameter_base&, bool) override;
60  bool update(net::node_base& b) override;
61  void run_commands();
62  void set_device(net::device_base& dev) override;
63  void stop() override;
64  ossia::net::device_base& get_device() const { return *m_device; }
65 
66  int get_osc_port() const { return m_oscPort; }
67 
68  int get_ws_port() const { return m_wsPort; }
69 
70  template <typename F>
71  void for_each_client(F&& f) const
72  noexcept(noexcept(f(std::declval<const oscquery_client&>())))
73  {
74  ossia::lock_t lck{m_clientsMutex};
75  for(auto& clt : m_clients)
76  {
77  f(*clt);
78  }
79  }
80 
81  Nano::Signal<void(const std::string&)> onClientConnected;
82  Nano::Signal<void(const std::string&)> onClientDisconnected;
83 
84  void disable_zeroconf();
85  void set_zeroconf_servers(
86  net::zeroconf_server oscquery_server, net::zeroconf_server osc_server);
87 
88 private:
89  // List of connected clients
90  oscquery_client* find_client(const connection_handler& hdl);
91 
92  void add_node(std::string_view path, const string_map<std::string>& parameters);
93  void remove_node(std::string_view path, const std::string& node);
94  void rename_node(std::string_view node, const std::string& new_name);
95 
96  // OSC callback
97  void on_OSCMessage(const oscpack::ReceivedMessage& m, oscpack::IpEndpointName ip);
98 
99  // Websocket callbacks
100  void on_connectionOpen(const connection_handler& hdl);
101  void on_connectionClosed(const connection_handler& hdl);
102 
103  // Local device callback
104  void on_nodeCreated(const ossia::net::node_base&);
105  void on_nodeRemoved(const ossia::net::node_base&);
106  void on_parameterChanged(const ossia::net::parameter_base&);
107  void on_attributeChanged(const ossia::net::node_base&, std::string_view attr);
108  void on_nodeRenamed(const ossia::net::node_base& n, std::string oldname);
109 
110  template <typename T>
111  bool push_impl(const T& addr, const ossia::value& v);
112 
113  void update_zeroconf();
114  // Exceptions here will be catched by the server
115  // which will set appropriate error codes.
116  ossia::net::server_reply
117  on_WSrequest(const connection_handler& hdl, const std::string& message);
118  ossia::net::server_reply
119  on_BinaryWSrequest(const connection_handler& hdl, const std::string& message);
120 
121  std::unique_ptr<osc::receiver> m_oscServer;
122  std::unique_ptr<ossia::net::websocket_server> m_websocketServer;
123 
124  net::zeroconf_server m_zeroconfServerWS;
125  net::zeroconf_server m_zeroconfServerOSC;
126 
127  // Listening status of the local software
128  net::listened_parameters m_listening;
129 
130  // The clients connected to this server
131  clients m_clients TS_GUARDED_BY(m_clientsMutex);
132 
133  ossia::net::device_base* m_device{};
134 
135  // Where the websocket server lives
136  std::thread m_serverThread;
137 
138  // To lock m_clients
139  mutable mutex_t m_clientsMutex;
140 
141  // The local ports
142  uint16_t m_oscPort{};
143  uint16_t m_wsPort{};
144 
145  bool m_echo{};
146  bool m_disableZeroconf{};
147 
148  // TODO could we make an intermediate base class for oscquery_{server,mirror}
149  // that hold that function queue and other shared members/methods ?
150 
151  // function queue to hold ws callback
152  // and avoid tree to be modified on another thread
153  ossia::spsc_queue<std::function<void()>> m_functionQueue;
154 };
155 }
156 
157 class OSSIA_EXPORT oscquery_device
158 {
159 public:
160  oscquery_device(
161  uint16_t osc_port = 1234, uint16_t ws_port = 5678, std::string name = "oscquery");
162 
163  ~oscquery_device();
164 
165  ossia::net::generic_device device;
167 };
168 }
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.hpp:38
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