2#include <ossia/network/context.hpp>
3#include <ossia/network/sockets/udp_socket.hpp>
4#include <ossia/network/sockets/websocket_client.hpp>
6#include <ossia-qt/protocols/utils.hpp>
12#include <nano_observer.hpp>
20class qml_websocket_outbound_socket
22 ,
public protocols_sender
24 W_OBJECT(qml_websocket_outbound_socket)
37 std::unique_ptr<ossia::net::websocket_client> client;
38 std::atomic_bool alive{
true};
46 qml_websocket_outbound_socket* self{};
60 void fire_message(websocketpp::frame::opcode::value opcode, std::string msg);
63 qml_websocket_outbound_socket() { }
65 ~qml_websocket_outbound_socket()
69 m_state->alive =
false;
78 bool isOpen() const noexcept {
return m_state && m_state->client; }
81 const ossia::net::outbound_socket_configuration& conf,
82 boost::asio::io_context& ctx)
84 m_state = std::make_shared<state>();
85 m_state->url =
"ws://" + conf.host +
":" + std::to_string(conf.port);
88 m_state->client = std::make_unique<ossia::net::websocket_client>(
89 ctx, [st](
auto hdl,
auto opcode,
const std::string& msg) {
92 st->fire_message(opcode, msg);
95 if(onOpen.isCallable())
97 if(onClose.isCallable())
98 m_state->client->on_close.connect<&state::fire_close>(m_state.get());
99 if(onError.isCallable())
100 m_state->client->on_fail.connect<&state::fire_fail>(m_state.get());
102 m_state->client->connect(m_state->url);
106 void deliver_message(
107 websocketpp::frame::opcode::value opcode,
const std::string& msg)
109 if(opcode == websocketpp::frame::opcode::text && onTextMessage.isCallable())
111 onTextMessage.call({QString::fromStdString(msg)});
113 else if(opcode == websocketpp::frame::opcode::binary && onBinaryMessage.isCallable())
115 if(
auto engine = qjsEngine(
this))
116 onBinaryMessage.call({engine->toScriptValue(QByteArray(msg.data(), msg.size()))});
122 if(!m_state || !m_state->alive)
124 ossia::qt::run_async(
125 this, [=,
this] { onOpen.call({qjsEngine(
this)->newQObject(
this)}); },
130 if(!m_state || !m_state->alive)
132 ossia::qt::run_async(
this, [=,
this] { onError.call(); }, Qt::AutoConnection);
136 if(!m_state || !m_state->alive)
138 if(m_state->closed.exchange(
true))
140 ossia::qt::run_async(
this, [=,
this] { onClose.call(); }, Qt::AutoConnection);
143 void write(QString message)
148 boost::asio::dispatch(
149 st->client->context(),
150 [st, msg = message.toStdString()] {
152 st->client->send_message(msg);
157 void writeBinary(QByteArray buffer)
162 boost::asio::dispatch(
163 st->client->context(),
164 [st, buf = std::string(buffer.data(), buffer.size())] {
166 st->client->send_binary_message(buf);
177 if(!m_state->closed.exchange(
true) && onClose.isCallable())
189 QJSValue onTextMessage;
190 QJSValue onBinaryMessage;
197 if(m_state && m_state->client)
198 m_state->client->stop();
201 std::shared_ptr<state> m_state;
204inline void qml_websocket_outbound_socket::state::fire_open()
206 std::lock_guard g{qt_mutex};
211inline void qml_websocket_outbound_socket::state::fire_fail()
213 std::lock_guard g{qt_mutex};
218inline void qml_websocket_outbound_socket::state::fire_close()
220 std::lock_guard g{qt_mutex};
225inline void qml_websocket_outbound_socket::state::fire_message(
226 websocketpp::frame::opcode::value opcode, std::string msg)
230 std::lock_guard g{qt_mutex};
233 ossia::qt::run_async(
235 [target = self, opcode, msg = std::move(msg)] {
236 target->deliver_message(opcode, msg);
Definition qml_device.cpp:43
Definition qml_ws_outbound_socket.hpp:35
std::mutex qt_mutex
Definition qml_ws_outbound_socket.hpp:45
void fire_open()
Nano slots, always on the websocketpp thread.
Definition qml_ws_outbound_socket.hpp:204
std::atomic_bool closed
Definition qml_ws_outbound_socket.hpp:41
void fire_message(websocketpp::frame::opcode::value opcode, std::string msg)
Message delivery, always on the websocketpp thread.
Definition qml_ws_outbound_socket.hpp:225