OSSIA
Open Scenario System for Interactive Application
oscquery_mirror_asio.hpp
1 #pragma once
2 
3 #include <ossia/detail/json_fwd.hpp>
4 #include <ossia/detail/lockfree_queue.hpp>
5 #include <ossia/network/base/listening.hpp>
6 #include <ossia/network/base/protocol.hpp>
7 #include <ossia/network/oscquery/host_info.hpp>
8 
9 #include <atomic>
10 
11 namespace osc
12 {
13 template <typename T>
14 class sender;
15 class receiver;
16 }
17 
18 namespace oscpack
19 {
20 class ReceivedMessage;
21 class IpEndpointName;
22 }
23 
24 namespace ossia
25 {
26 namespace net
27 {
28 class websocket_client;
29 struct parameter_data;
30 struct network_context;
31 using network_context_ptr = std::shared_ptr<network_context>;
32 }
33 namespace oscquery_asio
34 {
35 struct osc_outbound_visitor;
36 struct http_async_client_context;
37 struct http_responder;
38 
39 class oscquery_mirror_asio_protocol;
40 struct oscquery_shared_async_state
41 {
42  oscquery_mirror_asio_protocol& self;
43  bool active = true;
44 };
45 
46 class OSSIA_EXPORT oscquery_mirror_asio_protocol final : public ossia::net::protocol_base
47 {
48  struct osc_sender_impl;
49  struct osc_receiver_impl;
50 
51 public:
52  oscquery_mirror_asio_protocol(
53  ossia::net::network_context_ptr ctx, std::string host,
54  uint16_t local_osc_port = 0);
55  ~oscquery_mirror_asio_protocol() override;
56 
57  bool pull(net::parameter_base&) override;
58  std::future<void> pull_async(net::parameter_base&) override;
59  void request(net::parameter_base&) override;
60  bool push(const net::parameter_base&, const ossia::value& v) override;
61  bool push_raw(const ossia::net::full_parameter_data& parameter_base) override;
62  bool push_bundle(const std::vector<const ossia::net::parameter_base*>&) override;
63  bool push_raw_bundle(const std::vector<ossia::net::full_parameter_data>&) override;
64  bool observe(net::parameter_base&, bool) override;
65  bool observe_quietly(net::parameter_base&, bool) override;
66  bool update(net::node_base& b) override;
67  bool echo_incoming_message(
68  const ossia::net::message_origin_identifier& id,
69  const ossia::net::parameter_base& addr, const value& val) override;
70 
71  std::future<void> update_async(net::node_base& b) override;
72 
73  void stop() override;
74  void set_device(net::device_base& dev) override;
75  ossia::net::device_base& get_device() const { return *m_device; }
76 
77  bool ws_connected() const noexcept { return m_hasWS; }
78  bool osc_connected() const noexcept { return bool(m_oscSender); }
79  osc_sender_impl& osc_sender() const noexcept { return *m_oscSender; }
80  ossia::net::websocket_client& ws_client() const noexcept { return *m_websocketClient; }
81 
87  void request_add_node(net::node_base&, const ossia::net::parameter_data&);
88 
93  void request_remove_node(net::node_base&);
94 
99  void request_rename_node(net::node_base& node, const std::string& new_name);
100 
106  void set_zombie_on_remove(bool zombie_on_remove)
107  {
108  m_zombie_on_remove = zombie_on_remove;
109  }
110 
115  bool get_zombie_on_remove() const noexcept { return m_zombie_on_remove; }
116 
117  ossia::oscquery::host_info get_host_info() const noexcept;
118 
119  bool connected() const noexcept override { return m_hasWS; }
120  void connect() override;
121 
122 private:
123  friend struct http_async_answer;
124  friend struct http_async_value_answer;
125  using connection_handler = std::weak_ptr<void>;
126  void on_ws_disconnected() { m_hasWS = false; }
127 
128  void init();
129 
130  void start_http();
131  void start_websockets();
132  void start_osc();
133 
134  void cleanup_connections();
135 
136  // Input
137  bool on_text_ws_message(connection_handler hdl, const std::string& message);
138  bool on_binary_ws_message(connection_handler hdl, const std::string& message);
139  bool on_value_http_message(const std::string& address, const std::string& message);
140  void on_osc_message(const oscpack::ReceivedMessage& m);
141  void process_raw_osc_data(const char* data, std::size_t sz);
142 
143  // Output
144  void http_send_message(const std::string& str);
145  void http_send_message(const rapidjson::StringBuffer& str);
146 
147  void ws_send_message(const std::string& str);
148  void ws_send_message(const rapidjson::StringBuffer& str);
149 
150  // ZeroConf
151  bool query_connected();
152  void query_stop();
153 
154  void on_nodeRenamed(const ossia::net::node_base& n, std::string oldname);
155 
156  ossia::net::network_context_ptr m_ctx;
157 
158  std::unique_ptr<osc_sender_impl> m_oscSender;
159  std::unique_ptr<osc_receiver_impl> m_oscServer;
160 
161  std::unique_ptr<ossia::net::websocket_client> m_websocketClient;
162  std::shared_ptr<oscquery_shared_async_state> m_async_state;
163  std::atomic_bool m_hasWS{};
164 
165  // Listening status of the local software
166  net::listened_parameters m_listening;
167 
168  ossia::net::device_base* m_device{};
169 
170  std::promise<void> m_namespacePromise;
171 
172  std::string m_queryHost;
173  std::string m_queryPort;
174  std::string m_httpHost;
175  int m_osc_port{};
176 
177  std::unique_ptr<http_async_client_context> m_http;
178  ossia::oscquery::host_info m_host_info;
179 
180  ossia::net::message_origin_identifier m_id;
181 
182  bool m_zombie_on_remove{true};
183  enum
184  {
185  any_protocol,
186  http,
187  websockets
188  } m_protocol_to_use{any_protocol};
189 };
190 }
191 }
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
Low-level Websocket client.
Definition: websocket_client.hpp:18
The value class.
Definition: value.hpp:173
Definition: git_info.h:7
Full information about a parameter.
Definition: parameter_data.hpp:61
The data that can be found inside a parameter.
Definition: parameter_data.hpp:21
Represents the capabilities of an OSCQuery server.
Definition: host_info.hpp:12