3#include <ossia/network/context.hpp>
4#include <ossia/network/sockets/configuration.hpp>
5#include <ossia/network/sockets/writers.hpp>
7#include <boost/asio/io_context.hpp>
8#include <boost/asio/ip/udp.hpp>
9#include <boost/asio/local/datagram_protocol.hpp>
10#include <boost/asio/local/stream_protocol.hpp>
11#include <boost/asio/placeholders.hpp>
12#include <boost/asio/strand.hpp>
13#include <boost/asio/write.hpp>
15#include <nano_signal_slot.hpp>
19#if defined(BOOST_ASIO_HAS_LOCAL_SOCKETS)
20class unix_datagram_socket
22 using proto = boost::asio::local::datagram_protocol;
25 unix_datagram_socket(
const fd_configuration& conf, boost::asio::io_context& ctx)
28 , m_socket{boost::asio::make_strand(ctx)}
34 ::unlink(m_endpoint.path().data());
36 m_socket.bind(m_endpoint);
47 if(m_socket.is_open())
49 boost::asio::post(m_context, [
this] {
52 m_socket.shutdown(boost::asio::ip::udp::socket::shutdown_both);
66 m_socket.async_receive_from(
67 boost::asio::mutable_buffer(&m_data[0], std::size(m_data)), m_endpoint,
68 [
this, f](boost::system::error_code ec, std::size_t sz) {
69 if(ec == boost::asio::error::operation_aborted)
85 void write(
const char* data, std::size_t sz)
87 m_socket.send_to(boost::asio::buffer(data, sz), m_endpoint);
90 ~unix_datagram_socket()
99 if(m_socket.is_open())
101 boost::system::error_code ec;
105 while(m_context.poll() > 0) { }
108 Nano::Signal<void()> on_close;
110 boost::asio::io_context& m_context;
111 proto::endpoint m_endpoint;
112 proto::socket m_socket;
113 alignas(16)
char m_data[65535];
116class unix_stream_listener
119 using proto = boost::asio::local::stream_protocol;
120 unix_stream_listener() =
delete;
121 unix_stream_listener(
const unix_stream_listener&) =
delete;
122 unix_stream_listener& operator=(
const unix_stream_listener&) =
delete;
123 unix_stream_listener(unix_stream_listener&&) =
default;
124 unix_stream_listener& operator=(unix_stream_listener&&) =
default;
125 explicit unix_stream_listener(proto::socket sock)
126 : m_socket{std::move(sock)}
135 m_socket.shutdown(boost::asio::ip::udp::socket::shutdown_both);
143 void write(
const boost::asio::const_buffer& buf) { boost::asio::write(m_socket, buf); }
149 proto::socket m_socket;
152class unix_stream_server
155 using proto = boost::asio::local::stream_protocol;
156 using listener = unix_stream_listener;
157 [[no_unique_address]]
struct ensure_reuse
159 explicit ensure_reuse(
const proto::endpoint& endpoint)
161 ::unlink(endpoint.path().data());
165 unix_stream_server(
const fd_configuration& conf, boost::asio::io_context& ctx)
166 : m_ensure_reuse{conf.fd}
168 , m_acceptor{boost::asio::make_strand(ctx), conf.fd}
172 unix_stream_server(
const fd_configuration& conf, ossia::net::network_context_ptr ctx)
173 : unix_stream_server{conf, ctx->context}
177 boost::asio::io_context& m_context;
178 proto::acceptor m_acceptor;
181class unix_stream_client
184 using proto = boost::asio::local::stream_protocol;
185 using socket =
typename proto::socket;
187 unix_stream_client(
const fd_configuration& conf, boost::asio::io_context& ctx)
189 , m_endpoint{conf.fd}
190 , m_socket{boost::asio::make_strand(ctx)}
196 m_socket.connect(m_endpoint);
200 bool connected()
const {
return m_connected; }
204 boost::asio::post(m_context, [
this, alive = m_lifetime.watch()] {
210 m_socket.shutdown(boost::asio::ip::udp::socket::shutdown_both);
220 void write(
const char* data, std::size_t sz)
222 boost::asio::write(m_socket, boost::asio::buffer(data, sz));
225 Nano::Signal<void()> on_open;
226 Nano::Signal<void()> on_close;
227 Nano::Signal<void()> on_fail;
229 boost::asio::io_context& m_context;
230 proto::endpoint m_endpoint;
231 proto::socket m_socket;
232 bool m_connected{
false};
236 lifetime_token m_lifetime;