diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-27 18:24:20 +0000 |
commit | 483eb2f56657e8e7f419ab1a4fab8dce9ade8609 (patch) | |
tree | e5d88d25d870d5dedacb6bbdbe2a966086a0a5cf /src/boost/libs/beast/example/websocket/client | |
parent | Initial commit. (diff) | |
download | ceph-upstream.tar.xz ceph-upstream.zip |
Adding upstream version 14.2.21.upstream/14.2.21upstream
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'src/boost/libs/beast/example/websocket/client')
23 files changed, 1613 insertions, 0 deletions
diff --git a/src/boost/libs/beast/example/websocket/client/CMakeLists.txt b/src/boost/libs/beast/example/websocket/client/CMakeLists.txt new file mode 100644 index 00000000..5d1300e2 --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/CMakeLists.txt @@ -0,0 +1,19 @@ +# +# Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# +# Official repository: https://github.com/boostorg/beast +# + +add_subdirectory (async) +add_subdirectory (coro) +add_subdirectory (sync) + +if (OPENSSL_FOUND) + add_subdirectory (async-ssl) + add_subdirectory (async-ssl-system-executor) + add_subdirectory (coro-ssl) + add_subdirectory (sync-ssl) +endif() diff --git a/src/boost/libs/beast/example/websocket/client/Jamfile b/src/boost/libs/beast/example/websocket/client/Jamfile new file mode 100644 index 00000000..94a45811 --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/Jamfile @@ -0,0 +1,18 @@ +# +# Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# +# Official repository: https://github.com/boostorg/beast +# + +build-project async ; +build-project coro ; +build-project sync ; + +# SSL +build-project async-ssl ; +build-project async-ssl-system-executor ; +build-project coro-ssl ; +build-project sync-ssl ; diff --git a/src/boost/libs/beast/example/websocket/client/async-ssl-system-executor/CMakeLists.txt b/src/boost/libs/beast/example/websocket/client/async-ssl-system-executor/CMakeLists.txt new file mode 100644 index 00000000..3a22aade --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/async-ssl-system-executor/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# +# Official repository: https://github.com/boostorg/beast +# + +if (OPENSSL_FOUND) + GroupSources(include/boost/beast beast) + GroupSources(example/common common) + GroupSources(example/websocket/client/async-ssl-system-executor "/") + + add_executable (websocket-client-async-ssl-system-executor + ${BOOST_BEAST_FILES} + ${PROJECT_SOURCE_DIR}/example/common/root_certificates.hpp + Jamfile + websocket_client_async_ssl_system_executor.cpp + ) + + set_property(TARGET websocket-client-async-ssl-system-executor PROPERTY FOLDER "example-websocket-client") + + target_link_libraries (websocket-client-async-ssl-system-executor + OpenSSL::SSL OpenSSL::Crypto + lib-asio + lib-asio-ssl + lib-beast + ) + +endif() diff --git a/src/boost/libs/beast/example/websocket/client/async-ssl-system-executor/Jamfile b/src/boost/libs/beast/example/websocket/client/async-ssl-system-executor/Jamfile new file mode 100644 index 00000000..770a93c7 --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/async-ssl-system-executor/Jamfile @@ -0,0 +1,22 @@ +# +# Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# +# Official repository: https://github.com/boostorg/beast +# + +import ac ; + +project + : requirements + [ ac.check-library /boost/beast//lib-asio-ssl : <library>/boost/beast//lib-asio-ssl/<link>static : <build>no ] + ; + +exe websocket-client-async-ssl-system-executor : + websocket_client_async_ssl_system_executor.cpp + : + <variant>coverage:<build>no + <variant>ubasan:<build>no + ; diff --git a/src/boost/libs/beast/example/websocket/client/async-ssl-system-executor/websocket_client_async_ssl_system_executor.cpp b/src/boost/libs/beast/example/websocket/client/async-ssl-system-executor/websocket_client_async_ssl_system_executor.cpp new file mode 100644 index 00000000..352bc334 --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/async-ssl-system-executor/websocket_client_async_ssl_system_executor.cpp @@ -0,0 +1,254 @@ +// +// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/boostorg/beast +// + +//------------------------------------------------------------------------------ +// +// Example: WebSocket SSL client, asynchronous, using system_executor +// +//------------------------------------------------------------------------------ + +#include "example/common/root_certificates.hpp" + +#include <boost/beast/core.hpp> +#include <boost/beast/ssl.hpp> +#include <boost/beast/websocket.hpp> +#include <boost/beast/websocket/ssl.hpp> +#include <boost/asio/strand.hpp> +#include <boost/asio/system_executor.hpp> +#include <cstdlib> +#include <functional> +#include <iostream> +#include <memory> +#include <string> + +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> +namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp> +using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp> + +//------------------------------------------------------------------------------ + +// Report a failure +void +fail(beast::error_code ec, char const* what) +{ + std::cerr << what << ": " << ec.message() << "\n"; +} + +// Sends a WebSocket message and prints the response +class session : public std::enable_shared_from_this<session> +{ + tcp::resolver resolver_; + websocket::stream< + beast::ssl_stream<beast::tcp_stream>> ws_; + beast::flat_buffer buffer_; + std::string host_; + std::string text_; + + // Objects are constructed with a strand to + // ensure that handlers do not execute concurrently. + session(net::strand<net::system_executor> ex, ssl::context& ctx) + : resolver_(ex) + , ws_(ex, ctx) + { + } +public: + // Delegate construction to a prive constructor to be able to use + // the same strand for both I/O objects. + explicit + session(ssl::context& ctx) + : session(net::make_strand(net::system_executor{}), ctx) + { + } + + // Start the asynchronous operation + void + run( + char const* host, + char const* port, + char const* text) + { + // Save these for later + host_ = host; + text_ = text; + + // Look up the domain name + resolver_.async_resolve( + host, + port, + beast::bind_front_handler( + &session::on_resolve, + shared_from_this())); + } + + void + on_resolve( + beast::error_code ec, + tcp::resolver::results_type results) + { + if(ec) + return fail(ec, "resolve"); + + // Set a timeout on 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( + &session::on_connect, + shared_from_this())); + } + + void + on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type) + { + if(ec) + return fail(ec, "connect"); + + // Set a timeout on the operation + beast::get_lowest_layer(ws_).expires_after(std::chrono::seconds(30)); + + // Perform the SSL handshake + ws_.next_layer().async_handshake( + ssl::stream_base::client, + beast::bind_front_handler( + &session::on_ssl_handshake, + shared_from_this())); + } + + void + on_ssl_handshake(beast::error_code ec) + { + if(ec) + return fail(ec, "ssl_handshake"); + + // 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, + std::string(BOOST_BEAST_VERSION_STRING) + + " websocket-client-async-ssl"); + })); + + // Perform the websocket handshake + ws_.async_handshake(host_, "/", + beast::bind_front_handler( + &session::on_handshake, + shared_from_this())); + } + + void + on_handshake(beast::error_code ec) + { + if(ec) + return fail(ec, "handshake"); + + // Send the message + ws_.async_write( + net::buffer(text_), + beast::bind_front_handler( + &session::on_write, + shared_from_this())); + } + + void + on_write( + beast::error_code ec, + std::size_t bytes_transferred) + { + boost::ignore_unused(bytes_transferred); + + if(ec) + return fail(ec, "write"); + + // Read a message into our buffer + ws_.async_read( + buffer_, + beast::bind_front_handler( + &session::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 fail(ec, "read"); + + // Close the WebSocket connection + ws_.async_close(websocket::close_code::normal, + beast::bind_front_handler( + &session::on_close, + shared_from_this())); + } + + void + on_close(beast::error_code ec) + { + if(ec) + return fail(ec, "close"); + + // 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; + } +}; + +//------------------------------------------------------------------------------ + +int main(int argc, char** argv) +{ + // Check command line arguments. + if(argc != 4) + { + std::cerr << + "Usage: websocket-client-async-ssl <host> <port> <text>\n" << + "Example:\n" << + " websocket-client-async-ssl echo.websocket.org 443 \"Hello, world!\"\n"; + return EXIT_FAILURE; + } + auto const host = argv[1]; + auto const port = argv[2]; + auto const text = argv[3]; + + + // The SSL context is required, and holds certificates + ssl::context ctx{ssl::context::tlsv12_client}; + + // This holds the root certificate used for verification + load_root_certificates(ctx); + + // Launch the asynchronous operation + std::make_shared<session>(ctx)->run(host, port, text); + + // The async operations will run on the system_executor. + // Because the main thread has nothing to do in this example, we just wait + // for the system_executor to run out of work. + net::system_executor().context().join(); + + return EXIT_SUCCESS; +} diff --git a/src/boost/libs/beast/example/websocket/client/async-ssl/CMakeLists.txt b/src/boost/libs/beast/example/websocket/client/async-ssl/CMakeLists.txt new file mode 100644 index 00000000..a2198280 --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/async-ssl/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# +# Official repository: https://github.com/boostorg/beast +# + +if (OPENSSL_FOUND) + GroupSources(include/boost/beast beast) + GroupSources(example/common common) + GroupSources(example/websocket/client/async-ssl "/") + + add_executable (websocket-client-async-ssl + ${BOOST_BEAST_FILES} + ${PROJECT_SOURCE_DIR}/example/common/root_certificates.hpp + Jamfile + websocket_client_async_ssl.cpp + ) + + set_property(TARGET websocket-client-async-ssl PROPERTY FOLDER "example-websocket-client") + + target_link_libraries (websocket-client-async-ssl + OpenSSL::SSL OpenSSL::Crypto + lib-asio + lib-asio-ssl + lib-beast + ) + +endif() diff --git a/src/boost/libs/beast/example/websocket/client/async-ssl/Jamfile b/src/boost/libs/beast/example/websocket/client/async-ssl/Jamfile new file mode 100644 index 00000000..1f46a94d --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/async-ssl/Jamfile @@ -0,0 +1,22 @@ +# +# Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# +# Official repository: https://github.com/boostorg/beast +# + +import ac ; + +project + : requirements + [ ac.check-library /boost/beast//lib-asio-ssl : <library>/boost/beast//lib-asio-ssl/<link>static : <build>no ] + ; + +exe websocket-client-async-ssl : + websocket_client_async_ssl.cpp + : + <variant>coverage:<build>no + <variant>ubasan:<build>no + ; diff --git a/src/boost/libs/beast/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp b/src/boost/libs/beast/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp new file mode 100644 index 00000000..7251620a --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/async-ssl/websocket_client_async_ssl.cpp @@ -0,0 +1,247 @@ +// +// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/boostorg/beast +// + +//------------------------------------------------------------------------------ +// +// Example: WebSocket SSL client, asynchronous +// +//------------------------------------------------------------------------------ + +#include "example/common/root_certificates.hpp" + +#include <boost/beast/core.hpp> +#include <boost/beast/ssl.hpp> +#include <boost/beast/websocket.hpp> +#include <boost/beast/websocket/ssl.hpp> +#include <boost/asio/strand.hpp> +#include <cstdlib> +#include <functional> +#include <iostream> +#include <memory> +#include <string> + +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> +namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp> +using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp> + +//------------------------------------------------------------------------------ + +// Report a failure +void +fail(beast::error_code ec, char const* what) +{ + std::cerr << what << ": " << ec.message() << "\n"; +} + +// Sends a WebSocket message and prints the response +class session : public std::enable_shared_from_this<session> +{ + tcp::resolver resolver_; + websocket::stream< + beast::ssl_stream<beast::tcp_stream>> ws_; + beast::flat_buffer buffer_; + std::string host_; + std::string text_; + +public: + // Resolver and socket require an io_context + explicit + session(net::io_context& ioc, ssl::context& ctx) + : resolver_(net::make_strand(ioc)) + , ws_(net::make_strand(ioc), ctx) + { + } + + // Start the asynchronous operation + void + run( + char const* host, + char const* port, + char const* text) + { + // Save these for later + host_ = host; + text_ = text; + + // Look up the domain name + resolver_.async_resolve( + host, + port, + beast::bind_front_handler( + &session::on_resolve, + shared_from_this())); + } + + void + on_resolve( + beast::error_code ec, + tcp::resolver::results_type results) + { + if(ec) + return fail(ec, "resolve"); + + // Set a timeout on 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( + &session::on_connect, + shared_from_this())); + } + + void + on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type) + { + if(ec) + return fail(ec, "connect"); + + // Set a timeout on the operation + beast::get_lowest_layer(ws_).expires_after(std::chrono::seconds(30)); + + // Perform the SSL handshake + ws_.next_layer().async_handshake( + ssl::stream_base::client, + beast::bind_front_handler( + &session::on_ssl_handshake, + shared_from_this())); + } + + void + on_ssl_handshake(beast::error_code ec) + { + if(ec) + return fail(ec, "ssl_handshake"); + + // 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, + std::string(BOOST_BEAST_VERSION_STRING) + + " websocket-client-async-ssl"); + })); + + // Perform the websocket handshake + ws_.async_handshake(host_, "/", + beast::bind_front_handler( + &session::on_handshake, + shared_from_this())); + } + + void + on_handshake(beast::error_code ec) + { + if(ec) + return fail(ec, "handshake"); + + // Send the message + ws_.async_write( + net::buffer(text_), + beast::bind_front_handler( + &session::on_write, + shared_from_this())); + } + + void + on_write( + beast::error_code ec, + std::size_t bytes_transferred) + { + boost::ignore_unused(bytes_transferred); + + if(ec) + return fail(ec, "write"); + + // Read a message into our buffer + ws_.async_read( + buffer_, + beast::bind_front_handler( + &session::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 fail(ec, "read"); + + // Close the WebSocket connection + ws_.async_close(websocket::close_code::normal, + beast::bind_front_handler( + &session::on_close, + shared_from_this())); + } + + void + on_close(beast::error_code ec) + { + if(ec) + return fail(ec, "close"); + + // 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; + } +}; + +//------------------------------------------------------------------------------ + +int main(int argc, char** argv) +{ + // Check command line arguments. + if(argc != 4) + { + std::cerr << + "Usage: websocket-client-async-ssl <host> <port> <text>\n" << + "Example:\n" << + " websocket-client-async-ssl echo.websocket.org 443 \"Hello, world!\"\n"; + return EXIT_FAILURE; + } + auto const host = argv[1]; + auto const port = argv[2]; + auto const text = argv[3]; + + // The io_context is required for all I/O + net::io_context ioc; + + // The SSL context is required, and holds certificates + ssl::context ctx{ssl::context::tlsv12_client}; + + // This holds the root certificate used for verification + load_root_certificates(ctx); + + // Launch the asynchronous operation + std::make_shared<session>(ioc, ctx)->run(host, port, text); + + // Run the I/O service. The call will return when + // the socket is closed. + ioc.run(); + + return EXIT_SUCCESS; +} diff --git a/src/boost/libs/beast/example/websocket/client/async/CMakeLists.txt b/src/boost/libs/beast/example/websocket/client/async/CMakeLists.txt new file mode 100644 index 00000000..cc643407 --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/async/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# +# Official repository: https://github.com/boostorg/beast +# + +GroupSources(include/boost/beast beast) +GroupSources(example/websocket/client/async "/") + +add_executable (websocket-client-async + ${BOOST_BEAST_FILES} + Jamfile + websocket_client_async.cpp +) + +target_link_libraries(websocket-client-async + lib-asio + lib-beast) + +set_property(TARGET websocket-client-async PROPERTY FOLDER "example-websocket-client") diff --git a/src/boost/libs/beast/example/websocket/client/async/Jamfile b/src/boost/libs/beast/example/websocket/client/async/Jamfile new file mode 100644 index 00000000..e5359db3 --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/async/Jamfile @@ -0,0 +1,15 @@ +# +# Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# +# Official repository: https://github.com/boostorg/beast +# + +exe websocket-client-async : + websocket_client_async.cpp + : + <variant>coverage:<build>no + <variant>ubasan:<build>no + ; diff --git a/src/boost/libs/beast/example/websocket/client/async/websocket_client_async.cpp b/src/boost/libs/beast/example/websocket/client/async/websocket_client_async.cpp new file mode 100644 index 00000000..15b127d3 --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/async/websocket_client_async.cpp @@ -0,0 +1,218 @@ +// +// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/boostorg/beast +// + +//------------------------------------------------------------------------------ +// +// Example: WebSocket client, asynchronous +// +//------------------------------------------------------------------------------ + +#include <boost/beast/core.hpp> +#include <boost/beast/websocket.hpp> +#include <boost/asio/strand.hpp> +#include <cstdlib> +#include <functional> +#include <iostream> +#include <memory> +#include <string> + +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> + +//------------------------------------------------------------------------------ + +// Report a failure +void +fail(beast::error_code ec, char const* what) +{ + std::cerr << what << ": " << ec.message() << "\n"; +} + +// Sends a WebSocket message and prints the response +class session : public std::enable_shared_from_this<session> +{ + tcp::resolver resolver_; + websocket::stream<beast::tcp_stream> ws_; + beast::flat_buffer buffer_; + std::string host_; + std::string text_; + +public: + // Resolver and socket require an io_context + explicit + session(net::io_context& ioc) + : resolver_(net::make_strand(ioc)) + , ws_(net::make_strand(ioc)) + { + } + + // Start the asynchronous operation + void + run( + char const* host, + char const* port, + char const* text) + { + // Save these for later + host_ = host; + text_ = text; + + // Look up the domain name + resolver_.async_resolve( + host, + port, + beast::bind_front_handler( + &session::on_resolve, + shared_from_this())); + } + + void + on_resolve( + beast::error_code ec, + tcp::resolver::results_type results) + { + if(ec) + return fail(ec, "resolve"); + + // 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( + &session::on_connect, + shared_from_this())); + } + + void + on_connect(beast::error_code ec, tcp::resolver::results_type::endpoint_type) + { + if(ec) + return fail(ec, "connect"); + + // 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, + std::string(BOOST_BEAST_VERSION_STRING) + + " websocket-client-async"); + })); + + // Perform the websocket handshake + ws_.async_handshake(host_, "/", + beast::bind_front_handler( + &session::on_handshake, + shared_from_this())); + } + + void + on_handshake(beast::error_code ec) + { + if(ec) + return fail(ec, "handshake"); + + // Send the message + ws_.async_write( + net::buffer(text_), + beast::bind_front_handler( + &session::on_write, + shared_from_this())); + } + + void + on_write( + beast::error_code ec, + std::size_t bytes_transferred) + { + boost::ignore_unused(bytes_transferred); + + if(ec) + return fail(ec, "write"); + + // Read a message into our buffer + ws_.async_read( + buffer_, + beast::bind_front_handler( + &session::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 fail(ec, "read"); + + // Close the WebSocket connection + ws_.async_close(websocket::close_code::normal, + beast::bind_front_handler( + &session::on_close, + shared_from_this())); + } + + void + on_close(beast::error_code ec) + { + if(ec) + return fail(ec, "close"); + + // 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; + } +}; + +//------------------------------------------------------------------------------ + +int main(int argc, char** argv) +{ + // Check command line arguments. + if(argc != 4) + { + std::cerr << + "Usage: websocket-client-async <host> <port> <text>\n" << + "Example:\n" << + " websocket-client-async echo.websocket.org 80 \"Hello, world!\"\n"; + return EXIT_FAILURE; + } + auto const host = argv[1]; + auto const port = argv[2]; + auto const text = argv[3]; + + // The io_context is required for all I/O + net::io_context ioc; + + // Launch the asynchronous operation + std::make_shared<session>(ioc)->run(host, port, text); + + // Run the I/O service. The call will return when + // the socket is closed. + ioc.run(); + + return EXIT_SUCCESS; +} diff --git a/src/boost/libs/beast/example/websocket/client/coro-ssl/CMakeLists.txt b/src/boost/libs/beast/example/websocket/client/coro-ssl/CMakeLists.txt new file mode 100644 index 00000000..fe9db75c --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/coro-ssl/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# +# Official repository: https://github.com/boostorg/beast +# + +if (OPENSSL_FOUND) + GroupSources(include/boost/beast beast) + GroupSources(example/common common) + GroupSources(example/websocket/client/coro-ssl "/") + + add_executable (websocket-client-coro-ssl + ${BOOST_BEAST_FILES} + ${PROJECT_SOURCE_DIR}/example/common/root_certificates.hpp + Jamfile + websocket_client_coro_ssl.cpp + ) + + set_property(TARGET websocket-client-coro-ssl PROPERTY FOLDER "example-websocket-client") + + target_link_libraries (websocket-client-coro-ssl + OpenSSL::SSL OpenSSL::Crypto + lib-asio + lib-asio-ssl + lib-beast + ) + +endif() diff --git a/src/boost/libs/beast/example/websocket/client/coro-ssl/Jamfile b/src/boost/libs/beast/example/websocket/client/coro-ssl/Jamfile new file mode 100644 index 00000000..f6f1bb92 --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/coro-ssl/Jamfile @@ -0,0 +1,23 @@ +# +# Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# +# Official repository: https://github.com/boostorg/beast +# + +import ac ; + +project + : requirements + [ ac.check-library /boost/beast//lib-asio-ssl : <library>/boost/beast//lib-asio-ssl/<link>static : <build>no ] + ; + +exe websocket-client-coro-ssl : + websocket_client_coro_ssl.cpp + : + <variant>coverage:<build>no + <variant>ubasan:<build>no + <library>/boost/coroutine//boost_coroutine + ; diff --git a/src/boost/libs/beast/example/websocket/client/coro-ssl/websocket_client_coro_ssl.cpp b/src/boost/libs/beast/example/websocket/client/coro-ssl/websocket_client_coro_ssl.cpp new file mode 100644 index 00000000..d4d8ba32 --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/coro-ssl/websocket_client_coro_ssl.cpp @@ -0,0 +1,170 @@ +// +// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/boostorg/beast +// + +//------------------------------------------------------------------------------ +// +// Example: WebSocket SSL client, coroutine +// +//------------------------------------------------------------------------------ + +#include "example/common/root_certificates.hpp" + +#include <boost/beast/core.hpp> +#include <boost/beast/ssl.hpp> +#include <boost/beast/websocket.hpp> +#include <boost/beast/websocket/ssl.hpp> +#include <boost/asio/spawn.hpp> +#include <cstdlib> +#include <functional> +#include <iostream> +#include <string> + +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> +namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp> +using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp> + +//------------------------------------------------------------------------------ + +// Report a failure +void +fail(beast::error_code ec, char const* what) +{ + std::cerr << what << ": " << ec.message() << "\n"; +} + +// Sends a WebSocket message and prints the response +void +do_session( + std::string const& host, + std::string const& port, + std::string const& text, + net::io_context& ioc, + ssl::context& ctx, + net::yield_context yield) +{ + beast::error_code ec; + + // These objects perform our I/O + tcp::resolver resolver(ioc); + websocket::stream< + beast::ssl_stream<beast::tcp_stream>> ws(ioc, ctx); + + // Look up the domain name + auto const results = resolver.async_resolve(host, port, yield[ec]); + if(ec) + return fail(ec, "resolve"); + + // Set a timeout on 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, yield[ec]); + if(ec) + return fail(ec, "connect"); + + // Set a timeout on the operation + beast::get_lowest_layer(ws).expires_after(std::chrono::seconds(30)); + + // 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, + std::string(BOOST_BEAST_VERSION_STRING) + + " websocket-client-coro"); + })); + + // Perform the SSL handshake + ws.next_layer().async_handshake(ssl::stream_base::client, yield[ec]); + if(ec) + return fail(ec, "ssl_handshake"); + + // 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)); + + // Perform the websocket handshake + ws.async_handshake(host, "/", yield[ec]); + if(ec) + return fail(ec, "handshake"); + + // Send the message + ws.async_write(net::buffer(std::string(text)), yield[ec]); + if(ec) + return fail(ec, "write"); + + // This buffer will hold the incoming message + beast::flat_buffer buffer; + + // Read a message into our buffer + ws.async_read(buffer, yield[ec]); + if(ec) + return fail(ec, "read"); + + // Close the WebSocket connection + ws.async_close(websocket::close_code::normal, yield[ec]); + if(ec) + return fail(ec, "close"); + + // 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; +} + +//------------------------------------------------------------------------------ + +int main(int argc, char** argv) +{ + // Check command line arguments. + if(argc != 4) + { + std::cerr << + "Usage: websocket-client-coro-ssl <host> <port> <text>\n" << + "Example:\n" << + " websocket-client-coro-ssl echo.websocket.org 443 \"Hello, world!\"\n"; + return EXIT_FAILURE; + } + auto const host = argv[1]; + auto const port = argv[2]; + auto const text = argv[3]; + + // The io_context is required for all I/O + net::io_context ioc; + + // The SSL context is required, and holds certificates + ssl::context ctx{ssl::context::tlsv12_client}; + + // This holds the root certificate used for verification + load_root_certificates(ctx); + + // Launch the asynchronous operation + boost::asio::spawn(ioc, std::bind( + &do_session, + std::string(host), + std::string(port), + std::string(text), + std::ref(ioc), + std::ref(ctx), + std::placeholders::_1)); + + // Run the I/O service. The call will return when + // the socket is closed. + ioc.run(); + + return EXIT_SUCCESS; +} diff --git a/src/boost/libs/beast/example/websocket/client/coro/CMakeLists.txt b/src/boost/libs/beast/example/websocket/client/coro/CMakeLists.txt new file mode 100644 index 00000000..2bfeef28 --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/coro/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# +# Official repository: https://github.com/boostorg/beast +# + +GroupSources(include/boost/beast beast) +GroupSources(example/websocket/client/coro "/") + +add_executable (websocket-client-coro + ${BOOST_BEAST_FILES} + Jamfile + websocket_client_coro.cpp +) + +target_link_libraries(websocket-client-coro + lib-asio + lib-beast) + +set_property(TARGET websocket-client-coro PROPERTY FOLDER "example-websocket-client") diff --git a/src/boost/libs/beast/example/websocket/client/coro/Jamfile b/src/boost/libs/beast/example/websocket/client/coro/Jamfile new file mode 100644 index 00000000..761dfe8f --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/coro/Jamfile @@ -0,0 +1,16 @@ +# +# Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# +# Official repository: https://github.com/boostorg/beast +# + +exe websocket-client-coro : + websocket_client_coro.cpp + : + <variant>coverage:<build>no + <variant>ubasan:<build>no + <library>/boost/coroutine//boost_coroutine + ; diff --git a/src/boost/libs/beast/example/websocket/client/coro/websocket_client_coro.cpp b/src/boost/libs/beast/example/websocket/client/coro/websocket_client_coro.cpp new file mode 100644 index 00000000..359015b2 --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/coro/websocket_client_coro.cpp @@ -0,0 +1,148 @@ +// +// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/boostorg/beast +// + +//------------------------------------------------------------------------------ +// +// Example: WebSocket client, coroutine +// +//------------------------------------------------------------------------------ + +#include <boost/beast/core.hpp> +#include <boost/beast/websocket.hpp> +#include <boost/asio/spawn.hpp> +#include <cstdlib> +#include <functional> +#include <iostream> +#include <string> + +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> + +//------------------------------------------------------------------------------ + +// Report a failure +void +fail(beast::error_code ec, char const* what) +{ + std::cerr << what << ": " << ec.message() << "\n"; +} + +// Sends a WebSocket message and prints the response +void +do_session( + std::string const& host, + std::string const& port, + std::string const& text, + net::io_context& ioc, + net::yield_context yield) +{ + beast::error_code ec; + + // These objects perform our I/O + tcp::resolver resolver(ioc); + websocket::stream<beast::tcp_stream> ws(ioc); + + // Look up the domain name + auto const results = resolver.async_resolve(host, port, yield[ec]); + if(ec) + return fail(ec, "resolve"); + + // Set a timeout on 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, yield[ec]); + if(ec) + return fail(ec, "connect"); + + // 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, + std::string(BOOST_BEAST_VERSION_STRING) + + " websocket-client-coro"); + })); + + // Perform the websocket handshake + ws.async_handshake(host, "/", yield[ec]); + if(ec) + return fail(ec, "handshake"); + + // Send the message + ws.async_write(net::buffer(std::string(text)), yield[ec]); + if(ec) + return fail(ec, "write"); + + // This buffer will hold the incoming message + beast::flat_buffer buffer; + + // Read a message into our buffer + ws.async_read(buffer, yield[ec]); + if(ec) + return fail(ec, "read"); + + // Close the WebSocket connection + ws.async_close(websocket::close_code::normal, yield[ec]); + if(ec) + return fail(ec, "close"); + + // 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; +} + +//------------------------------------------------------------------------------ + +int main(int argc, char** argv) +{ + // Check command line arguments. + if(argc != 4) + { + std::cerr << + "Usage: websocket-client-coro <host> <port> <text>\n" << + "Example:\n" << + " websocket-client-coro echo.websocket.org 80 \"Hello, world!\"\n"; + return EXIT_FAILURE; + } + auto const host = argv[1]; + auto const port = argv[2]; + auto const text = argv[3]; + + // The io_context is required for all I/O + net::io_context ioc; + + // Launch the asynchronous operation + boost::asio::spawn(ioc, std::bind( + &do_session, + std::string(host), + std::string(port), + std::string(text), + std::ref(ioc), + std::placeholders::_1)); + + // Run the I/O service. The call will return when + // the socket is closed. + ioc.run(); + + return EXIT_SUCCESS; +} diff --git a/src/boost/libs/beast/example/websocket/client/sync-ssl/CMakeLists.txt b/src/boost/libs/beast/example/websocket/client/sync-ssl/CMakeLists.txt new file mode 100644 index 00000000..b8449570 --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/sync-ssl/CMakeLists.txt @@ -0,0 +1,31 @@ +# +# Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# +# Official repository: https://github.com/boostorg/beast +# + +if (OPENSSL_FOUND) + GroupSources(include/boost/beast beast) + GroupSources(example/common common) + GroupSources(example/websocket/client/sync-ssl "/") + + add_executable (websocket-client-sync-ssl + ${BOOST_BEAST_FILES} + ${PROJECT_SOURCE_DIR}/example/common/root_certificates.hpp + Jamfile + websocket_client_sync_ssl.cpp + ) + + set_property(TARGET websocket-client-sync-ssl PROPERTY FOLDER "example-websocket-client") + + target_link_libraries (websocket-client-sync-ssl + OpenSSL::SSL OpenSSL::Crypto + lib-asio + lib-asio-ssl + lib-beast + ) + +endif() diff --git a/src/boost/libs/beast/example/websocket/client/sync-ssl/Jamfile b/src/boost/libs/beast/example/websocket/client/sync-ssl/Jamfile new file mode 100644 index 00000000..0cfec0f6 --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/sync-ssl/Jamfile @@ -0,0 +1,22 @@ +# +# Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# +# Official repository: https://github.com/boostorg/beast +# + +import ac ; + +project + : requirements + [ ac.check-library /boost/beast//lib-asio-ssl : <library>/boost/beast//lib-asio-ssl/<link>static : <build>no ] + ; + +exe websocket-client-sync-ssl : + websocket_client_sync_ssl.cpp + : + <variant>coverage:<build>no + <variant>ubasan:<build>no + ; diff --git a/src/boost/libs/beast/example/websocket/client/sync-ssl/websocket_client_sync_ssl.cpp b/src/boost/libs/beast/example/websocket/client/sync-ssl/websocket_client_sync_ssl.cpp new file mode 100644 index 00000000..8291e479 --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/sync-ssl/websocket_client_sync_ssl.cpp @@ -0,0 +1,111 @@ +// +// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/boostorg/beast +// + +//------------------------------------------------------------------------------ +// +// Example: WebSocket SSL client, synchronous +// +//------------------------------------------------------------------------------ + +#include "example/common/root_certificates.hpp" + +#include <boost/beast/core.hpp> +#include <boost/beast/ssl.hpp> +#include <boost/beast/websocket.hpp> +#include <boost/beast/websocket/ssl.hpp> +#include <boost/asio/connect.hpp> +#include <boost/asio/ip/tcp.hpp> +#include <boost/asio/ssl/stream.hpp> +#include <cstdlib> +#include <iostream> +#include <string> + +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> +namespace ssl = boost::asio::ssl; // from <boost/asio/ssl.hpp> +using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp> + +// Sends a WebSocket message and prints the response +int main(int argc, char** argv) +{ + try + { + // Check command line arguments. + if(argc != 4) + { + std::cerr << + "Usage: websocket-client-sync-ssl <host> <port> <text>\n" << + "Example:\n" << + " websocket-client-sync-ssl echo.websocket.org 443 \"Hello, world!\"\n"; + return EXIT_FAILURE; + } + auto const host = argv[1]; + auto const port = argv[2]; + auto const text = argv[3]; + + // The io_context is required for all I/O + net::io_context ioc; + + // The SSL context is required, and holds certificates + ssl::context ctx{ssl::context::tlsv12_client}; + + // This holds the root certificate used for verification + load_root_certificates(ctx); + + // These objects perform our I/O + tcp::resolver resolver{ioc}; + websocket::stream<beast::ssl_stream<tcp::socket>> ws{ioc, ctx}; + + // Look up the domain name + auto const results = resolver.resolve(host, port); + + // Make the connection on the IP address we get from a lookup + net::connect(ws.next_layer().next_layer(), results.begin(), results.end()); + + // Perform the SSL handshake + ws.next_layer().handshake(ssl::stream_base::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, + std::string(BOOST_BEAST_VERSION_STRING) + + " websocket-client-coro"); + })); + + // Perform the websocket handshake + ws.handshake(host, "/"); + + // Send the message + ws.write(net::buffer(std::string(text))); + + // This buffer will hold the incoming message + beast::flat_buffer buffer; + + // Read a message into our buffer + ws.read(buffer); + + // Close the WebSocket connection + ws.close(websocket::close_code::normal); + + // 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; + } + catch(std::exception const& e) + { + std::cerr << "Error: " << e.what() << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} diff --git a/src/boost/libs/beast/example/websocket/client/sync/CMakeLists.txt b/src/boost/libs/beast/example/websocket/client/sync/CMakeLists.txt new file mode 100644 index 00000000..d8606ab5 --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/sync/CMakeLists.txt @@ -0,0 +1,23 @@ +# +# Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# +# Official repository: https://github.com/boostorg/beast +# + +GroupSources(include/boost/beast beast) +GroupSources(example/websocket/client/sync "/") + +add_executable (websocket-client-sync + ${BOOST_BEAST_FILES} + Jamfile + websocket_client_sync.cpp +) + +target_link_libraries(websocket-client-sync + lib-asio + lib-beast) + +set_property(TARGET websocket-client-sync PROPERTY FOLDER "example-websocket-client") diff --git a/src/boost/libs/beast/example/websocket/client/sync/Jamfile b/src/boost/libs/beast/example/websocket/client/sync/Jamfile new file mode 100644 index 00000000..ea71a0ce --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/sync/Jamfile @@ -0,0 +1,15 @@ +# +# Copyright (c) 2016-2017 Vinnie Falco (vinnie dot falco at gmail dot com) +# +# Distributed under the Boost Software License, Version 1.0. (See accompanying +# file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +# +# Official repository: https://github.com/boostorg/beast +# + +exe websocket-client-sync : + websocket_client_sync.cpp + : + <variant>coverage:<build>no + <variant>ubasan:<build>no + ; diff --git a/src/boost/libs/beast/example/websocket/client/sync/websocket_client_sync.cpp b/src/boost/libs/beast/example/websocket/client/sync/websocket_client_sync.cpp new file mode 100644 index 00000000..c80ae41b --- /dev/null +++ b/src/boost/libs/beast/example/websocket/client/sync/websocket_client_sync.cpp @@ -0,0 +1,100 @@ +// +// Copyright (c) 2016-2019 Vinnie Falco (vinnie dot falco at gmail dot com) +// +// Distributed under the Boost Software License, Version 1.0. (See accompanying +// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) +// +// Official repository: https://github.com/boostorg/beast +// + +//------------------------------------------------------------------------------ +// +// Example: WebSocket client, synchronous +// +//------------------------------------------------------------------------------ + +//[example_websocket_client + +#include <boost/beast/core.hpp> +#include <boost/beast/websocket.hpp> +#include <boost/asio/connect.hpp> +#include <boost/asio/ip/tcp.hpp> +#include <cstdlib> +#include <iostream> +#include <string> + +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> + +// Sends a WebSocket message and prints the response +int main(int argc, char** argv) +{ + try + { + // Check command line arguments. + if(argc != 4) + { + std::cerr << + "Usage: websocket-client-sync <host> <port> <text>\n" << + "Example:\n" << + " websocket-client-sync echo.websocket.org 80 \"Hello, world!\"\n"; + return EXIT_FAILURE; + } + auto const host = argv[1]; + auto const port = argv[2]; + auto const text = argv[3]; + + // The io_context is required for all I/O + net::io_context ioc; + + // These objects perform our I/O + tcp::resolver resolver{ioc}; + websocket::stream<tcp::socket> ws{ioc}; + + // Look up the domain name + auto const results = resolver.resolve(host, port); + + // Make the connection on the IP address we get from a lookup + net::connect(ws.next_layer(), results.begin(), results.end()); + + // 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, + std::string(BOOST_BEAST_VERSION_STRING) + + " websocket-client-coro"); + })); + + // Perform the websocket handshake + ws.handshake(host, "/"); + + // Send the message + ws.write(net::buffer(std::string(text))); + + // This buffer will hold the incoming message + beast::flat_buffer buffer; + + // Read a message into our buffer + ws.read(buffer); + + // Close the WebSocket connection + ws.close(websocket::close_code::normal); + + // 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; + } + catch(std::exception const& e) + { + std::cerr << "Error: " << e.what() << std::endl; + return EXIT_FAILURE; + } + return EXIT_SUCCESS; +} + +//] |