namespace beast = boost::beast; // from <boost/beast.hpp>
namespace http = beast::http; // from <boost/beast/http.hpp>
namespace websocket = beast::websocket; // from <boost/beast/websocket.hpp>
namespace net = boost::asio; // from <boost/asio.hpp>
using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
public:
// Resolver and socket require an io_context
explicit
Client()
: resolver_(net::make_strand(ioc))
, ws_(net::make_strand(ioc)),point(protocol_json_handler, endpoint, _log)
{
proxy_ = std::make_shared<lsp::websocket_stream_wrapper>(ws_);
}
// Start the asynchronous operation
void
run(
char const* host,
char const* port, char const* user_agent)
{
// Save these for later
host_ = host;
user_agent_ = user_agent;
// Look up the domain name
resolver_.async_resolve(
host,
port,
beast::bind_front_handler(
&Client::on_resolve,
shared_from_this()));
std::thread([&]
{
ioc.run();
}).detach();
while (!point.isWorking())
{
std::this_thread::sleep_for(std::chrono::milliseconds (50));
}
}
void
on_resolve(
beast::error_code ec,
tcp::resolver::results_type results)
{
if (ec)
return;
// Set the timeout for the operation
beast::get_lowest_layer(ws_).expires_after(std::chrono::seconds(30));
// Make the connection on the IP address we get from a lookup
beast::get_lowest_layer(ws_).async_connect(
results,
beast::bind_front_handler(
&Client::on_connect,
shared_from_this()));
}
void
on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type)
{
if (ec)
return;
// Turn off the timeout on the tcp_stream, because
// the websocket stream has its own timeout system.
beast::get_lowest_layer(ws_).expires_never();
// Set suggested timeout settings for the websocket
ws_.set_option(
websocket::stream_base::timeout::suggested(
beast::role_type::client));
// Set a decorator to change the User-Agent of the handshake
ws_.set_option(websocket::stream_base::decorator(
[=](websocket::request_type& req)
{
req.set(http::field::user_agent,
user_agent_.c_str());
}));