Joedb 10.2.1
The Journal-Only Embedded Database
Loading...
Searching...
No Matches
Websocket_Channel.cpp
Go to the documentation of this file.
1#ifdef JOEDB_HAS_WEBSOCKETS
3
4#include <boost/asio/ip/tcp.hpp>
5#include <boost/asio/connect.hpp>
6#include <boost/asio/ssl.hpp>
7#include <boost/beast/websocket.hpp>
8#include <boost/beast/websocket/ssl.hpp>
9#include <boost/certify/https_verification.hpp>
10#include <boost/certify/extensions.hpp>
11
12namespace joedb
13{
14 namespace detail
15 {
16 class Websocket_Channel
17 {
18 private:
19 boost::asio::io_context io_context;
20 boost::asio::ssl::context ssl_context;
21
22 boost::beast::websocket::stream
23 <
24 boost::asio::ssl::stream
25 <
26 boost::asio::ip::tcp::socket
27 >
28 >
29 ws;
30
31 public:
32 Websocket_Channel
33 (
34 const std::string &host,
35 const std::string &port,
36 const std::string &path
37 ):
38 ssl_context(boost::asio::ssl::context::tlsv12_client),
39 ws(io_context, ssl_context)
40 {
41 ssl_context.set_verify_mode
42 (
43 boost::asio::ssl::context::verify_peer |
44 boost::asio::ssl::context::verify_fail_if_no_peer_cert
45 );
46
47 ssl_context.set_default_verify_paths();
48
49 boost::certify::enable_native_https_server_verification(ssl_context);
50 boost::certify::set_server_hostname(ws.next_layer(), host);
51 boost::certify::sni_hostname(ws.next_layer(), host);
52
53 const auto endpoint = boost::asio::connect
54 (
55 boost::beast::get_lowest_layer(ws),
56 boost::asio::ip::tcp::resolver(io_context).resolve(host, port)
57 );
58
59 ws.next_layer().handshake(boost::asio::ssl::stream_base::client);
60
61 ws.binary(true);
62
63 boost::beast::get_lowest_layer(ws).set_option
64 (
65 boost::asio::ip::tcp::no_delay(true)
66 );
67
68 boost::beast::get_lowest_layer(ws).set_option
69 (
70 boost::asio::socket_base::keep_alive(true)
71 );
72
73 ws.handshake
74 (
75 host + ":" + std::to_string(endpoint.port()),
76 path
77 );
78 }
79
80 size_t write_some(const char *data, size_t size)
81 {
82 return ws.write(boost::asio::buffer(data, size));
83 }
84
85 size_t read_some(char *data, size_t size)
86 {
87 return ws.read_some(boost::asio::buffer(data, size));
88 }
89
90 ~Websocket_Channel()
91 {
92 try
93 {
94 boost::system::error_code ec;
95 ws.close(boost::beast::websocket::close_code::normal, ec);
96 }
97 catch (...)
98 {
99 }
100 }
101 };
102 }
103
105 (
106 const std::string &host,
107 const std::string &port,
108 const std::string &path
109 )
110 : p(new detail::Websocket_Channel(host, port, path))
111 {
112 }
113
114 size_t Websocket_Channel::write_some(const char *data, size_t size)
115 {
116 return p->write_some(data, size);
117 }
118
119 size_t Websocket_Channel::read_some(char *data, size_t size)
120 {
121 return p->read_some(data, size);
122 }
123
125}
126#endif
Channel to communicate with a (secure) Websocket.
size_t write_some(const char *data, size_t size) override
Websocket_Channel(const std::string &host, const std::string &port, const std::string &path)
size_t read_some(char *data, size_t size) override