2#include <ossia/network/context.hpp>
3#include <ossia/network/sockets/tcp_socket.hpp>
5#include <ossia-qt/protocols/utils.hpp>
11#include <nano_observer.hpp>
17class qml_tcp_connection
19 ,
public Nano::Observer
21 W_OBJECT(qml_tcp_connection)
25 boost::asio::io_context& context;
26 ossia::net::tcp_listener listener;
28 std::atomic_bool alive{
true};
30 state(ossia::net::tcp_listener l, boost::asio::io_context& ctx)
32 , listener{std::move(l)}
37 explicit qml_tcp_connection(
38 ossia::net::tcp_listener listener, boost::asio::io_context& ctx)
39 : m_state{std::make_shared<state>(std::move(listener), ctx)}
43 ~qml_tcp_connection() { m_state->alive =
false; }
44 inline boost::asio::io_context& context() noexcept {
return m_state->context; }
46 void write(QByteArray buffer)
49 boost::asio::dispatch(st->context, [st, buffer] {
51 st->listener.write(boost::asio::const_buffer(buffer.data(), buffer.size()));
56 void close(QByteArray)
59 boost::asio::dispatch(st->context, [st] {
66 void receive(QJSValue v)
69 receive_impl(m_state, QPointer{
this});
75 W_PROPERTY(QJSValue, onClose W_MEMBER onClose);
78 static void receive_impl(
79 std::shared_ptr<state> st, QPointer<qml_tcp_connection> self)
81 st->listener.m_socket.async_read_some(
82 boost::asio::buffer(st->data,
sizeof(st->data)),
83 [self, st](boost::system::error_code ec, std::size_t bytes_transferred) {
88 auto buf = QByteArray(st->data, bytes_transferred);
94 if(self->onBytes.isCallable())
96 auto engine = qjsEngine(self.get());
98 self->onBytes.call({engine->toScriptValue(buf)});
102 receive_impl(st, self);
106 ossia::qt::run_async(
109 if(self && self->onClose.isCallable())
110 self->onClose.call();
117 std::shared_ptr<state> m_state;
120class qml_tcp_inbound_socket
122 ,
public Nano::Observer
124 W_OBJECT(qml_tcp_inbound_socket)
128 ossia::net::tcp_server server;
129 std::atomic_bool alive{
true};
130 std::atomic_bool open{
false};
133 const ossia::net::inbound_socket_configuration& conf,
134 boost::asio::io_context& ctx)
140 qml_tcp_inbound_socket(
141 const ossia::net::inbound_socket_configuration& conf, boost::asio::io_context& ctx)
142 : m_state{std::make_shared<state>(conf, ctx)}
146 ~qml_tcp_inbound_socket() { m_state->alive =
false; }
148 inline boost::asio::io_context& context() noexcept {
return m_state->server.m_context; }
152 m_state->open =
true;
153 accept_impl(m_state, QPointer{
this});
154 if(onOpen.isCallable())
155 onOpen.call({qjsEngine(
this)->newQObject(
this)});
160 m_state->open =
false;
161 m_state->server.m_acceptor.close();
162 if(onClose.isCallable())
169 m_state->open =
false;
170 ossia::qt::run_async(
this, [=,
this] { onClose.call(); }, Qt::AutoConnection);
176 QJSValue onConnection;
179 static void accept_impl(
180 std::shared_ptr<state> st, QPointer<qml_tcp_inbound_socket> self)
182 st->server.m_acceptor.async_accept(
184 boost::system::error_code ec, ossia::net::tcp_server::proto::socket socket) {
185 if(!st->alive || !st->open)
189 ossia::qt::run_async(
191 [self, st, socket = std::move(socket)]()
mutable {
194 auto conn = new qml_tcp_connection{
195 ossia::net::tcp_listener{std::move(socket)}, st->server.m_context};
197 if(self->onConnection.isCallable())
199 self->onConnection.call({qjsEngine(self.get())->newQObject(conn)});
203 accept_impl(st, self);
208 std::shared_ptr<state> m_state;
Definition qml_device.cpp:43