From 350b3e35109171f0edd6fe9d697b91d5e76561f9 Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Sun, 6 Feb 2022 03:01:17 +0000 Subject: CTAN sync 202202060301 --- .../asymptote/LspCpp/examples/WebsocketExample.cpp | 296 +++++++++++++++++++++ 1 file changed, 296 insertions(+) create mode 100755 graphics/asymptote/LspCpp/examples/WebsocketExample.cpp (limited to 'graphics/asymptote/LspCpp/examples/WebsocketExample.cpp') diff --git a/graphics/asymptote/LspCpp/examples/WebsocketExample.cpp b/graphics/asymptote/LspCpp/examples/WebsocketExample.cpp new file mode 100755 index 0000000000..d79569f536 --- /dev/null +++ b/graphics/asymptote/LspCpp/examples/WebsocketExample.cpp @@ -0,0 +1,296 @@ + +#include "LibLsp/JsonRpc/WebSocketServer.h" +#include "LibLsp/lsp/textDocument/signature_help.h" +#include "LibLsp/lsp/general/initialize.h" +#include "LibLsp/lsp/ProtocolJsonHandler.h" +#include "LibLsp/lsp/textDocument/typeHierarchy.h" +#include "LibLsp/lsp/AbsolutePath.h" +#include "LibLsp/lsp/textDocument/resolveCompletionItem.h" +#include + + +#include "LibLsp/JsonRpc/Endpoint.h" +#include "LibLsp/JsonRpc/stream.h" +#include "LibLsp/JsonRpc/TcpServer.h" +#include "LibLsp/lsp/textDocument/document_symbol.h" +#include "LibLsp/lsp/workspace/execute_command.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include +#include +#include "LibLsp/JsonRpc/Endpoint.h" +#include "LibLsp/JsonRpc/RemoteEndPoint.h" +#include "LibLsp/JsonRpc/stream.h" +#include "LibLsp/lsp/ProtocolJsonHandler.h" + +namespace beast = boost::beast; // from +namespace http = beast::http; // from +namespace websocket = beast::websocket; // from +namespace net = boost::asio; // from +using tcp = boost::asio::ip::tcp; // from + +//------------------------------------------------------------------------------ + +std::string _address = "127.0.0.1"; +std::string _port = "9333"; + + + + +using namespace std; +class DummyLog :public lsp::Log +{ +public: + + void log(Level level, std::wstring&& msg) + { + std::wcout << msg << std::endl; + }; + void log(Level level, const std::wstring& msg) + { + std::wcout << msg << std::endl; + }; + void log(Level level, std::string&& msg) + { + std::cout << msg << std::endl; + }; + void log(Level level, const std::string& msg) + { + std::cout << msg << std::endl; + }; +}; + + + +// Sends a WebSocket message and prints the response +class Client : public std::enable_shared_from_this +{ + net::io_context ioc; + tcp::resolver resolver_; + websocket::stream ws_; + beast::flat_buffer buffer_; + std::string host_; + std::string user_agent_; + std::shared_ptr < lsp::ProtocolJsonHandler > protocol_json_handler = std::make_shared< lsp::ProtocolJsonHandler>(); + DummyLog _log; + + std::shared_ptr endpoint = std::make_shared(_log); + + std::shared_ptr proxy_; +public: + RemoteEndPoint point; + +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(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()); + })); + + // Perform the websocket handshake + ws_.async_handshake(host_, "/", + beast::bind_front_handler( + &Client::on_handshake, + shared_from_this())); + } + + void + on_handshake(beast::error_code ec) + { + if (ec) + return; + + // Send the message + + + point.startProcessingMessages(proxy_, proxy_); + // Read a message into our buffer + ws_.async_read( + buffer_, + beast::bind_front_handler( + &Client::on_read, + shared_from_this())); + } + + + void + on_read( + beast::error_code ec, + std::size_t bytes_transferred) + { + boost::ignore_unused(bytes_transferred); + + if (ec) + return; + + char* data = reinterpret_cast(buffer_.data().data()); + std::vector elements(data, data + bytes_transferred); + buffer_.clear(); + proxy_->on_request.EnqueueAll(std::move(elements), false); + + ws_.async_read( + buffer_, + beast::bind_front_handler( + &Client::on_read, + shared_from_this())); + } + + void + on_close(beast::error_code ec) + { + if (ec) + return; + + // If we get here then the connection is closed gracefully + + // The make_printable() function helps print a ConstBufferSequence + std::cout << beast::make_printable(buffer_.data()) << std::endl; + } +}; + +class Server +{ +public: + Server(const std::string& user_agent) : server(user_agent,_address, _port, protocol_json_handler, endpoint, _log) + { + server.point.registerHandler( + [&](const td_initialize::request& req) + { + td_initialize::response rsp; + CodeLensOptions code_lens_options; + code_lens_options.resolveProvider = true; + rsp.result.capabilities.codeLensProvider = code_lens_options; + return rsp; + }); + std::thread([&]() + { + server.run(); + }).detach(); + } + ~Server() + { + server.stop(); + } + std::shared_ptr < lsp::ProtocolJsonHandler > protocol_json_handler = std::make_shared < lsp::ProtocolJsonHandler >(); + DummyLog _log; + + std::shared_ptr < GenericEndpoint > endpoint = std::make_shared(_log); + lsp::WebSocketServer server; + +}; + +int main() +{ + std::string user_agent = std::string(BOOST_BEAST_VERSION_STRING) +" websocket-server-async"; + Server server(user_agent); + + auto client = std::make_shared(); + user_agent = std::string(BOOST_BEAST_VERSION_STRING) + " websocket-client-async"; + client->run(_address.c_str(), _port.c_str(), user_agent.c_str()); + + td_initialize::request req; + + auto rsp = client->point.waitResponse(req); + if (rsp) + { + std::cout << rsp->ToJson() << std::endl; + } + return 0; +} + + + + + + + + + -- cgit v1.2.3