126 lines
3.5 KiB
C++
126 lines
3.5 KiB
C++
#include <nano/node/websocket_stream.hpp>
|
|
|
|
#include <boost/asio/bind_executor.hpp>
|
|
|
|
namespace
|
|
{
|
|
/** Type-erasing wrapper for tls and non-tls websocket streams */
|
|
template <typename stream_type>
|
|
class stream_wrapper : public nano::websocket::websocket_stream_concept
|
|
{
|
|
public:
|
|
#ifdef NANO_SECURE_RPC
|
|
stream_wrapper (socket_type socket_a, boost::asio::ssl::context & ctx_a) :
|
|
ws (std::move (socket_a), ctx_a), strand (ws.get_executor ())
|
|
{
|
|
is_tls = true;
|
|
ws.text (true);
|
|
}
|
|
#endif
|
|
|
|
stream_wrapper (socket_type socket_a) :
|
|
ws (std::move (socket_a)), strand (ws.get_executor ())
|
|
{
|
|
ws.text (true);
|
|
}
|
|
|
|
void handshake (std::function<void (boost::system::error_code const & ec)> callback_a) override
|
|
{
|
|
if (is_tls)
|
|
{
|
|
ssl_handshake (callback_a);
|
|
}
|
|
else
|
|
{
|
|
// Websocket handshake
|
|
ws.async_accept ([callback_a] (boost::system::error_code const & ec) {
|
|
callback_a (ec);
|
|
});
|
|
}
|
|
}
|
|
|
|
void ssl_handshake (std::function<void (boost::system::error_code const & ec)> callback_a)
|
|
{
|
|
#ifdef NANO_SECURE_RPC
|
|
// Only perform TLS handshakes for TLS streams
|
|
if constexpr (std::is_same<wss_type, stream_type>::value)
|
|
{
|
|
ws.next_layer ().async_handshake (boost::asio::ssl::stream_base::server, [this, callback_a] (boost::system::error_code const & ec) {
|
|
if (!ec)
|
|
{
|
|
// Websocket handshake
|
|
this->ws.async_accept ([callback_a] (boost::system::error_code const & ec) {
|
|
callback_a (ec);
|
|
});
|
|
}
|
|
else
|
|
{
|
|
callback_a (ec);
|
|
}
|
|
});
|
|
}
|
|
#endif
|
|
}
|
|
|
|
boost::asio::strand<boost::asio::io_context::executor_type> & get_strand () override
|
|
{
|
|
return strand;
|
|
}
|
|
|
|
void close (boost::beast::websocket::close_reason const & reason_a, boost::system::error_code & ec_a) override
|
|
{
|
|
ws.close (reason_a, ec_a);
|
|
}
|
|
|
|
void async_write (nano::shared_const_buffer const & buffer_a, std::function<void (boost::system::error_code, std::size_t)> callback_a) override
|
|
{
|
|
ws.async_write (buffer_a, boost::asio::bind_executor (strand, callback_a));
|
|
}
|
|
|
|
void async_read (boost::beast::multi_buffer & buffer_a, std::function<void (boost::system::error_code, std::size_t)> callback_a) override
|
|
{
|
|
ws.async_read (buffer_a, boost::asio::bind_executor (strand, callback_a));
|
|
}
|
|
|
|
private:
|
|
bool is_tls{ false };
|
|
stream_type ws;
|
|
boost::asio::strand<boost::asio::io_context::executor_type> strand;
|
|
};
|
|
}
|
|
|
|
#ifdef NANO_SECURE_RPC
|
|
nano::websocket::stream::stream (socket_type socket_a, boost::asio::ssl::context & ctx_a)
|
|
{
|
|
impl = std::make_unique<stream_wrapper<wss_type>> (std::move (socket_a), ctx_a);
|
|
}
|
|
#endif
|
|
nano::websocket::stream::stream (socket_type socket_a)
|
|
{
|
|
impl = std::make_unique<stream_wrapper<ws_type>> (std::move (socket_a));
|
|
}
|
|
|
|
[[nodiscard]] boost::asio::strand<boost::asio::io_context::executor_type> & nano::websocket::stream::get_strand ()
|
|
{
|
|
return impl->get_strand ();
|
|
}
|
|
|
|
void nano::websocket::stream::handshake (std::function<void (boost::system::error_code const & ec)> callback_a)
|
|
{
|
|
impl->handshake (callback_a);
|
|
}
|
|
|
|
void nano::websocket::stream::close (boost::beast::websocket::close_reason const & reason_a, boost::system::error_code & ec_a)
|
|
{
|
|
impl->close (reason_a, ec_a);
|
|
}
|
|
|
|
void nano::websocket::stream::async_write (nano::shared_const_buffer const & buffer_a, std::function<void (boost::system::error_code, std::size_t)> callback_a)
|
|
{
|
|
impl->async_write (buffer_a, callback_a);
|
|
}
|
|
|
|
void nano::websocket::stream::async_read (boost::beast::multi_buffer & buffer_a, std::function<void (boost::system::error_code, std::size_t)> callback_a)
|
|
{
|
|
impl->async_read (buffer_a, callback_a);
|
|
}
|