From 7028579170d83cb81a97478b620f3cb15a2fd693 Mon Sep 17 00:00:00 2001 From: Vinnie Falco Date: Tue, 17 Jan 2017 14:50:38 -0500 Subject: [PATCH] Squashed 'src/beast/' changes from 1ab7a2f..c00cd37 c00cd37 Set version to 1.0.0-b23 f662e36 Travis CI improvements: b05fa33 Fix message constructor and special members b4722cc Add copy special members 420d1c7 Better logging in async echo server 149e3a2 Add file and line number to thrown exceptions 3e88b83 Tune websocket echo server for performance git-subtree-dir: src/beast git-subtree-split: c00cd37b8a441a92755658014fdde97d515ec7ed --- .travis.yml | 7 +- CHANGELOG.md | 11 ++ include/beast/core/detail/buffer_cat.hpp | 9 +- include/beast/core/detail/type_traits.hpp | 14 +++ include/beast/core/impl/basic_streambuf.ipp | 4 +- include/beast/core/impl/buffers_adapter.ipp | 5 +- include/beast/core/impl/static_streambuf.ipp | 4 +- include/beast/core/static_string.hpp | 22 ++-- include/beast/http/impl/message.ipp | 18 +-- include/beast/http/message.hpp | 19 +++- include/beast/version.hpp | 2 +- include/beast/websocket/impl/stream.ipp | 1 + include/beast/websocket/option.hpp | 10 +- include/beast/zlib/detail/deflate_stream.hpp | 12 +- include/beast/zlib/detail/inflate_stream.hpp | 11 +- scripts/build-and-test.sh | 13 ++- test/http/message.cpp | 14 +++ test/websocket/stream.cpp | 5 +- .../websocket/websocket_async_echo_server.hpp | 105 ++++++++++++------ test/websocket/websocket_echo.cpp | 20 +++- 20 files changed, 221 insertions(+), 85 deletions(-) diff --git a/.travis.yml b/.travis.yml index 96efe8e73..0035abc4c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,3 +1,4 @@ +sudo: false language: cpp env: @@ -11,7 +12,7 @@ env: - LCOV_ROOT=$HOME/lcov - VALGRIND_ROOT=$HOME/valgrind-install - BOOST_ROOT=$HOME/boost_1_61_0 - - BOOST_URL='http://downloads.sourceforge.net/project/boost/boost/1.61.0/boost_1_61_0.tar.gz?use_mirror=netix' + - BOOST_URL='http://sourceforge.net/projects/boost/files/boost/1.61.0/boost_1_61_0.tar.gz' packages: &gcc5_pkgs - gcc-5 - g++-5 @@ -30,7 +31,7 @@ packages: &gcc5_pkgs matrix: include: - # GCC/Coverage/Autobahn + # GCC/Coverage/Autobahn (if master or develop branch) - compiler: gcc env: - GCC_VER=5 @@ -77,7 +78,7 @@ before_install: - scripts/install-dependencies.sh script: - - scripts/build-and-test.sh + - travis_retry scripts/build-and-test.sh after_script: - cat nohup.out || echo "nohup.out already deleted" diff --git a/CHANGELOG.md b/CHANGELOG.md index 0ac23dea1..515988fbc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,3 +1,14 @@ +1.0.0-b23 + +* Tune websocket echo server for performance +* Add file and line number to thrown exceptions +* Better logging in async echo server +* Add copy special members +* Fix message constructor and special members +* Travis CI improvements + +-------------------------------------------------------------------------------- + 1.0.0-b22 * Fix broken Intellisense diff --git a/include/beast/core/detail/buffer_cat.hpp b/include/beast/core/detail/buffer_cat.hpp index fdf2b6104..b94d99656 100644 --- a/include/beast/core/detail/buffer_cat.hpp +++ b/include/beast/core/detail/buffer_cat.hpp @@ -253,7 +253,8 @@ private: reference dereference(C const&) const { - throw std::logic_error("invalid iterator"); + throw detail::make_exception( + "invalid iterator", __FILE__, __LINE__); } template @@ -269,7 +270,8 @@ private: void increment(C const&) { - throw std::logic_error("invalid iterator"); + throw detail::make_exception( + "invalid iterator", __FILE__, __LINE__); } template @@ -310,7 +312,8 @@ private: --iter(); return; } - throw std::logic_error("invalid iterator"); + throw detail::make_exception( + "invalid iterator", __FILE__, __LINE__); } template diff --git a/include/beast/core/detail/type_traits.hpp b/include/beast/core/detail/type_traits.hpp index 24928abdd..f50b3a3c0 100644 --- a/include/beast/core/detail/type_traits.hpp +++ b/include/beast/core/detail/type_traits.hpp @@ -10,6 +10,8 @@ #include #include +#include +#include namespace beast { namespace detail { @@ -78,6 +80,18 @@ struct repeat_tuple<0, T> using type = std::tuple<>; }; +template +Exception +make_exception(char const* reason, char const* file, int line) +{ + char const* n = file; + for(auto p = file; *p; ++p) + if(*p == '\\' || *p == '/') + n = p + 1; + return Exception{std::string(reason) + " (" + + n + ":" + std::to_string(line) + ")"}; +} + } // detail } // beast diff --git a/include/beast/core/impl/basic_streambuf.ipp b/include/beast/core/impl/basic_streambuf.ipp index c70d646bb..a3fdcef70 100644 --- a/include/beast/core/impl/basic_streambuf.ipp +++ b/include/beast/core/impl/basic_streambuf.ipp @@ -524,8 +524,8 @@ basic_streambuf::basic_streambuf( , alloc_size_(alloc_size) { if(alloc_size <= 0) - throw std::invalid_argument( - "basic_streambuf: invalid alloc_size"); + throw detail::make_exception( + "invalid alloc_size", __FILE__, __LINE__); } template diff --git a/include/beast/core/impl/buffers_adapter.ipp b/include/beast/core/impl/buffers_adapter.ipp index cf537d6e4..309830f1e 100644 --- a/include/beast/core/impl/buffers_adapter.ipp +++ b/include/beast/core/impl/buffers_adapter.ipp @@ -8,6 +8,7 @@ #ifndef BEAST_IMPL_BUFFERS_ADAPTER_IPP #define BEAST_IMPL_BUFFERS_ADAPTER_IPP +#include #include #include #include @@ -413,8 +414,8 @@ buffers_adapter::prepare(std::size_t n) -> } } if(n > 0) - throw std::length_error( - "no space in buffers_adapter"); + throw detail::make_exception( + "no space", __FILE__, __LINE__); return mutable_buffers_type{*this}; } diff --git a/include/beast/core/impl/static_streambuf.ipp b/include/beast/core/impl/static_streambuf.ipp index 3f19cd7e1..44c4e2610 100644 --- a/include/beast/core/impl/static_streambuf.ipp +++ b/include/beast/core/impl/static_streambuf.ipp @@ -8,6 +8,7 @@ #ifndef BEAST_IMPL_STATIC_STREAMBUF_IPP #define BEAST_IMPL_STATIC_STREAMBUF_IPP +#include #include #include #include @@ -295,7 +296,8 @@ static_streambuf::prepare(std::size_t n) -> mutable_buffers_type { if(n > static_cast(end_ - out_)) - throw std::length_error("no space in streambuf"); + throw detail::make_exception( + "no space in streambuf", __FILE__, __LINE__); last_ = out_ + n; return mutable_buffers_type{out_, n}; } diff --git a/include/beast/core/static_string.hpp b/include/beast/core/static_string.hpp index a3ec8919d..6a9ef1e6a 100644 --- a/include/beast/core/static_string.hpp +++ b/include/beast/core/static_string.hpp @@ -8,6 +8,7 @@ #ifndef BEAST_WEBSOCKET_STATIC_STRING_HPP #define BEAST_WEBSOCKET_STATIC_STRING_HPP +#include #include #include #include @@ -329,7 +330,8 @@ static_string:: static_string(static_string const& s) { if(s.size() > N) - throw std::length_error("static_string overflow"); + throw detail::make_exception( + "static_string overflow", __FILE__, __LINE__); n_ = s.size(); Traits::copy(&s_[0], &s.s_[0], n_ + 1); } @@ -353,7 +355,8 @@ operator=(static_string const& s) -> static_string& { if(s.size() > N) - throw std::length_error("static_string overflow"); + throw detail::make_exception( + "static_string overflow", __FILE__, __LINE__); n_ = s.size(); Traits::copy(&s_[0], &s.s_[0], n_ + 1); return *this; @@ -391,7 +394,8 @@ at(size_type pos) -> reference { if(pos >= n_) - throw std::out_of_range("static_string::at"); + throw detail::make_exception( + "invalid pos", __FILE__, __LINE__); return s_[pos]; } @@ -402,7 +406,8 @@ at(size_type pos) const -> const_reference { if(pos >= n_) - throw std::out_of_range("static_string::at"); + throw detail::make_exception( + "static_string::at", __FILE__, __LINE__); return s_[pos]; } @@ -412,7 +417,8 @@ static_string:: resize(std::size_t n) { if(n > N) - throw std::length_error("static_string overflow"); + throw detail::make_exception( + "static_string overflow", __FILE__, __LINE__); n_ = n; s_[n_] = 0; } @@ -423,7 +429,8 @@ static_string:: resize(std::size_t n, CharT c) { if(n > N) - throw std::length_error("static_string overflow"); + throw detail::make_exception( + "static_string overflow", __FILE__, __LINE__); if(n > n_) Traits::assign(&s_[n_], n - n_, c); n_ = n; @@ -462,7 +469,8 @@ assign(CharT const* s) { auto const n = Traits::length(s); if(n > N) - throw std::out_of_range("too large"); + throw detail::make_exception( + "too large", __FILE__, __LINE__); n_ = n; Traits::copy(&s_[0], s, n_ + 1); } diff --git a/include/beast/http/impl/message.ipp b/include/beast/http/impl/message.ipp index 9a818cd87..3f7c05650 100644 --- a/include/beast/http/impl/message.ipp +++ b/include/beast/http/impl/message.ipp @@ -159,6 +159,8 @@ void prepare(message& msg, Options&&... options) { + using beast::detail::make_exception; + // VFALCO TODO static_assert(is_Body::value, "Body requirements not met"); @@ -174,16 +176,16 @@ prepare(message& msg, std::forward(options)...); if(msg.fields.exists("Connection")) - throw std::invalid_argument( - "prepare called with Connection field set"); + throw make_exception( + "prepare called with Connection field set", __FILE__, __LINE__); if(msg.fields.exists("Content-Length")) - throw std::invalid_argument( - "prepare called with Content-Length field set"); + throw make_exception( + "prepare called with Content-Length field set", __FILE__, __LINE__); if(token_list{msg.fields["Transfer-Encoding"]}.exists("chunked")) - throw std::invalid_argument( - "prepare called with Transfer-Encoding: chunked set"); + throw make_exception( + "prepare called with Transfer-Encoding: chunked set", __FILE__, __LINE__); if(pi.connection_value != connection::upgrade) { @@ -254,8 +256,8 @@ prepare(message& msg, // rfc7230 6.7. if(msg.version < 11 && token_list{ msg.fields["Connection"]}.exists("upgrade")) - throw std::invalid_argument( - "invalid version for Connection: upgrade"); + throw make_exception( + "invalid version for Connection: upgrade", __FILE__, __LINE__); } } // http diff --git a/include/beast/http/message.hpp b/include/beast/http/message.hpp index ebe172384..007b48746 100644 --- a/include/beast/http/message.hpp +++ b/include/beast/http/message.hpp @@ -246,6 +246,18 @@ struct message : header /// Default constructor message() = default; + /// Move constructor + message(message&&) = default; + + /// Copy constructor + message(message const&) = default; + + /// Move assignment + message& operator=(message&&) = default; + + /// Copy assignment + message& operator=(message const&) = default; + /** Construct a message from a header. Additional arguments, if any, are forwarded to @@ -281,8 +293,9 @@ struct message : header */ template::type, base_type>::value> + , class = typename std::enable_if< + ! std::is_convertible::type, base_type>::value>::type #endif > explicit @@ -303,7 +316,7 @@ struct message : header template::type, base_type>::value> + typename std::decay::type, base_type>::value>::type #endif > message(U&& u, V&& v) diff --git a/include/beast/version.hpp b/include/beast/version.hpp index 7d02e3293..cc71abf07 100644 --- a/include/beast/version.hpp +++ b/include/beast/version.hpp @@ -16,6 +16,6 @@ // #define BEAST_VERSION 100000 -#define BEAST_VERSION_STRING "1.0.0-b22" +#define BEAST_VERSION_STRING "1.0.0-b23" #endif diff --git a/include/beast/websocket/impl/stream.ipp b/include/beast/websocket/impl/stream.ipp index bd04db45a..2e4192498 100644 --- a/include/beast/websocket/impl/stream.ipp +++ b/include/beast/websocket/impl/stream.ipp @@ -20,6 +20,7 @@ #include #include #include +#include #include #include #include diff --git a/include/beast/websocket/option.hpp b/include/beast/websocket/option.hpp index d2864cdd2..4f009f969 100644 --- a/include/beast/websocket/option.hpp +++ b/include/beast/websocket/option.hpp @@ -10,6 +10,7 @@ #include #include +#include #include #include #include @@ -186,7 +187,8 @@ struct message_type message_type(opcode op) { if(op != opcode::binary && op != opcode::text) - throw std::domain_error("bad opcode"); + throw beast::detail::make_exception( + "bad opcode", __FILE__, __LINE__); value = op; } }; @@ -277,6 +279,9 @@ struct read_buffer_size read_buffer_size(std::size_t n) : value(n) { + if(n < 8) + throw beast::detail::make_exception( + "read buffer size is too small", __FILE__, __LINE__); } }; #endif @@ -356,7 +361,8 @@ struct write_buffer_size : value(n) { if(n < 8) - throw std::domain_error("write buffer size is too small"); + throw beast::detail::make_exception( + "write buffer size is too small", __FILE__, __LINE__); } }; #endif diff --git a/include/beast/zlib/detail/deflate_stream.hpp b/include/beast/zlib/detail/deflate_stream.hpp index 7b367d3e4..45dbdb98b 100644 --- a/include/beast/zlib/detail/deflate_stream.hpp +++ b/include/beast/zlib/detail/deflate_stream.hpp @@ -37,6 +37,7 @@ #include #include +#include #include #include #include @@ -893,14 +894,19 @@ doReset( if(windowBits == 8) windowBits = 9; + using beast::detail::make_exception; + if(level < 0 || level > 9) - throw std::invalid_argument{"invalid level"}; + throw make_exception( + "invalid level", __FILE__, __LINE__); if(windowBits < 8 || windowBits > 15) - throw std::invalid_argument{"invalid windowBits"}; + throw make_exception( + "invalid windowBits", __FILE__, __LINE__); if(memLevel < 1 || memLevel > MAX_MEM_LEVEL) - throw std::invalid_argument{"invalid memLevel"}; + throw make_exception( + "invalid memLevel", __FILE__, __LINE__); w_bits_ = windowBits; diff --git a/include/beast/zlib/detail/inflate_stream.hpp b/include/beast/zlib/detail/inflate_stream.hpp index c13d9428c..5b748fbe3 100644 --- a/include/beast/zlib/detail/inflate_stream.hpp +++ b/include/beast/zlib/detail/inflate_stream.hpp @@ -40,6 +40,7 @@ #include #include #include +#include #include #include #include @@ -232,7 +233,8 @@ inflate_stream:: doReset(int windowBits) { if(windowBits < 8 || windowBits > 15) - throw std::domain_error("windowBits out of range"); + throw beast::detail::make_exception( + "windowBits out of range", __FILE__, __LINE__); w_.reset(windowBits); bi_.flush(); @@ -706,7 +708,8 @@ doWrite(z_params& zs, Flush flush, error_code& ec) case SYNC: default: - throw std::logic_error("stream error"); + throw beast::detail::make_exception( + "stream error", __FILE__, __LINE__); } } } @@ -932,8 +935,8 @@ inflate_table( auto const not_enough = [] { - throw std::logic_error( - "insufficient output size when inflating tables"); + throw beast::detail::make_exception( + "insufficient output size when inflating tables", __FILE__, __LINE__); }; // check available table space diff --git a/scripts/build-and-test.sh b/scripts/build-and-test.sh index 3c8ed47ef..e62e93aa8 100755 --- a/scripts/build-and-test.sh +++ b/scripts/build-and-test.sh @@ -40,6 +40,9 @@ elif [[ $(uname -s) == "Linux" ]]; then if ((${num_proc_units} < ${num_jobs})); then num_jobs=$num_proc_units fi + if [[ "${TRAVIS}" == "true" && ${NUM_PROCESSORS:=2} > ${num_jobs} ]]; then + num_jobs=$NUM_PROCESSORS + fi fi echo "using toolset: $CC" @@ -99,10 +102,10 @@ function run_autobahn_test_suite { # We need to wait a while so wstest can connect! sleep 5 + # Show the output (if any) as it is generated + tail -f nohup.out & cd scripts && wstest -m fuzzingclient cd .. - # Show the output - cat nohup.out rm nohup.out # Show what jobs are running jobs @@ -110,6 +113,7 @@ function run_autobahn_test_suite { sleep 5 # Kill it gracefully kill -INT %1 + kill -INT %2 # Wait for all the jobs to finish wait # Parse the test results, with python>=2.5<3 script @@ -135,9 +139,10 @@ if [[ $VARIANT == "coverage" ]]; then # Perform test if [[ $MAIN_BRANCH == "1" ]]; then run_tests_with_valgrind - run_autobahn_test_suite + # skip slow autobahn tests + #run_autobahn_test_suite else - echo "skipping autobahn tests for feature branch build" + echo "skipping autobahn/valgrind tests for feature branch build" run_tests fi diff --git a/test/http/message.cpp b/test/http/message.cpp index d5db86e08..47216b236 100644 --- a/test/http/message.cpp +++ b/test/http/message.cpp @@ -278,6 +278,19 @@ public: BEAST_EXPECT(m2.fields.exists("h")); } + void + testSpecialMembers() + { + response r1; + response r2{r1}; + response r3{std::move(r2)}; + r2 = r3; + r1 = std::move(r2); + [r1]() + { + }(); + } + void run() override { testMessage(); @@ -285,6 +298,7 @@ public: testFreeFunctions(); testPrepare(); testSwap(); + testSpecialMembers(); } }; diff --git a/test/websocket/stream.cpp b/test/websocket/stream.cpp index 084019ebe..53a16bdd9 100644 --- a/test/websocket/stream.cpp +++ b/test/websocket/stream.cpp @@ -1416,7 +1416,10 @@ public: yield_to_mf(ep, &stream_test::testAsyncClient); } { - async_echo_server server(true, any, 4); + error_code ec; + async_echo_server server{nullptr, 4}; + server.open(true, any, ec); + BEAST_EXPECTS(! ec, ec.message()); auto const ep = server.local_endpoint(); testSyncClient(ep); testAsyncWriteFrame(ep); diff --git a/test/websocket/websocket_async_echo_server.hpp b/test/websocket/websocket_async_echo_server.hpp index ae4963243..0519deb20 100644 --- a/test/websocket/websocket_async_echo_server.hpp +++ b/test/websocket/websocket_async_echo_server.hpp @@ -18,6 +18,8 @@ #include #include +#include + namespace beast { namespace websocket { @@ -31,38 +33,24 @@ public: using socket_type = boost::asio::ip::tcp::socket; private: - bool log_ = false; + std::ostream* log_; boost::asio::io_service ios_; socket_type sock_; boost::asio::ip::tcp::acceptor acceptor_; std::vector thread_; + boost::optional work_; public: - async_echo_server(bool server, - endpoint_type const& ep, std::size_t threads) - : sock_(ios_) + async_echo_server(async_echo_server const&) = delete; + async_echo_server& operator=(async_echo_server const&) = delete; + + async_echo_server(std::ostream* log, + std::size_t threads) + : log_(log) + , sock_(ios_) , acceptor_(ios_) + , work_(ios_) { - if(server) - { - error_code ec; - acceptor_.open(ep.protocol(), ec); - maybe_throw(ec, "open"); - acceptor_.set_option( - boost::asio::socket_base::reuse_address{true}); - acceptor_.bind(ep, ec); - maybe_throw(ec, "bind"); - acceptor_.listen( - boost::asio::socket_base::max_connections, ec); - maybe_throw(ec, "listen"); - acceptor_.async_accept(sock_, - std::bind(&async_echo_server::on_accept, this, - beast::asio::placeholders::error)); - } - else - { - Peer{log_, std::move(sock_), ep}; - } thread_.reserve(threads); for(std::size_t i = 0; i < threads; ++i) thread_.emplace_back( @@ -71,6 +59,7 @@ public: ~async_echo_server() { + work_ = boost::none; error_code ec; ios_.dispatch( [&]{ acceptor_.close(ec); }); @@ -78,6 +67,46 @@ public: t.join(); } + void + open(bool server, + endpoint_type const& ep, error_code& ec) + { + if(server) + { + acceptor_.open(ep.protocol(), ec); + if(ec) + { + if(log_) + (*log_) << "open: " << ec.message() << std::endl; + return; + } + acceptor_.set_option( + boost::asio::socket_base::reuse_address{true}); + acceptor_.bind(ep, ec); + if(ec) + { + if(log_) + (*log_) << "bind: " << ec.message() << std::endl; + return; + } + acceptor_.listen( + boost::asio::socket_base::max_connections, ec); + if(ec) + { + if(log_) + (*log_) << "listen: " << ec.message() << std::endl; + return; + } + acceptor_.async_accept(sock_, + std::bind(&async_echo_server::on_accept, this, + beast::asio::placeholders::error)); + } + else + { + Peer{*this, std::move(sock_), ep}; + } + } + endpoint_type local_endpoint() const { @@ -89,7 +118,7 @@ private: { struct data { - bool log; + async_echo_server& server; int state = 0; boost::optional ep; stream ws; @@ -98,8 +127,9 @@ private: beast::streambuf db; int id; - data(bool log_, socket_type&& sock_) - : log(log_) + data(async_echo_server& server_, + socket_type&& sock_) + : server(server_) , ws(std::move(sock_)) , strand(ws.get_io_service()) , id([] @@ -110,9 +140,9 @@ private: { } - data(bool log_, socket_type&& sock_, - endpoint_type const& ep_) - : log(log_) + data(async_echo_server& server_, + socket_type&& sock_, endpoint_type const& ep_) + : server(server_) , ep(ep_) , ws(std::move(sock_)) , strand(ws.get_io_service()) @@ -152,14 +182,17 @@ private: template explicit - Peer(bool log, socket_type&& sock, Args&&... args) - : d_(std::make_shared(log, + Peer(async_echo_server& server, + socket_type&& sock, Args&&... args) + : d_(std::make_shared(server, std::forward(sock), std::forward(args)...)) { auto& d = *d_; d.ws.set_option(decorate(identity{})); d.ws.set_option(read_message_max(64 * 1024 * 1024)); + d.ws.set_option(auto_fragment{false}); + //d.ws.set_option(write_buffer_size{64 * 1024}); run(); } @@ -289,10 +322,10 @@ private: fail(error_code ec, std::string what) { auto& d = *d_; - if(d.log) + if(d.server.log_) { if(ec != error::closed) - std::cerr << "#" << d_->id << " " << + (*d.server.log_) << "#" << d.id << " " << what << ": " << ec.message() << std::endl; } } @@ -302,7 +335,7 @@ private: fail(error_code ec, std::string what) { if(log_) - std::cerr << what << ": " << + (*log_) << what << ": " << ec.message() << std::endl; } @@ -328,7 +361,7 @@ private: acceptor_.async_accept(sock_, std::bind(&async_echo_server::on_accept, this, beast::asio::placeholders::error)); - Peer{false, std::move(sock)}; + Peer{*this, std::move(sock)}; } }; diff --git a/test/websocket/websocket_echo.cpp b/test/websocket/websocket_echo.cpp index 636087b4c..a4ddee49c 100644 --- a/test/websocket/websocket_echo.cpp +++ b/test/websocket/websocket_echo.cpp @@ -8,17 +8,27 @@ #include "websocket_async_echo_server.hpp" #include "websocket_sync_echo_server.hpp" #include +#include int main() { using endpoint_type = boost::asio::ip::tcp::endpoint; using address_type = boost::asio::ip::address; - beast::websocket::async_echo_server s1(true, endpoint_type{ - address_type::from_string("127.0.0.1"), 6000 }, 4); + try + { + boost::system::error_code ec; + beast::websocket::async_echo_server s1{nullptr, 1}; + s1.open(true, endpoint_type{ + address_type::from_string("127.0.0.1"), 6000 }, ec); - beast::websocket::sync_echo_server s2(true, endpoint_type{ - address_type::from_string("127.0.0.1"), 6001 }); + beast::websocket::sync_echo_server s2(true, endpoint_type{ + address_type::from_string("127.0.0.1"), 6001 }); - beast::test::sig_wait(); + beast::test::sig_wait(); + } + catch(std::exception const& e) + { + std::cout << "Error: " << e.what() << std::endl; + } }