mirror of
https://github.com/boostorg/beast.git
synced 2025-07-30 21:07:26 +02:00
Fixes to support Asio changes (API Change):
This adjusts Beast's interfaces and implementation to match the changes in Boost.Asio.
This commit is contained in:
@ -84,6 +84,11 @@ add_definitions (-DBOOST_ASIO_DISABLE_BOOST_ARRAY=1)
|
|||||||
add_definitions (-DBOOST_ASIO_DISABLE_BOOST_BIND=1)
|
add_definitions (-DBOOST_ASIO_DISABLE_BOOST_BIND=1)
|
||||||
add_definitions (-DBOOST_ASIO_DISABLE_BOOST_DATE_TIME=1)
|
add_definitions (-DBOOST_ASIO_DISABLE_BOOST_DATE_TIME=1)
|
||||||
add_definitions (-DBOOST_ASIO_DISABLE_BOOST_REGEX=1)
|
add_definitions (-DBOOST_ASIO_DISABLE_BOOST_REGEX=1)
|
||||||
|
|
||||||
|
# workaround for asio defect
|
||||||
|
add_definitions (-DBOOST_ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE=1)
|
||||||
|
add_definitions (-DBOOST_ASIO_DISABLE_WINDOWS_STREAM_HANDLE=1)
|
||||||
|
|
||||||
add_definitions (-DBOOST_COROUTINES_NO_DEPRECATION_WARNING=1)
|
add_definitions (-DBOOST_COROUTINES_NO_DEPRECATION_WARNING=1)
|
||||||
|
|
||||||
include_directories (${BOOST_ROOT})
|
include_directories (${BOOST_ROOT})
|
||||||
@ -174,6 +179,9 @@ endif()
|
|||||||
|
|
||||||
include_directories (.)
|
include_directories (.)
|
||||||
|
|
||||||
|
# VFALCO FIXME Need this for recent asio changes
|
||||||
|
add_definitions (-DBOOST_BEAST_NO_FILE_BODY_WIN32=1)
|
||||||
|
|
||||||
if (OPENSSL_FOUND)
|
if (OPENSSL_FOUND)
|
||||||
include_directories (${OPENSSL_INCLUDE_DIR})
|
include_directories (${OPENSSL_INCLUDE_DIR})
|
||||||
endif()
|
endif()
|
||||||
|
8
Jamfile
8
Jamfile
@ -93,6 +93,14 @@ project /boost/beast
|
|||||||
<define>BOOST_ASIO_DISABLE_BOOST_DATE_TIME=1
|
<define>BOOST_ASIO_DISABLE_BOOST_DATE_TIME=1
|
||||||
<define>BOOST_ASIO_DISABLE_BOOST_REGEX=1
|
<define>BOOST_ASIO_DISABLE_BOOST_REGEX=1
|
||||||
<define>BOOST_COROUTINES_NO_DEPRECATION_WARNING=1
|
<define>BOOST_COROUTINES_NO_DEPRECATION_WARNING=1
|
||||||
|
|
||||||
|
# workaround for asio defect
|
||||||
|
<define>BOOST_ASIO_DISABLE_WINDOWS_RANDOM_ACCESS_HANDLE=1
|
||||||
|
<define>BOOST_ASIO_DISABLE_WINDOWS_STREAM_HANDLE=1
|
||||||
|
|
||||||
|
# VFALCO FIXME Need this for recent asio changes
|
||||||
|
<define>BOOST_BEAST_NO_FILE_BODY_WIN32=1
|
||||||
|
|
||||||
<toolset>msvc:<cxxflags>"/bigobj"
|
<toolset>msvc:<cxxflags>"/bigobj"
|
||||||
<toolset>msvc-14.1:<cxxflags>"/permissive-"
|
<toolset>msvc-14.1:<cxxflags>"/permissive-"
|
||||||
<toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS=1
|
<toolset>msvc:<define>_SCL_SECURE_NO_WARNINGS=1
|
||||||
|
@ -331,27 +331,26 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Handles a plain WebSocket connection
|
// Handles a plain WebSocket connection
|
||||||
class plain_websocket_session
|
class plain_websocket_session
|
||||||
: public websocket_session<plain_websocket_session>
|
: public websocket_session<plain_websocket_session>
|
||||||
, public std::enable_shared_from_this<plain_websocket_session>
|
, public std::enable_shared_from_this<plain_websocket_session>
|
||||||
{
|
{
|
||||||
websocket::stream<
|
websocket::stream<beast::tcp_stream> ws_;
|
||||||
beast::tcp_stream<net::io_context::strand>> ws_;
|
|
||||||
bool close_ = false;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Create the session
|
// Create the session
|
||||||
explicit
|
explicit
|
||||||
plain_websocket_session(
|
plain_websocket_session(
|
||||||
beast::tcp_stream<net::io_context::strand>&& stream)
|
beast::tcp_stream&& stream)
|
||||||
: ws_(std::move(stream))
|
: ws_(std::move(stream))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called by the base class
|
// Called by the base class
|
||||||
websocket::stream<
|
websocket::stream<beast::tcp_stream>&
|
||||||
beast::tcp_stream<net::io_context::strand>>&
|
|
||||||
ws()
|
ws()
|
||||||
{
|
{
|
||||||
return ws_;
|
return ws_;
|
||||||
@ -365,48 +364,28 @@ public:
|
|||||||
// Accept the WebSocket upgrade request
|
// Accept the WebSocket upgrade request
|
||||||
do_accept(std::move(req));
|
do_accept(std::move(req));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
on_close(beast::error_code ec)
|
|
||||||
{
|
|
||||||
// Happens when close times out
|
|
||||||
if(ec == net::error::operation_aborted)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(ec)
|
|
||||||
return fail(ec, "close");
|
|
||||||
|
|
||||||
// At this point the connection is gracefully closed
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Handles an SSL WebSocket connection
|
// Handles an SSL WebSocket connection
|
||||||
class ssl_websocket_session
|
class ssl_websocket_session
|
||||||
: public websocket_session<ssl_websocket_session>
|
: public websocket_session<ssl_websocket_session>
|
||||||
, public std::enable_shared_from_this<ssl_websocket_session>
|
, public std::enable_shared_from_this<ssl_websocket_session>
|
||||||
{
|
{
|
||||||
websocket::stream<beast::ssl_stream<
|
websocket::stream<
|
||||||
beast::tcp_stream<net::io_context::strand>>> ws_;
|
beast::ssl_stream<beast::tcp_stream>> ws_;
|
||||||
bool eof_ = false;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Create the http_session
|
// Create the ssl_websocket_session
|
||||||
explicit
|
explicit
|
||||||
ssl_websocket_session(beast::ssl_stream<
|
ssl_websocket_session(
|
||||||
beast::tcp_stream<net::io_context::strand>>&& stream)
|
beast::ssl_stream<beast::tcp_stream>&& stream)
|
||||||
: ws_(std::move(stream))
|
: ws_(std::move(stream))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called by the base class
|
// Start the session
|
||||||
websocket::stream<beast::ssl_stream<
|
|
||||||
beast::tcp_stream<net::io_context::strand>>>&
|
|
||||||
ws()
|
|
||||||
{
|
|
||||||
return ws_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start the asynchronous operation
|
|
||||||
template<class Body, class Allocator>
|
template<class Body, class Allocator>
|
||||||
void
|
void
|
||||||
run(http::request<Body, http::basic_fields<Allocator>> req)
|
run(http::request<Body, http::basic_fields<Allocator>> req)
|
||||||
@ -415,18 +394,15 @@ public:
|
|||||||
do_accept(std::move(req));
|
do_accept(std::move(req));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
// Called by the base class
|
||||||
do_eof()
|
websocket::stream<
|
||||||
|
beast::ssl_stream<beast::tcp_stream>>&
|
||||||
|
ws()
|
||||||
{
|
{
|
||||||
eof_ = true;
|
return ws_;
|
||||||
|
|
||||||
// Perform the SSL shutdown
|
|
||||||
ws_.next_layer().async_shutdown(
|
|
||||||
beast::bind_front_handler(
|
|
||||||
&ssl_websocket_session::on_shutdown,
|
|
||||||
shared_from_this()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
void
|
void
|
||||||
on_shutdown(beast::error_code ec)
|
on_shutdown(beast::error_code ec)
|
||||||
{
|
{
|
||||||
@ -437,10 +413,12 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class Body, class Allocator>
|
template<class Body, class Allocator>
|
||||||
void
|
void
|
||||||
make_websocket_session(
|
make_websocket_session(
|
||||||
beast::tcp_stream<net::io_context::strand> stream,
|
beast::tcp_stream stream,
|
||||||
http::request<Body, http::basic_fields<Allocator>> req)
|
http::request<Body, http::basic_fields<Allocator>> req)
|
||||||
{
|
{
|
||||||
std::make_shared<plain_websocket_session>(
|
std::make_shared<plain_websocket_session>(
|
||||||
@ -450,7 +428,7 @@ make_websocket_session(
|
|||||||
template<class Body, class Allocator>
|
template<class Body, class Allocator>
|
||||||
void
|
void
|
||||||
make_websocket_session(
|
make_websocket_session(
|
||||||
beast::ssl_stream<beast::tcp_stream<net::io_context::strand>> stream,
|
beast::ssl_stream<beast::tcp_stream> stream,
|
||||||
http::request<Body, http::basic_fields<Allocator>> req)
|
http::request<Body, http::basic_fields<Allocator>> req)
|
||||||
{
|
{
|
||||||
std::make_shared<ssl_websocket_session>(
|
std::make_shared<ssl_websocket_session>(
|
||||||
@ -568,19 +546,15 @@ class http_session
|
|||||||
queue queue_;
|
queue queue_;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
net::steady_timer timer_;
|
|
||||||
beast::flat_buffer buffer_;
|
beast::flat_buffer buffer_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Construct the session
|
// Construct the session
|
||||||
http_session(
|
http_session(
|
||||||
net::io_context& ioc,
|
|
||||||
beast::flat_buffer buffer,
|
beast::flat_buffer buffer,
|
||||||
std::shared_ptr<std::string const> const& doc_root)
|
std::shared_ptr<std::string const> const& doc_root)
|
||||||
: doc_root_(doc_root)
|
: doc_root_(doc_root)
|
||||||
, queue_(*this)
|
, queue_(*this)
|
||||||
, timer_(ioc,
|
|
||||||
(std::chrono::steady_clock::time_point::max)())
|
|
||||||
, buffer_(std::move(buffer))
|
, buffer_(std::move(buffer))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -621,7 +595,11 @@ public:
|
|||||||
// See if it is a WebSocket Upgrade
|
// See if it is a WebSocket Upgrade
|
||||||
if(websocket::is_upgrade(req_))
|
if(websocket::is_upgrade(req_))
|
||||||
{
|
{
|
||||||
// Transfer the stream to a new WebSocket session
|
// Disable the timeout.
|
||||||
|
// The websocket::stream uses its own timeout settings.
|
||||||
|
beast::get_lowest_layer(derived().stream()).expires_never();
|
||||||
|
|
||||||
|
// Transfer the stream to a new WebSocket session.
|
||||||
return make_websocket_session(
|
return make_websocket_session(
|
||||||
derived().release_stream(),
|
derived().release_stream(),
|
||||||
std::move(req_));
|
std::move(req_));
|
||||||
@ -663,56 +641,50 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Handles a plain HTTP connection
|
// Handles a plain HTTP connection
|
||||||
class plain_http_session
|
class plain_http_session
|
||||||
: public http_session<plain_http_session>
|
: public http_session<plain_http_session>
|
||||||
, public std::enable_shared_from_this<plain_http_session>
|
, public std::enable_shared_from_this<plain_http_session>
|
||||||
{
|
{
|
||||||
beast::tcp_stream<net::io_context::strand> stream_;
|
beast::tcp_stream stream_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Create the http_session
|
// Create the session
|
||||||
plain_http_session(
|
plain_http_session(
|
||||||
beast::tcp_stream<net::io_context::strand>&& stream,
|
beast::tcp_stream&& stream,
|
||||||
beast::flat_buffer&& buffer,
|
beast::flat_buffer&& buffer,
|
||||||
std::shared_ptr<std::string const> const& doc_root)
|
std::shared_ptr<std::string const> const& doc_root)
|
||||||
: http_session<plain_http_session>(
|
: http_session<plain_http_session>(
|
||||||
stream.get_executor().context(),
|
|
||||||
std::move(buffer),
|
std::move(buffer),
|
||||||
doc_root)
|
doc_root)
|
||||||
, stream_(std::move(stream))
|
, stream_(std::move(stream))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Start the session
|
||||||
|
void
|
||||||
|
run()
|
||||||
|
{
|
||||||
|
this->do_read();
|
||||||
|
}
|
||||||
|
|
||||||
// Called by the base class
|
// Called by the base class
|
||||||
beast::tcp_stream<net::io_context::strand>&
|
beast::tcp_stream&
|
||||||
stream()
|
stream()
|
||||||
{
|
{
|
||||||
return stream_;
|
return stream_;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called by the base class
|
// Called by the base class
|
||||||
beast::tcp_stream<net::io_context::strand>
|
beast::tcp_stream
|
||||||
release_stream()
|
release_stream()
|
||||||
{
|
{
|
||||||
return std::move(stream_);
|
return std::move(stream_);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the asynchronous operation
|
// Called by the base class
|
||||||
void
|
|
||||||
run()
|
|
||||||
{
|
|
||||||
// Make sure we run on the strand
|
|
||||||
if(! stream_.get_executor().running_in_this_thread())
|
|
||||||
return net::post(
|
|
||||||
stream_.get_executor(),
|
|
||||||
beast::bind_front_handler(
|
|
||||||
&plain_http_session::run,
|
|
||||||
shared_from_this()));
|
|
||||||
|
|
||||||
do_read();
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
do_eof()
|
do_eof()
|
||||||
{
|
{
|
||||||
@ -722,70 +694,35 @@ public:
|
|||||||
|
|
||||||
// At this point the connection is closed gracefully
|
// At this point the connection is closed gracefully
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
do_timeout()
|
|
||||||
{
|
|
||||||
// Closing the socket cancels all outstanding operations. They
|
|
||||||
// will complete with net::error::operation_aborted
|
|
||||||
beast::error_code ec;
|
|
||||||
stream_.socket().shutdown(tcp::socket::shutdown_both, ec);
|
|
||||||
stream_.socket().close(ec);
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// Handles an SSL HTTP connection
|
// Handles an SSL HTTP connection
|
||||||
class ssl_http_session
|
class ssl_http_session
|
||||||
: public http_session<ssl_http_session>
|
: public http_session<ssl_http_session>
|
||||||
, public std::enable_shared_from_this<ssl_http_session>
|
, public std::enable_shared_from_this<ssl_http_session>
|
||||||
{
|
{
|
||||||
beast::ssl_stream<
|
beast::ssl_stream<beast::tcp_stream> stream_;
|
||||||
beast::tcp_stream<net::io_context::strand>> stream_;
|
|
||||||
bool eof_ = false;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Create the http_session
|
// Create the http_session
|
||||||
ssl_http_session(
|
ssl_http_session(
|
||||||
beast::tcp_stream<net::io_context::strand>&& stream,
|
beast::tcp_stream&& stream,
|
||||||
ssl::context& ctx,
|
ssl::context& ctx,
|
||||||
beast::flat_buffer&& buffer,
|
beast::flat_buffer&& buffer,
|
||||||
std::shared_ptr<std::string const> const& doc_root)
|
std::shared_ptr<std::string const> const& doc_root)
|
||||||
: http_session<ssl_http_session>(
|
: http_session<ssl_http_session>(
|
||||||
stream.get_executor().context(),
|
|
||||||
std::move(buffer),
|
std::move(buffer),
|
||||||
doc_root)
|
doc_root)
|
||||||
, stream_(std::move(stream), ctx)
|
, stream_(std::move(stream), ctx)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Called by the base class
|
// Start the session
|
||||||
beast::ssl_stream<
|
|
||||||
beast::tcp_stream<net::io_context::strand>>&
|
|
||||||
stream()
|
|
||||||
{
|
|
||||||
return stream_;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Called by the base class
|
|
||||||
beast::ssl_stream<
|
|
||||||
beast::tcp_stream<net::io_context::strand>>
|
|
||||||
release_stream()
|
|
||||||
{
|
|
||||||
return std::move(stream_);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Start the asynchronous operation
|
|
||||||
void
|
void
|
||||||
run()
|
run()
|
||||||
{
|
{
|
||||||
// Make sure we run on the strand
|
|
||||||
if(! stream_.get_executor().running_in_this_thread())
|
|
||||||
return net::post(
|
|
||||||
stream_.get_executor(),
|
|
||||||
beast::bind_front_handler(
|
|
||||||
&ssl_http_session::run,
|
|
||||||
shared_from_this()));
|
|
||||||
|
|
||||||
// Set the timeout.
|
// Set the timeout.
|
||||||
beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
|
beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
|
||||||
|
|
||||||
@ -798,6 +735,36 @@ public:
|
|||||||
&ssl_http_session::on_handshake,
|
&ssl_http_session::on_handshake,
|
||||||
shared_from_this()));
|
shared_from_this()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Called by the base class
|
||||||
|
beast::ssl_stream<beast::tcp_stream>&
|
||||||
|
stream()
|
||||||
|
{
|
||||||
|
return stream_;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by the base class
|
||||||
|
beast::ssl_stream<beast::tcp_stream>
|
||||||
|
release_stream()
|
||||||
|
{
|
||||||
|
return std::move(stream_);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Called by the base class
|
||||||
|
void
|
||||||
|
do_eof()
|
||||||
|
{
|
||||||
|
// Set the timeout.
|
||||||
|
beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
|
||||||
|
|
||||||
|
// Perform the SSL shutdown
|
||||||
|
stream_.async_shutdown(
|
||||||
|
beast::bind_front_handler(
|
||||||
|
&ssl_http_session::on_shutdown,
|
||||||
|
shared_from_this()));
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
void
|
void
|
||||||
on_handshake(
|
on_handshake(
|
||||||
beast::error_code ec,
|
beast::error_code ec,
|
||||||
@ -812,21 +779,6 @@ public:
|
|||||||
do_read();
|
do_read();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
do_eof()
|
|
||||||
{
|
|
||||||
eof_ = true;
|
|
||||||
|
|
||||||
// Set the timeout.
|
|
||||||
beast::get_lowest_layer(stream_).expires_after(std::chrono::seconds(30));
|
|
||||||
|
|
||||||
// Perform the SSL shutdown
|
|
||||||
stream_.async_shutdown(
|
|
||||||
beast::bind_front_handler(
|
|
||||||
&ssl_http_session::on_shutdown,
|
|
||||||
shared_from_this()));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
on_shutdown(beast::error_code ec)
|
on_shutdown(beast::error_code ec)
|
||||||
{
|
{
|
||||||
@ -846,7 +798,7 @@ public:
|
|||||||
// Detects SSL handshakes
|
// Detects SSL handshakes
|
||||||
class detect_session : public std::enable_shared_from_this<detect_session>
|
class detect_session : public std::enable_shared_from_this<detect_session>
|
||||||
{
|
{
|
||||||
beast::tcp_stream<net::io_context::strand> stream_;
|
beast::tcp_stream stream_;
|
||||||
ssl::context& ctx_;
|
ssl::context& ctx_;
|
||||||
std::shared_ptr<std::string const> doc_root_;
|
std::shared_ptr<std::string const> doc_root_;
|
||||||
beast::flat_buffer buffer_;
|
beast::flat_buffer buffer_;
|
||||||
@ -854,7 +806,7 @@ class detect_session : public std::enable_shared_from_this<detect_session>
|
|||||||
public:
|
public:
|
||||||
explicit
|
explicit
|
||||||
detect_session(
|
detect_session(
|
||||||
tcp::socket socket,
|
tcp::socket&& socket,
|
||||||
ssl::context& ctx,
|
ssl::context& ctx,
|
||||||
std::shared_ptr<std::string const> const& doc_root)
|
std::shared_ptr<std::string const> const& doc_root)
|
||||||
: stream_(std::move(socket))
|
: stream_(std::move(socket))
|
||||||
@ -906,8 +858,10 @@ public:
|
|||||||
// Accepts incoming connections and launches the sessions
|
// Accepts incoming connections and launches the sessions
|
||||||
class listener : public std::enable_shared_from_this<listener>
|
class listener : public std::enable_shared_from_this<listener>
|
||||||
{
|
{
|
||||||
|
net::io_context& ioc_;
|
||||||
ssl::context& ctx_;
|
ssl::context& ctx_;
|
||||||
tcp::acceptor acceptor_;
|
tcp::acceptor acceptor_;
|
||||||
|
tcp::socket socket_;
|
||||||
std::shared_ptr<std::string const> doc_root_;
|
std::shared_ptr<std::string const> doc_root_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -916,8 +870,10 @@ public:
|
|||||||
ssl::context& ctx,
|
ssl::context& ctx,
|
||||||
tcp::endpoint endpoint,
|
tcp::endpoint endpoint,
|
||||||
std::shared_ptr<std::string const> const& doc_root)
|
std::shared_ptr<std::string const> const& doc_root)
|
||||||
: ctx_(ctx)
|
: ioc_(ioc)
|
||||||
, acceptor_(ioc)
|
, ctx_(ctx)
|
||||||
|
, acceptor_(beast::make_strand(ioc))
|
||||||
|
, socket_(beast::make_strand(ioc))
|
||||||
, doc_root_(doc_root)
|
, doc_root_(doc_root)
|
||||||
{
|
{
|
||||||
beast::error_code ec;
|
beast::error_code ec;
|
||||||
@ -969,13 +925,14 @@ public:
|
|||||||
do_accept()
|
do_accept()
|
||||||
{
|
{
|
||||||
acceptor_.async_accept(
|
acceptor_.async_accept(
|
||||||
|
socket_,
|
||||||
beast::bind_front_handler(
|
beast::bind_front_handler(
|
||||||
&listener::on_accept,
|
&listener::on_accept,
|
||||||
shared_from_this()));
|
shared_from_this()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
on_accept(beast::error_code ec, tcp::socket socket)
|
on_accept(beast::error_code ec)
|
||||||
{
|
{
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
@ -985,11 +942,14 @@ public:
|
|||||||
{
|
{
|
||||||
// Create the detector http_session and run it
|
// Create the detector http_session and run it
|
||||||
std::make_shared<detect_session>(
|
std::make_shared<detect_session>(
|
||||||
std::move(socket),
|
std::move(socket_),
|
||||||
ctx_,
|
ctx_,
|
||||||
doc_root_)->run();
|
doc_root_)->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure each session gets its own strand
|
||||||
|
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||||
|
|
||||||
// Accept another connection
|
// Accept another connection
|
||||||
do_accept();
|
do_accept();
|
||||||
}
|
}
|
||||||
|
@ -219,14 +219,13 @@ fail(beast::error_code ec, char const* what)
|
|||||||
// Echoes back all received WebSocket messages
|
// Echoes back all received WebSocket messages
|
||||||
class websocket_session : public std::enable_shared_from_this<websocket_session>
|
class websocket_session : public std::enable_shared_from_this<websocket_session>
|
||||||
{
|
{
|
||||||
websocket::stream<beast::tcp_stream<net::io_context::strand>> ws_;
|
websocket::stream<beast::tcp_stream> ws_;
|
||||||
beast::flat_buffer buffer_;
|
beast::flat_buffer buffer_;
|
||||||
char ping_state_ = 0;
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Take ownership of the socket
|
// Take ownership of the socket
|
||||||
explicit
|
explicit
|
||||||
websocket_session(tcp::socket socket)
|
websocket_session(tcp::socket&& socket)
|
||||||
: ws_(std::move(socket))
|
: ws_(std::move(socket))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -258,6 +257,7 @@ public:
|
|||||||
shared_from_this()));
|
shared_from_this()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
void
|
void
|
||||||
on_accept(beast::error_code ec)
|
on_accept(beast::error_code ec)
|
||||||
{
|
{
|
||||||
@ -413,7 +413,7 @@ class http_session : public std::enable_shared_from_this<http_session>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
beast::tcp_stream<net::io_context::strand> stream_;
|
beast::tcp_stream stream_;
|
||||||
beast::flat_buffer buffer_;
|
beast::flat_buffer buffer_;
|
||||||
std::shared_ptr<std::string const> doc_root_;
|
std::shared_ptr<std::string const> doc_root_;
|
||||||
http::request<http::string_body> req_;
|
http::request<http::string_body> req_;
|
||||||
@ -421,9 +421,8 @@ class http_session : public std::enable_shared_from_this<http_session>
|
|||||||
|
|
||||||
public:
|
public:
|
||||||
// Take ownership of the socket
|
// Take ownership of the socket
|
||||||
explicit
|
|
||||||
http_session(
|
http_session(
|
||||||
tcp::socket socket,
|
tcp::socket&& socket,
|
||||||
std::shared_ptr<std::string const> const& doc_root)
|
std::shared_ptr<std::string const> const& doc_root)
|
||||||
: stream_(std::move(socket))
|
: stream_(std::move(socket))
|
||||||
, doc_root_(doc_root)
|
, doc_root_(doc_root)
|
||||||
@ -431,21 +430,14 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
// Start the asynchronous operation
|
// Start the session
|
||||||
void
|
void
|
||||||
run()
|
run()
|
||||||
{
|
{
|
||||||
// Make sure we run on the strand
|
|
||||||
if(! stream_.get_executor().running_in_this_thread())
|
|
||||||
return net::post(
|
|
||||||
stream_.get_executor(),
|
|
||||||
std::bind(
|
|
||||||
&http_session::run,
|
|
||||||
shared_from_this()));
|
|
||||||
|
|
||||||
do_read();
|
do_read();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
void
|
void
|
||||||
do_read()
|
do_read()
|
||||||
{
|
{
|
||||||
@ -532,6 +524,7 @@ public:
|
|||||||
// Accepts incoming connections and launches the sessions
|
// Accepts incoming connections and launches the sessions
|
||||||
class listener : public std::enable_shared_from_this<listener>
|
class listener : public std::enable_shared_from_this<listener>
|
||||||
{
|
{
|
||||||
|
net::io_context& ioc_;
|
||||||
tcp::acceptor acceptor_;
|
tcp::acceptor acceptor_;
|
||||||
tcp::socket socket_;
|
tcp::socket socket_;
|
||||||
std::shared_ptr<std::string const> doc_root_;
|
std::shared_ptr<std::string const> doc_root_;
|
||||||
@ -541,8 +534,9 @@ public:
|
|||||||
net::io_context& ioc,
|
net::io_context& ioc,
|
||||||
tcp::endpoint endpoint,
|
tcp::endpoint endpoint,
|
||||||
std::shared_ptr<std::string const> const& doc_root)
|
std::shared_ptr<std::string const> const& doc_root)
|
||||||
: acceptor_(ioc)
|
: ioc_(ioc)
|
||||||
, socket_(ioc)
|
, acceptor_(beast::make_strand(ioc))
|
||||||
|
, socket_(beast::make_strand(ioc))
|
||||||
, doc_root_(doc_root)
|
, doc_root_(doc_root)
|
||||||
{
|
{
|
||||||
beast::error_code ec;
|
beast::error_code ec;
|
||||||
@ -594,13 +588,14 @@ public:
|
|||||||
do_accept()
|
do_accept()
|
||||||
{
|
{
|
||||||
acceptor_.async_accept(
|
acceptor_.async_accept(
|
||||||
|
socket_,
|
||||||
beast::bind_front_handler(
|
beast::bind_front_handler(
|
||||||
&listener::on_accept,
|
&listener::on_accept,
|
||||||
shared_from_this()));
|
shared_from_this()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
on_accept(beast::error_code ec, tcp::socket socket)
|
on_accept(beast::error_code ec)
|
||||||
{
|
{
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
@ -610,10 +605,13 @@ public:
|
|||||||
{
|
{
|
||||||
// Create the http session and run it
|
// Create the http session and run it
|
||||||
std::make_shared<http_session>(
|
std::make_shared<http_session>(
|
||||||
std::move(socket),
|
std::move(socket_),
|
||||||
doc_root_)->run();
|
doc_root_)->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure each session gets its own strand
|
||||||
|
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||||
|
|
||||||
// Accept another connection
|
// Accept another connection
|
||||||
do_accept();
|
do_accept();
|
||||||
}
|
}
|
||||||
|
@ -33,10 +33,6 @@ using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// The type of stream to use
|
|
||||||
using stream_type =
|
|
||||||
beast::ssl_stream<beast::tcp_stream<net::io_context::executor_type>>;
|
|
||||||
|
|
||||||
// Report a failure
|
// Report a failure
|
||||||
void
|
void
|
||||||
fail(beast::error_code ec, char const* what)
|
fail(beast::error_code ec, char const* what)
|
||||||
@ -48,17 +44,18 @@ fail(beast::error_code ec, char const* what)
|
|||||||
class session : public std::enable_shared_from_this<session>
|
class session : public std::enable_shared_from_this<session>
|
||||||
{
|
{
|
||||||
tcp::resolver resolver_;
|
tcp::resolver resolver_;
|
||||||
stream_type stream_;
|
beast::ssl_stream<beast::tcp_stream> stream_;
|
||||||
beast::flat_buffer buffer_; // (Must persist between reads)
|
beast::flat_buffer buffer_; // (Must persist between reads)
|
||||||
http::request<http::empty_body> req_;
|
http::request<http::empty_body> req_;
|
||||||
http::response<http::string_body> res_;
|
http::response<http::string_body> res_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Resolver and stream require an io_context
|
// Objects are constructed with a strand to
|
||||||
|
// ensure that handlers do not execute concurrently.
|
||||||
explicit
|
explicit
|
||||||
session(net::io_context& ioc, ssl::context& ctx)
|
session(net::io_context& ioc, ssl::context& ctx)
|
||||||
: resolver_(ioc)
|
: resolver_(beast::make_strand(ioc))
|
||||||
, stream_(ioc, ctx)
|
, stream_(beast::make_strand(ioc), ctx)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -29,9 +29,6 @@ using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// The type of stream to use
|
|
||||||
using stream_type = beast::tcp_stream<net::io_context::executor_type>;
|
|
||||||
|
|
||||||
// Report a failure
|
// Report a failure
|
||||||
void
|
void
|
||||||
fail(beast::error_code ec, char const* what)
|
fail(beast::error_code ec, char const* what)
|
||||||
@ -43,17 +40,18 @@ fail(beast::error_code ec, char const* what)
|
|||||||
class session : public std::enable_shared_from_this<session>
|
class session : public std::enable_shared_from_this<session>
|
||||||
{
|
{
|
||||||
tcp::resolver resolver_;
|
tcp::resolver resolver_;
|
||||||
stream_type stream_;
|
beast::tcp_stream stream_;
|
||||||
beast::flat_buffer buffer_; // (Must persist between reads)
|
beast::flat_buffer buffer_; // (Must persist between reads)
|
||||||
http::request<http::empty_body> req_;
|
http::request<http::empty_body> req_;
|
||||||
http::response<http::string_body> res_;
|
http::response<http::string_body> res_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Resolver and socket require an io_context
|
// Objects are constructed with a strand to
|
||||||
|
// ensure that handlers do not execute concurrently.
|
||||||
explicit
|
explicit
|
||||||
session(net::io_context& ioc)
|
session(net::io_context& ioc)
|
||||||
: resolver_(ioc)
|
: resolver_(beast::make_strand(ioc))
|
||||||
, stream_(ioc)
|
, stream_(beast::make_strand(ioc))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -33,11 +33,6 @@ using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// The type of stream to use
|
|
||||||
// Stackful coroutines are already stranded.
|
|
||||||
using stream_type =
|
|
||||||
beast::ssl_stream<beast::tcp_stream<net::io_context::executor_type>>;
|
|
||||||
|
|
||||||
// Report a failure
|
// Report a failure
|
||||||
void
|
void
|
||||||
fail(beast::error_code ec, char const* what)
|
fail(beast::error_code ec, char const* what)
|
||||||
@ -60,7 +55,7 @@ do_session(
|
|||||||
|
|
||||||
// These objects perform our I/O
|
// These objects perform our I/O
|
||||||
tcp::resolver resolver(ioc);
|
tcp::resolver resolver(ioc);
|
||||||
stream_type stream(ioc, ctx);
|
beast::ssl_stream<beast::tcp_stream> stream(ioc, ctx);
|
||||||
|
|
||||||
// Set SNI Hostname (many hosts need this to handshake successfully)
|
// Set SNI Hostname (many hosts need this to handshake successfully)
|
||||||
if(! SSL_set_tlsext_host_name(stream.native_handle(), host.c_str()))
|
if(! SSL_set_tlsext_host_name(stream.native_handle(), host.c_str()))
|
||||||
|
@ -29,10 +29,6 @@ using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// The type of stream to use.
|
|
||||||
// Stackful coroutines are already stranded.
|
|
||||||
using stream_type = beast::tcp_stream<net::io_context::executor_type>;
|
|
||||||
|
|
||||||
// Report a failure
|
// Report a failure
|
||||||
void
|
void
|
||||||
fail(beast::error_code ec, char const* what)
|
fail(beast::error_code ec, char const* what)
|
||||||
@ -53,8 +49,8 @@ do_session(
|
|||||||
beast::error_code ec;
|
beast::error_code ec;
|
||||||
|
|
||||||
// These objects perform our I/O
|
// These objects perform our I/O
|
||||||
tcp::resolver resolver{ioc};
|
tcp::resolver resolver(ioc);
|
||||||
stream_type stream(ioc);
|
beast::tcp_stream stream(ioc);
|
||||||
|
|
||||||
// Look up the domain name
|
// Look up the domain name
|
||||||
auto const results = resolver.async_resolve(host, port, yield[ec]);
|
auto const results = resolver.async_resolve(host, port, yield[ec]);
|
||||||
|
@ -151,10 +151,7 @@ class worker : public std::enable_shared_from_this<worker>
|
|||||||
|
|
||||||
crawl_report& report_;
|
crawl_report& report_;
|
||||||
tcp::resolver resolver_;
|
tcp::resolver resolver_;
|
||||||
tcp::socket socket_;
|
beast::tcp_stream stream_;
|
||||||
net::steady_timer timer_;
|
|
||||||
net::strand<
|
|
||||||
net::io_context::executor_type> strand_;
|
|
||||||
beast::flat_buffer buffer_; // (Must persist between reads)
|
beast::flat_buffer buffer_; // (Must persist between reads)
|
||||||
http::request<http::empty_body> req_;
|
http::request<http::empty_body> req_;
|
||||||
http::response<http::string_body> res_;
|
http::response<http::string_body> res_;
|
||||||
@ -167,11 +164,8 @@ public:
|
|||||||
crawl_report& report,
|
crawl_report& report,
|
||||||
net::io_context& ioc)
|
net::io_context& ioc)
|
||||||
: report_(report)
|
: report_(report)
|
||||||
, resolver_(ioc)
|
, resolver_(beast::make_strand(ioc))
|
||||||
, socket_(ioc)
|
, stream_(beast::make_strand(ioc))
|
||||||
, timer_(ioc,
|
|
||||||
(chrono::steady_clock::time_point::max)())
|
|
||||||
, strand_(ioc.get_executor())
|
|
||||||
{
|
{
|
||||||
// Set up the common fields of the request
|
// Set up the common fields of the request
|
||||||
req_.version(11);
|
req_.version(11);
|
||||||
@ -184,44 +178,9 @@ public:
|
|||||||
void
|
void
|
||||||
run()
|
run()
|
||||||
{
|
{
|
||||||
// Run the timer. The timer is operated
|
|
||||||
// continuously, this simplifies the code.
|
|
||||||
on_timer({});
|
|
||||||
|
|
||||||
do_get_host();
|
do_get_host();
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
|
||||||
on_timer(beast::error_code ec)
|
|
||||||
{
|
|
||||||
if(ec && ec != net::error::operation_aborted)
|
|
||||||
{
|
|
||||||
// Should never happen
|
|
||||||
report_.aggregate(
|
|
||||||
[](crawl_report& rep)
|
|
||||||
{
|
|
||||||
++rep.timer_failures;
|
|
||||||
});
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Verify that the timer really expired since the deadline may have moved.
|
|
||||||
if(timer_.expiry() <= chrono::steady_clock::now())
|
|
||||||
{
|
|
||||||
socket_.shutdown(tcp::socket::shutdown_both, ec);
|
|
||||||
socket_.close(ec);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Wait on the timer
|
|
||||||
timer_.async_wait(
|
|
||||||
net::bind_executor(
|
|
||||||
strand_,
|
|
||||||
beast::bind_front_handler(
|
|
||||||
&worker::on_timer,
|
|
||||||
shared_from_this())));
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
void
|
||||||
do_get_host()
|
do_get_host()
|
||||||
{
|
{
|
||||||
@ -230,27 +189,19 @@ public:
|
|||||||
|
|
||||||
// nullptr means no more work
|
// nullptr means no more work
|
||||||
if(! host)
|
if(! host)
|
||||||
{
|
|
||||||
timer_.cancel_one();
|
|
||||||
return;
|
return;
|
||||||
}
|
|
||||||
|
|
||||||
// The Host HTTP field is required
|
// The Host HTTP field is required
|
||||||
req_.set(http::field::host, host);
|
req_.set(http::field::host, host);
|
||||||
|
|
||||||
// Set the timer
|
|
||||||
timer_.expires_after(chrono::seconds(timeout));
|
|
||||||
|
|
||||||
// Set up an HTTP GET request message
|
// Set up an HTTP GET request message
|
||||||
// Look up the domain name
|
// Look up the domain name
|
||||||
resolver_.async_resolve(
|
resolver_.async_resolve(
|
||||||
host,
|
host,
|
||||||
"http",
|
"http",
|
||||||
net::bind_executor(
|
beast::bind_front_handler(
|
||||||
strand_,
|
&worker::on_resolve,
|
||||||
beast::bind_front_handler(
|
shared_from_this()));
|
||||||
&worker::on_resolve,
|
|
||||||
shared_from_this())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -268,18 +219,16 @@ public:
|
|||||||
return do_get_host();
|
return do_get_host();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the timer
|
// Set a timeout on the operation
|
||||||
timer_.expires_after(chrono::seconds(timeout));
|
stream_.expires_after(std::chrono::seconds(10));
|
||||||
|
|
||||||
// Make the connection on the IP address we get from a lookup
|
// Make the connection on the IP address we get from a lookup
|
||||||
net::async_connect(
|
beast::async_connect(
|
||||||
socket_,
|
stream_,
|
||||||
results,
|
results,
|
||||||
net::bind_executor(
|
beast::bind_front_handler(
|
||||||
strand_,
|
&worker::on_connect,
|
||||||
beast::bind_front_handler(
|
shared_from_this()));
|
||||||
&worker::on_connect,
|
|
||||||
shared_from_this())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -295,18 +244,16 @@ public:
|
|||||||
return do_get_host();
|
return do_get_host();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the timer
|
// Set a timeout on the operation
|
||||||
timer_.expires_after(chrono::seconds(timeout));
|
stream_.expires_after(std::chrono::seconds(10));
|
||||||
|
|
||||||
// Send the HTTP request to the remote host
|
// Send the HTTP request to the remote host
|
||||||
http::async_write(
|
http::async_write(
|
||||||
socket_,
|
stream_,
|
||||||
req_,
|
req_,
|
||||||
net::bind_executor(
|
beast::bind_front_handler(
|
||||||
strand_,
|
&worker::on_write,
|
||||||
beast::bind_front_handler(
|
shared_from_this()));
|
||||||
&worker::on_write,
|
|
||||||
shared_from_this())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -325,21 +272,16 @@ public:
|
|||||||
});
|
});
|
||||||
return do_get_host();
|
return do_get_host();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Set the timer
|
|
||||||
timer_.expires_after(chrono::seconds(timeout));
|
|
||||||
|
|
||||||
// Receive the HTTP response
|
// Receive the HTTP response
|
||||||
res_ = {};
|
res_ = {};
|
||||||
http::async_read(
|
http::async_read(
|
||||||
socket_,
|
stream_,
|
||||||
buffer_,
|
buffer_,
|
||||||
res_,
|
res_,
|
||||||
net::bind_executor(
|
beast::bind_front_handler(
|
||||||
strand_,
|
&worker::on_read,
|
||||||
beast::bind_front_handler(
|
shared_from_this()));
|
||||||
&worker::on_read,
|
|
||||||
shared_from_this())));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
@ -368,8 +310,8 @@ public:
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Gracefully close the socket
|
// Gracefully close the socket
|
||||||
socket_.shutdown(tcp::socket::shutdown_both, ec);
|
stream_.socket().shutdown(tcp::socket::shutdown_both, ec);
|
||||||
socket_.close(ec);
|
stream_.close();
|
||||||
|
|
||||||
// If we get here then the connection is closed gracefully
|
// If we get here then the connection is closed gracefully
|
||||||
|
|
||||||
@ -412,7 +354,7 @@ int main(int argc, char* argv[])
|
|||||||
auto const threads = std::max<int>(1, std::atoi(argv[1]));
|
auto const threads = std::max<int>(1, std::atoi(argv[1]));
|
||||||
|
|
||||||
// The io_context is required for all I/O
|
// The io_context is required for all I/O
|
||||||
net::io_context ioc{1};
|
net::io_context ioc;
|
||||||
|
|
||||||
// The work keeps io_context::run from returning
|
// The work keeps io_context::run from returning
|
||||||
auto work = net::make_work_guard(ioc);
|
auto work = net::make_work_guard(ioc);
|
||||||
|
@ -57,7 +57,7 @@ int main(int argc, char** argv)
|
|||||||
net::io_context ioc;
|
net::io_context ioc;
|
||||||
|
|
||||||
// The SSL context is required, and holds certificates
|
// The SSL context is required, and holds certificates
|
||||||
ssl::context ctx{ssl::context::sslv23_client};
|
ssl::context ctx(ssl::context::sslv23_client);
|
||||||
|
|
||||||
// This holds the root certificate used for verification
|
// This holds the root certificate used for verification
|
||||||
load_root_certificates(ctx);
|
load_root_certificates(ctx);
|
||||||
@ -66,8 +66,8 @@ int main(int argc, char** argv)
|
|||||||
ctx.set_verify_mode(ssl::verify_peer);
|
ctx.set_verify_mode(ssl::verify_peer);
|
||||||
|
|
||||||
// These objects perform our I/O
|
// These objects perform our I/O
|
||||||
tcp::resolver resolver{ioc};
|
tcp::resolver resolver(ioc);
|
||||||
beast::ssl_stream<tcp::socket> stream{ioc, ctx};
|
beast::ssl_stream<beast::tcp_stream> stream(ioc, ctx);
|
||||||
|
|
||||||
// Set SNI Hostname (many hosts need this to handshake successfully)
|
// Set SNI Hostname (many hosts need this to handshake successfully)
|
||||||
if(! SSL_set_tlsext_host_name(stream.native_handle(), host))
|
if(! SSL_set_tlsext_host_name(stream.native_handle(), host))
|
||||||
@ -80,7 +80,7 @@ int main(int argc, char** argv)
|
|||||||
auto const results = resolver.resolve(host, port);
|
auto const results = resolver.resolve(host, port);
|
||||||
|
|
||||||
// Make the connection on the IP address we get from a lookup
|
// Make the connection on the IP address we get from a lookup
|
||||||
net::connect(stream.next_layer(), results.begin(), results.end());
|
beast::connect(beast::get_lowest_layer(stream), results);
|
||||||
|
|
||||||
// Perform the SSL handshake
|
// Perform the SSL handshake
|
||||||
stream.handshake(ssl::stream_base::client);
|
stream.handshake(ssl::stream_base::client);
|
||||||
|
@ -53,14 +53,14 @@ int main(int argc, char** argv)
|
|||||||
net::io_context ioc;
|
net::io_context ioc;
|
||||||
|
|
||||||
// These objects perform our I/O
|
// These objects perform our I/O
|
||||||
tcp::resolver resolver{ioc};
|
tcp::resolver resolver(ioc);
|
||||||
tcp::socket socket{ioc};
|
beast::tcp_stream stream(ioc);
|
||||||
|
|
||||||
// Look up the domain name
|
// Look up the domain name
|
||||||
auto const results = resolver.resolve(host, port);
|
auto const results = resolver.resolve(host, port);
|
||||||
|
|
||||||
// Make the connection on the IP address we get from a lookup
|
// Make the connection on the IP address we get from a lookup
|
||||||
net::connect(socket, results.begin(), results.end());
|
beast::connect(stream, results);
|
||||||
|
|
||||||
// Set up an HTTP GET request message
|
// Set up an HTTP GET request message
|
||||||
http::request<http::string_body> req{http::verb::get, target, version};
|
http::request<http::string_body> req{http::verb::get, target, version};
|
||||||
@ -68,7 +68,7 @@ int main(int argc, char** argv)
|
|||||||
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
|
req.set(http::field::user_agent, BOOST_BEAST_VERSION_STRING);
|
||||||
|
|
||||||
// Send the HTTP request to the remote host
|
// Send the HTTP request to the remote host
|
||||||
http::write(socket, req);
|
http::write(stream, req);
|
||||||
|
|
||||||
// This buffer is used for reading and must be persisted
|
// This buffer is used for reading and must be persisted
|
||||||
beast::flat_buffer buffer;
|
beast::flat_buffer buffer;
|
||||||
@ -77,14 +77,14 @@ int main(int argc, char** argv)
|
|||||||
http::response<http::dynamic_body> res;
|
http::response<http::dynamic_body> res;
|
||||||
|
|
||||||
// Receive the HTTP response
|
// Receive the HTTP response
|
||||||
http::read(socket, buffer, res);
|
http::read(stream, buffer, res);
|
||||||
|
|
||||||
// Write the message to standard out
|
// Write the message to standard out
|
||||||
std::cout << res << std::endl;
|
std::cout << res << std::endl;
|
||||||
|
|
||||||
// Gracefully close the socket
|
// Gracefully close the socket
|
||||||
beast::error_code ec;
|
beast::error_code ec;
|
||||||
socket.shutdown(tcp::socket::shutdown_both, ec);
|
stream.socket().shutdown(tcp::socket::shutdown_both, ec);
|
||||||
|
|
||||||
// not_connected happens sometimes
|
// not_connected happens sometimes
|
||||||
// so don't bother reporting it.
|
// so don't bother reporting it.
|
||||||
|
@ -255,7 +255,7 @@ class session : public std::enable_shared_from_this<session>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
beast::ssl_stream<beast::tcp_stream<net::io_context::strand>> stream_;
|
beast::ssl_stream<beast::tcp_stream> stream_;
|
||||||
beast::flat_buffer buffer_;
|
beast::flat_buffer buffer_;
|
||||||
std::shared_ptr<std::string const> doc_root_;
|
std::shared_ptr<std::string const> doc_root_;
|
||||||
http::request<http::string_body> req_;
|
http::request<http::string_body> req_;
|
||||||
@ -387,8 +387,10 @@ public:
|
|||||||
// Accepts incoming connections and launches the sessions
|
// Accepts incoming connections and launches the sessions
|
||||||
class listener : public std::enable_shared_from_this<listener>
|
class listener : public std::enable_shared_from_this<listener>
|
||||||
{
|
{
|
||||||
|
net::io_context& ioc_;
|
||||||
ssl::context& ctx_;
|
ssl::context& ctx_;
|
||||||
tcp::acceptor acceptor_;
|
tcp::acceptor acceptor_;
|
||||||
|
tcp::socket socket_;
|
||||||
std::shared_ptr<std::string const> doc_root_;
|
std::shared_ptr<std::string const> doc_root_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -397,8 +399,10 @@ public:
|
|||||||
ssl::context& ctx,
|
ssl::context& ctx,
|
||||||
tcp::endpoint endpoint,
|
tcp::endpoint endpoint,
|
||||||
std::shared_ptr<std::string const> const& doc_root)
|
std::shared_ptr<std::string const> const& doc_root)
|
||||||
: ctx_(ctx)
|
: ioc_(ioc)
|
||||||
|
, ctx_(ctx)
|
||||||
, acceptor_(ioc)
|
, acceptor_(ioc)
|
||||||
|
, socket_(beast::make_strand(ioc))
|
||||||
, doc_root_(doc_root)
|
, doc_root_(doc_root)
|
||||||
{
|
{
|
||||||
beast::error_code ec;
|
beast::error_code ec;
|
||||||
@ -450,13 +454,14 @@ public:
|
|||||||
do_accept()
|
do_accept()
|
||||||
{
|
{
|
||||||
acceptor_.async_accept(
|
acceptor_.async_accept(
|
||||||
|
socket_,
|
||||||
beast::bind_front_handler(
|
beast::bind_front_handler(
|
||||||
&listener::on_accept,
|
&listener::on_accept,
|
||||||
shared_from_this()));
|
shared_from_this()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
on_accept(beast::error_code ec, tcp::socket socket)
|
on_accept(beast::error_code ec)
|
||||||
{
|
{
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
@ -466,11 +471,14 @@ public:
|
|||||||
{
|
{
|
||||||
// Create the session and run it
|
// Create the session and run it
|
||||||
std::make_shared<session>(
|
std::make_shared<session>(
|
||||||
std::move(socket),
|
std::move(socket_),
|
||||||
ctx_,
|
ctx_,
|
||||||
doc_root_)->run();
|
doc_root_)->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure each session gets its own strand
|
||||||
|
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||||
|
|
||||||
// Accept another connection
|
// Accept another connection
|
||||||
do_accept();
|
do_accept();
|
||||||
}
|
}
|
||||||
|
@ -251,7 +251,7 @@ class session : public std::enable_shared_from_this<session>
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
beast::tcp_stream<net::io_context::strand> stream_;
|
beast::tcp_stream stream_;
|
||||||
beast::flat_buffer buffer_;
|
beast::flat_buffer buffer_;
|
||||||
std::shared_ptr<std::string const> doc_root_;
|
std::shared_ptr<std::string const> doc_root_;
|
||||||
http::request<http::string_body> req_;
|
http::request<http::string_body> req_;
|
||||||
@ -259,7 +259,7 @@ class session : public std::enable_shared_from_this<session>
|
|||||||
send_lambda lambda_;
|
send_lambda lambda_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Take ownership of the socket
|
// Take ownership of the stream
|
||||||
session(
|
session(
|
||||||
tcp::socket&& socket,
|
tcp::socket&& socket,
|
||||||
std::shared_ptr<std::string const> const& doc_root)
|
std::shared_ptr<std::string const> const& doc_root)
|
||||||
@ -352,7 +352,9 @@ public:
|
|||||||
// Accepts incoming connections and launches the sessions
|
// Accepts incoming connections and launches the sessions
|
||||||
class listener : public std::enable_shared_from_this<listener>
|
class listener : public std::enable_shared_from_this<listener>
|
||||||
{
|
{
|
||||||
|
net::io_context& ioc_;
|
||||||
tcp::acceptor acceptor_;
|
tcp::acceptor acceptor_;
|
||||||
|
tcp::socket socket_;
|
||||||
std::shared_ptr<std::string const> doc_root_;
|
std::shared_ptr<std::string const> doc_root_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -360,7 +362,9 @@ public:
|
|||||||
net::io_context& ioc,
|
net::io_context& ioc,
|
||||||
tcp::endpoint endpoint,
|
tcp::endpoint endpoint,
|
||||||
std::shared_ptr<std::string const> const& doc_root)
|
std::shared_ptr<std::string const> const& doc_root)
|
||||||
: acceptor_(ioc)
|
: ioc_(ioc)
|
||||||
|
, acceptor_(beast::make_strand(ioc))
|
||||||
|
, socket_(beast::make_strand(ioc))
|
||||||
, doc_root_(doc_root)
|
, doc_root_(doc_root)
|
||||||
{
|
{
|
||||||
beast::error_code ec;
|
beast::error_code ec;
|
||||||
@ -412,13 +416,14 @@ public:
|
|||||||
do_accept()
|
do_accept()
|
||||||
{
|
{
|
||||||
acceptor_.async_accept(
|
acceptor_.async_accept(
|
||||||
|
socket_,
|
||||||
beast::bind_front_handler(
|
beast::bind_front_handler(
|
||||||
&listener::on_accept,
|
&listener::on_accept,
|
||||||
shared_from_this()));
|
shared_from_this()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
on_accept(beast::error_code ec, tcp::socket socket)
|
on_accept(beast::error_code ec)
|
||||||
{
|
{
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
@ -428,10 +433,13 @@ public:
|
|||||||
{
|
{
|
||||||
// Create the session and run it
|
// Create the session and run it
|
||||||
std::make_shared<session>(
|
std::make_shared<session>(
|
||||||
std::move(socket),
|
std::move(socket_),
|
||||||
doc_root_)->run();
|
doc_root_)->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure each session gets its own strand
|
||||||
|
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||||
|
|
||||||
// Accept another connection
|
// Accept another connection
|
||||||
do_accept();
|
do_accept();
|
||||||
}
|
}
|
||||||
|
@ -207,11 +207,6 @@ handle_request(
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// The type of stream to use
|
|
||||||
// Stackful coroutines are already stranded.
|
|
||||||
using stream_type =
|
|
||||||
beast::ssl_stream<beast::tcp_stream<net::io_context::executor_type>>;
|
|
||||||
|
|
||||||
// Report a failure
|
// Report a failure
|
||||||
void
|
void
|
||||||
fail(beast::error_code ec, char const* what)
|
fail(beast::error_code ec, char const* what)
|
||||||
@ -223,13 +218,13 @@ fail(beast::error_code ec, char const* what)
|
|||||||
// The function object is used to send an HTTP message.
|
// The function object is used to send an HTTP message.
|
||||||
struct send_lambda
|
struct send_lambda
|
||||||
{
|
{
|
||||||
stream_type& stream_;
|
beast::ssl_stream<beast::tcp_stream>& stream_;
|
||||||
bool& close_;
|
bool& close_;
|
||||||
beast::error_code& ec_;
|
beast::error_code& ec_;
|
||||||
net::yield_context yield_;
|
net::yield_context yield_;
|
||||||
|
|
||||||
send_lambda(
|
send_lambda(
|
||||||
stream_type& stream,
|
beast::ssl_stream<beast::tcp_stream>& stream,
|
||||||
bool& close,
|
bool& close,
|
||||||
beast::error_code& ec,
|
beast::error_code& ec,
|
||||||
net::yield_context yield)
|
net::yield_context yield)
|
||||||
@ -258,7 +253,7 @@ struct send_lambda
|
|||||||
// Handles an HTTP server connection
|
// Handles an HTTP server connection
|
||||||
void
|
void
|
||||||
do_session(
|
do_session(
|
||||||
stream_type& stream,
|
beast::ssl_stream<beast::tcp_stream>& stream,
|
||||||
std::shared_ptr<std::string const> const& doc_root,
|
std::shared_ptr<std::string const> const& doc_root,
|
||||||
net::yield_context yield)
|
net::yield_context yield)
|
||||||
{
|
{
|
||||||
@ -357,10 +352,11 @@ do_listen(
|
|||||||
fail(ec, "accept");
|
fail(ec, "accept");
|
||||||
else
|
else
|
||||||
net::spawn(
|
net::spawn(
|
||||||
acceptor.get_executor().context(),
|
acceptor.get_executor(),
|
||||||
std::bind(
|
std::bind(
|
||||||
&do_session,
|
&do_session,
|
||||||
stream_type(std::move(socket), ctx),
|
beast::ssl_stream<beast::tcp_stream>(
|
||||||
|
std::move(socket), ctx),
|
||||||
doc_root,
|
doc_root,
|
||||||
std::placeholders::_1));
|
std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
@ -204,10 +204,6 @@ handle_request(
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// The type of stream to use.
|
|
||||||
// Stackful coroutines are already stranded.
|
|
||||||
using stream_type = beast::tcp_stream<net::io_context::executor_type>;
|
|
||||||
|
|
||||||
// Report a failure
|
// Report a failure
|
||||||
void
|
void
|
||||||
fail(beast::error_code ec, char const* what)
|
fail(beast::error_code ec, char const* what)
|
||||||
@ -219,13 +215,13 @@ fail(beast::error_code ec, char const* what)
|
|||||||
// The function object is used to send an HTTP message.
|
// The function object is used to send an HTTP message.
|
||||||
struct send_lambda
|
struct send_lambda
|
||||||
{
|
{
|
||||||
stream_type& stream_;
|
beast::tcp_stream& stream_;
|
||||||
bool& close_;
|
bool& close_;
|
||||||
beast::error_code& ec_;
|
beast::error_code& ec_;
|
||||||
net::yield_context yield_;
|
net::yield_context yield_;
|
||||||
|
|
||||||
send_lambda(
|
send_lambda(
|
||||||
stream_type& stream,
|
beast::tcp_stream& stream,
|
||||||
bool& close,
|
bool& close,
|
||||||
beast::error_code& ec,
|
beast::error_code& ec,
|
||||||
net::yield_context yield)
|
net::yield_context yield)
|
||||||
@ -254,7 +250,7 @@ struct send_lambda
|
|||||||
// Handles an HTTP server connection
|
// Handles an HTTP server connection
|
||||||
void
|
void
|
||||||
do_session(
|
do_session(
|
||||||
stream_type& stream,
|
beast::tcp_stream& stream,
|
||||||
std::shared_ptr<std::string const> const& doc_root,
|
std::shared_ptr<std::string const> const& doc_root,
|
||||||
net::yield_context yield)
|
net::yield_context yield)
|
||||||
{
|
{
|
||||||
@ -339,10 +335,10 @@ do_listen(
|
|||||||
fail(ec, "accept");
|
fail(ec, "accept");
|
||||||
else
|
else
|
||||||
net::spawn(
|
net::spawn(
|
||||||
acceptor.get_executor().context(),
|
acceptor.get_executor(),
|
||||||
std::bind(
|
std::bind(
|
||||||
&do_session,
|
&do_session,
|
||||||
stream_type(std::move(socket)),
|
beast::tcp_stream(std::move(socket)),
|
||||||
doc_root,
|
doc_root,
|
||||||
std::placeholders::_1));
|
std::placeholders::_1));
|
||||||
}
|
}
|
||||||
|
@ -99,7 +99,7 @@ private:
|
|||||||
std::string doc_root_;
|
std::string doc_root_;
|
||||||
|
|
||||||
// The socket for the currently connected client.
|
// The socket for the currently connected client.
|
||||||
tcp::socket socket_{acceptor_.get_executor().context()};
|
tcp::socket socket_{acceptor_.get_executor()};
|
||||||
|
|
||||||
// The buffer for performing reads
|
// The buffer for performing reads
|
||||||
beast::flat_static_buffer<8192> buffer_;
|
beast::flat_static_buffer<8192> buffer_;
|
||||||
@ -112,7 +112,7 @@ private:
|
|||||||
|
|
||||||
// The timer putting a time limit on requests.
|
// The timer putting a time limit on requests.
|
||||||
net::basic_waitable_timer<std::chrono::steady_clock> request_deadline_{
|
net::basic_waitable_timer<std::chrono::steady_clock> request_deadline_{
|
||||||
acceptor_.get_executor().context(), (std::chrono::steady_clock::time_point::max)()};
|
acceptor_.get_executor(), (std::chrono::steady_clock::time_point::max)()};
|
||||||
|
|
||||||
// The string-based response message.
|
// The string-based response message.
|
||||||
boost::optional<http::response<http::string_body, http::basic_fields<alloc_t>>> string_response_;
|
boost::optional<http::response<http::string_body, http::basic_fields<alloc_t>>> string_response_;
|
||||||
|
@ -208,13 +208,6 @@ handle_request(
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// The type of plain streams
|
|
||||||
using plain_stream_type = beast::tcp_stream<net::io_context::strand>;
|
|
||||||
|
|
||||||
// The type of TLS streams
|
|
||||||
using ssl_stream_type =
|
|
||||||
beast::ssl_stream<beast::tcp_stream<net::io_context::strand>>;
|
|
||||||
|
|
||||||
// Report a failure
|
// Report a failure
|
||||||
void
|
void
|
||||||
fail(beast::error_code ec, char const* what)
|
fail(beast::error_code ec, char const* what)
|
||||||
@ -358,7 +351,7 @@ class plain_session
|
|||||||
: public session<plain_session>
|
: public session<plain_session>
|
||||||
, public std::enable_shared_from_this<plain_session>
|
, public std::enable_shared_from_this<plain_session>
|
||||||
{
|
{
|
||||||
plain_stream_type stream_;
|
beast::tcp_stream stream_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Create the session
|
// Create the session
|
||||||
@ -374,7 +367,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Called by the base class
|
// Called by the base class
|
||||||
plain_stream_type&
|
beast::tcp_stream&
|
||||||
stream()
|
stream()
|
||||||
{
|
{
|
||||||
return stream_;
|
return stream_;
|
||||||
@ -403,7 +396,7 @@ class ssl_session
|
|||||||
: public session<ssl_session>
|
: public session<ssl_session>
|
||||||
, public std::enable_shared_from_this<ssl_session>
|
, public std::enable_shared_from_this<ssl_session>
|
||||||
{
|
{
|
||||||
ssl_stream_type stream_;
|
beast::ssl_stream<beast::tcp_stream> stream_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Create the session
|
// Create the session
|
||||||
@ -420,7 +413,7 @@ public:
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Called by the base class
|
// Called by the base class
|
||||||
ssl_stream_type&
|
beast::ssl_stream<beast::tcp_stream>&
|
||||||
stream()
|
stream()
|
||||||
{
|
{
|
||||||
return stream_;
|
return stream_;
|
||||||
@ -442,6 +435,7 @@ public:
|
|||||||
&ssl_session::on_handshake,
|
&ssl_session::on_handshake,
|
||||||
shared_from_this()));
|
shared_from_this()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
on_handshake(
|
on_handshake(
|
||||||
beast::error_code ec,
|
beast::error_code ec,
|
||||||
@ -484,14 +478,14 @@ public:
|
|||||||
// Detects SSL handshakes
|
// Detects SSL handshakes
|
||||||
class detect_session : public std::enable_shared_from_this<detect_session>
|
class detect_session : public std::enable_shared_from_this<detect_session>
|
||||||
{
|
{
|
||||||
plain_stream_type stream_;
|
beast::tcp_stream stream_;
|
||||||
ssl::context& ctx_;
|
ssl::context& ctx_;
|
||||||
std::shared_ptr<std::string const> doc_root_;
|
std::shared_ptr<std::string const> doc_root_;
|
||||||
beast::flat_buffer buffer_;
|
beast::flat_buffer buffer_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
detect_session(
|
detect_session(
|
||||||
tcp::socket socket,
|
tcp::socket&& socket,
|
||||||
ssl::context& ctx,
|
ssl::context& ctx,
|
||||||
std::shared_ptr<std::string const> const& doc_root)
|
std::shared_ptr<std::string const> const& doc_root)
|
||||||
: stream_(std::move(socket))
|
: stream_(std::move(socket))
|
||||||
@ -544,8 +538,10 @@ public:
|
|||||||
// Accepts incoming connections and launches the sessions
|
// Accepts incoming connections and launches the sessions
|
||||||
class listener : public std::enable_shared_from_this<listener>
|
class listener : public std::enable_shared_from_this<listener>
|
||||||
{
|
{
|
||||||
|
net::io_context& ioc_;
|
||||||
ssl::context& ctx_;
|
ssl::context& ctx_;
|
||||||
tcp::acceptor acceptor_;
|
tcp::acceptor acceptor_;
|
||||||
|
tcp::socket socket_;
|
||||||
std::shared_ptr<std::string const> doc_root_;
|
std::shared_ptr<std::string const> doc_root_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -554,8 +550,10 @@ public:
|
|||||||
ssl::context& ctx,
|
ssl::context& ctx,
|
||||||
tcp::endpoint endpoint,
|
tcp::endpoint endpoint,
|
||||||
std::shared_ptr<std::string const> const& doc_root)
|
std::shared_ptr<std::string const> const& doc_root)
|
||||||
: ctx_(ctx)
|
: ioc_(ioc)
|
||||||
, acceptor_(ioc)
|
, ctx_(ctx)
|
||||||
|
, acceptor_(beast::make_strand(ioc))
|
||||||
|
, socket_(beast::make_strand(ioc))
|
||||||
, doc_root_(doc_root)
|
, doc_root_(doc_root)
|
||||||
{
|
{
|
||||||
beast::error_code ec;
|
beast::error_code ec;
|
||||||
@ -607,13 +605,14 @@ public:
|
|||||||
do_accept()
|
do_accept()
|
||||||
{
|
{
|
||||||
acceptor_.async_accept(
|
acceptor_.async_accept(
|
||||||
|
socket_,
|
||||||
beast::bind_front_handler(
|
beast::bind_front_handler(
|
||||||
&listener::on_accept,
|
&listener::on_accept,
|
||||||
shared_from_this()));
|
shared_from_this()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
on_accept(beast::error_code ec, tcp::socket sock)
|
on_accept(beast::error_code ec)
|
||||||
{
|
{
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
@ -623,11 +622,14 @@ public:
|
|||||||
{
|
{
|
||||||
// Create the detector session and run it
|
// Create the detector session and run it
|
||||||
std::make_shared<detect_session>(
|
std::make_shared<detect_session>(
|
||||||
std::move(sock),
|
std::move(socket_),
|
||||||
ctx_,
|
ctx_,
|
||||||
doc_root_)->run();
|
doc_root_)->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure each session gets its own strand
|
||||||
|
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||||
|
|
||||||
// Accept another connection
|
// Accept another connection
|
||||||
do_accept();
|
do_accept();
|
||||||
}
|
}
|
||||||
|
@ -76,7 +76,7 @@ private:
|
|||||||
|
|
||||||
// The timer for putting a deadline on connection processing.
|
// The timer for putting a deadline on connection processing.
|
||||||
net::basic_waitable_timer<std::chrono::steady_clock> deadline_{
|
net::basic_waitable_timer<std::chrono::steady_clock> deadline_{
|
||||||
socket_.get_executor().context(), std::chrono::seconds(60)};
|
socket_.get_executor(), std::chrono::seconds(60)};
|
||||||
|
|
||||||
// Asynchronously receive a complete request message.
|
// Asynchronously receive a complete request message.
|
||||||
void
|
void
|
||||||
|
@ -209,10 +209,6 @@ handle_request(
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// The type of TLS streams
|
|
||||||
using ssl_stream_type =
|
|
||||||
beast::ssl_stream<beast::tcp_stream<net::io_context::strand>>;
|
|
||||||
|
|
||||||
// Report a failure
|
// Report a failure
|
||||||
void
|
void
|
||||||
fail(beast::error_code ec, char const* what)
|
fail(beast::error_code ec, char const* what)
|
||||||
@ -264,7 +260,7 @@ class session
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
ssl_stream_type stream_;
|
beast::ssl_stream<beast::tcp_stream> stream_;
|
||||||
beast::flat_buffer buffer_;
|
beast::flat_buffer buffer_;
|
||||||
std::shared_ptr<std::string const> doc_root_;
|
std::shared_ptr<std::string const> doc_root_;
|
||||||
http::request<http::string_body> req_;
|
http::request<http::string_body> req_;
|
||||||
@ -383,6 +379,7 @@ class listener
|
|||||||
: public net::coroutine
|
: public net::coroutine
|
||||||
, public std::enable_shared_from_this<listener>
|
, public std::enable_shared_from_this<listener>
|
||||||
{
|
{
|
||||||
|
net::io_context& ioc_;
|
||||||
ssl::context& ctx_;
|
ssl::context& ctx_;
|
||||||
tcp::acceptor acceptor_;
|
tcp::acceptor acceptor_;
|
||||||
tcp::socket socket_;
|
tcp::socket socket_;
|
||||||
@ -394,9 +391,10 @@ public:
|
|||||||
ssl::context& ctx,
|
ssl::context& ctx,
|
||||||
tcp::endpoint endpoint,
|
tcp::endpoint endpoint,
|
||||||
std::shared_ptr<std::string const> const& doc_root)
|
std::shared_ptr<std::string const> const& doc_root)
|
||||||
: ctx_(ctx)
|
: ioc_(ioc)
|
||||||
, acceptor_(ioc)
|
, ctx_(ctx)
|
||||||
, socket_(ioc)
|
, acceptor_(beast::make_strand(ioc))
|
||||||
|
, socket_(beast::make_strand(ioc))
|
||||||
, doc_root_(doc_root)
|
, doc_root_(doc_root)
|
||||||
{
|
{
|
||||||
beast::error_code ec;
|
beast::error_code ec;
|
||||||
@ -470,6 +468,9 @@ public:
|
|||||||
ctx_,
|
ctx_,
|
||||||
doc_root_)->run();
|
doc_root_)->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure each session gets its own strand
|
||||||
|
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -205,9 +205,6 @@ handle_request(
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// The type of stream to use
|
|
||||||
using stream_type = beast::tcp_stream<net::io_context::strand>;
|
|
||||||
|
|
||||||
// Report a failure
|
// Report a failure
|
||||||
void
|
void
|
||||||
fail(beast::error_code ec, char const* what)
|
fail(beast::error_code ec, char const* what)
|
||||||
@ -258,7 +255,7 @@ class session
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
stream_type stream_;
|
beast::tcp_stream stream_;
|
||||||
beast::flat_buffer buffer_;
|
beast::flat_buffer buffer_;
|
||||||
std::shared_ptr<std::string const> doc_root_;
|
std::shared_ptr<std::string const> doc_root_;
|
||||||
http::request<http::string_body> req_;
|
http::request<http::string_body> req_;
|
||||||
@ -269,7 +266,7 @@ public:
|
|||||||
// Take ownership of the socket
|
// Take ownership of the socket
|
||||||
explicit
|
explicit
|
||||||
session(
|
session(
|
||||||
tcp::socket socket,
|
tcp::socket&& socket,
|
||||||
std::shared_ptr<std::string const> const& doc_root)
|
std::shared_ptr<std::string const> const& doc_root)
|
||||||
: stream_(std::move(socket))
|
: stream_(std::move(socket))
|
||||||
, doc_root_(doc_root)
|
, doc_root_(doc_root)
|
||||||
@ -348,6 +345,7 @@ class listener
|
|||||||
: public net::coroutine
|
: public net::coroutine
|
||||||
, public std::enable_shared_from_this<listener>
|
, public std::enable_shared_from_this<listener>
|
||||||
{
|
{
|
||||||
|
net::io_context& ioc_;
|
||||||
tcp::acceptor acceptor_;
|
tcp::acceptor acceptor_;
|
||||||
tcp::socket socket_;
|
tcp::socket socket_;
|
||||||
std::shared_ptr<std::string const> doc_root_;
|
std::shared_ptr<std::string const> doc_root_;
|
||||||
@ -357,8 +355,9 @@ public:
|
|||||||
net::io_context& ioc,
|
net::io_context& ioc,
|
||||||
tcp::endpoint endpoint,
|
tcp::endpoint endpoint,
|
||||||
std::shared_ptr<std::string const> const& doc_root)
|
std::shared_ptr<std::string const> const& doc_root)
|
||||||
: acceptor_(ioc)
|
: ioc_(ioc)
|
||||||
, socket_(ioc)
|
, acceptor_(beast::make_strand(ioc))
|
||||||
|
, socket_(beast::make_strand(ioc))
|
||||||
, doc_root_(doc_root)
|
, doc_root_(doc_root)
|
||||||
{
|
{
|
||||||
beast::error_code ec;
|
beast::error_code ec;
|
||||||
@ -429,6 +428,9 @@ public:
|
|||||||
std::move(socket_),
|
std::move(socket_),
|
||||||
doc_root_)->run();
|
doc_root_)->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure each session gets its own strand
|
||||||
|
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,8 +45,8 @@ fail(beast::error_code ec, char const* what)
|
|||||||
class session : public std::enable_shared_from_this<session>
|
class session : public std::enable_shared_from_this<session>
|
||||||
{
|
{
|
||||||
tcp::resolver resolver_;
|
tcp::resolver resolver_;
|
||||||
websocket::stream<beast::ssl_stream<
|
websocket::stream<
|
||||||
beast::tcp_stream<net::io_context::executor_type>>> ws_;
|
beast::ssl_stream<beast::tcp_stream>> ws_;
|
||||||
beast::multi_buffer buffer_;
|
beast::multi_buffer buffer_;
|
||||||
std::string host_;
|
std::string host_;
|
||||||
std::string text_;
|
std::string text_;
|
||||||
@ -55,8 +55,8 @@ public:
|
|||||||
// Resolver and socket require an io_context
|
// Resolver and socket require an io_context
|
||||||
explicit
|
explicit
|
||||||
session(net::io_context& ioc, ssl::context& ctx)
|
session(net::io_context& ioc, ssl::context& ctx)
|
||||||
: resolver_(ioc)
|
: resolver_(beast::make_strand(ioc))
|
||||||
, ws_(ioc, ctx)
|
, ws_(beast::make_strand(ioc), ctx)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -40,8 +40,7 @@ fail(beast::error_code ec, char const* what)
|
|||||||
class session : public std::enable_shared_from_this<session>
|
class session : public std::enable_shared_from_this<session>
|
||||||
{
|
{
|
||||||
tcp::resolver resolver_;
|
tcp::resolver resolver_;
|
||||||
websocket::stream<
|
websocket::stream<beast::tcp_stream> ws_;
|
||||||
beast::tcp_stream<net::io_context::executor_type>> ws_;
|
|
||||||
beast::multi_buffer buffer_;
|
beast::multi_buffer buffer_;
|
||||||
std::string host_;
|
std::string host_;
|
||||||
std::string text_;
|
std::string text_;
|
||||||
@ -50,8 +49,8 @@ public:
|
|||||||
// Resolver and socket require an io_context
|
// Resolver and socket require an io_context
|
||||||
explicit
|
explicit
|
||||||
session(net::io_context& ioc)
|
session(net::io_context& ioc)
|
||||||
: resolver_(ioc)
|
: resolver_(beast::make_strand(ioc))
|
||||||
, ws_(ioc)
|
, ws_(beast::make_strand(ioc))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -54,9 +54,9 @@ do_session(
|
|||||||
beast::error_code ec;
|
beast::error_code ec;
|
||||||
|
|
||||||
// These objects perform our I/O
|
// These objects perform our I/O
|
||||||
tcp::resolver resolver{ioc};
|
tcp::resolver resolver(ioc);
|
||||||
websocket::stream<beast::ssl_stream<
|
websocket::stream<
|
||||||
beast::tcp_stream<net::io_context::executor_type>>> ws(ioc, ctx);
|
beast::ssl_stream<beast::tcp_stream>> ws(ioc, ctx);
|
||||||
|
|
||||||
// Look up the domain name
|
// Look up the domain name
|
||||||
auto const results = resolver.async_resolve(host, port, yield[ec]);
|
auto const results = resolver.async_resolve(host, port, yield[ec]);
|
||||||
|
@ -48,9 +48,8 @@ do_session(
|
|||||||
beast::error_code ec;
|
beast::error_code ec;
|
||||||
|
|
||||||
// These objects perform our I/O
|
// These objects perform our I/O
|
||||||
tcp::resolver resolver{ioc};
|
tcp::resolver resolver(ioc);
|
||||||
websocket::stream<
|
websocket::stream<beast::tcp_stream> ws(ioc);
|
||||||
beast::tcp_stream<net::io_context::executor_type>> ws(ioc);
|
|
||||||
|
|
||||||
// Look up the domain name
|
// Look up the domain name
|
||||||
auto const results = resolver.async_resolve(host, port, yield[ec]);
|
auto const results = resolver.async_resolve(host, port, yield[ec]);
|
||||||
|
@ -48,13 +48,13 @@ fail(beast::error_code ec, char const* what)
|
|||||||
// Echoes back all received WebSocket messages
|
// Echoes back all received WebSocket messages
|
||||||
class session : public std::enable_shared_from_this<session>
|
class session : public std::enable_shared_from_this<session>
|
||||||
{
|
{
|
||||||
websocket::stream<beast::ssl_stream<
|
websocket::stream<
|
||||||
beast::tcp_stream<net::io_context::strand>>> ws_;
|
beast::ssl_stream<beast::tcp_stream>> ws_;
|
||||||
beast::multi_buffer buffer_;
|
beast::multi_buffer buffer_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Take ownership of the socket
|
// Take ownership of the socket
|
||||||
session(tcp::socket socket, ssl::context& ctx)
|
session(tcp::socket&& socket, ssl::context& ctx)
|
||||||
: ws_(std::move(socket), ctx)
|
: ws_(std::move(socket), ctx)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -172,16 +172,20 @@ public:
|
|||||||
// Accepts incoming connections and launches the sessions
|
// Accepts incoming connections and launches the sessions
|
||||||
class listener : public std::enable_shared_from_this<listener>
|
class listener : public std::enable_shared_from_this<listener>
|
||||||
{
|
{
|
||||||
|
net::io_context& ioc_;
|
||||||
ssl::context& ctx_;
|
ssl::context& ctx_;
|
||||||
tcp::acceptor acceptor_;
|
tcp::acceptor acceptor_;
|
||||||
|
tcp::socket socket_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
listener(
|
listener(
|
||||||
net::io_context& ioc,
|
net::io_context& ioc,
|
||||||
ssl::context& ctx,
|
ssl::context& ctx,
|
||||||
tcp::endpoint endpoint)
|
tcp::endpoint endpoint)
|
||||||
: ctx_(ctx)
|
: ioc_(ioc)
|
||||||
, acceptor_(ioc)
|
, ctx_(ctx)
|
||||||
|
, acceptor_(beast::make_strand(ioc))
|
||||||
|
, socket_(beast::make_strand(ioc))
|
||||||
{
|
{
|
||||||
beast::error_code ec;
|
beast::error_code ec;
|
||||||
|
|
||||||
@ -232,13 +236,14 @@ public:
|
|||||||
do_accept()
|
do_accept()
|
||||||
{
|
{
|
||||||
acceptor_.async_accept(
|
acceptor_.async_accept(
|
||||||
|
socket_,
|
||||||
beast::bind_front_handler(
|
beast::bind_front_handler(
|
||||||
&listener::on_accept,
|
&listener::on_accept,
|
||||||
shared_from_this()));
|
shared_from_this()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
on_accept(beast::error_code ec, tcp::socket socket)
|
on_accept(beast::error_code ec)
|
||||||
{
|
{
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
@ -247,9 +252,12 @@ public:
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Create the session and run it
|
// Create the session and run it
|
||||||
std::make_shared<session>(std::move(socket), ctx_)->run();
|
std::make_shared<session>(std::move(socket_), ctx_)->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure each session gets its own strand
|
||||||
|
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||||
|
|
||||||
// Accept another connection
|
// Accept another connection
|
||||||
do_accept();
|
do_accept();
|
||||||
}
|
}
|
||||||
|
@ -43,13 +43,13 @@ fail(beast::error_code ec, char const* what)
|
|||||||
// Echoes back all received WebSocket messages
|
// Echoes back all received WebSocket messages
|
||||||
class session : public std::enable_shared_from_this<session>
|
class session : public std::enable_shared_from_this<session>
|
||||||
{
|
{
|
||||||
websocket::stream<beast::tcp_stream<net::io_context::strand>> ws_;
|
websocket::stream<beast::tcp_stream> ws_;
|
||||||
beast::multi_buffer buffer_;
|
beast::multi_buffer buffer_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Take ownership of the socket
|
// Take ownership of the socket
|
||||||
explicit
|
explicit
|
||||||
session(tcp::socket socket)
|
session(tcp::socket&& socket)
|
||||||
: ws_(std::move(socket))
|
: ws_(std::move(socket))
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@ -146,13 +146,17 @@ public:
|
|||||||
// Accepts incoming connections and launches the sessions
|
// Accepts incoming connections and launches the sessions
|
||||||
class listener : public std::enable_shared_from_this<listener>
|
class listener : public std::enable_shared_from_this<listener>
|
||||||
{
|
{
|
||||||
|
net::io_context& ioc_;
|
||||||
tcp::acceptor acceptor_;
|
tcp::acceptor acceptor_;
|
||||||
|
tcp::socket socket_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
listener(
|
listener(
|
||||||
net::io_context& ioc,
|
net::io_context& ioc,
|
||||||
tcp::endpoint endpoint)
|
tcp::endpoint endpoint)
|
||||||
: acceptor_(ioc)
|
: ioc_(ioc)
|
||||||
|
, acceptor_(ioc)
|
||||||
|
, socket_(beast::make_strand(ioc_))
|
||||||
{
|
{
|
||||||
beast::error_code ec;
|
beast::error_code ec;
|
||||||
|
|
||||||
@ -203,13 +207,14 @@ public:
|
|||||||
do_accept()
|
do_accept()
|
||||||
{
|
{
|
||||||
acceptor_.async_accept(
|
acceptor_.async_accept(
|
||||||
|
socket_,
|
||||||
beast::bind_front_handler(
|
beast::bind_front_handler(
|
||||||
&listener::on_accept,
|
&listener::on_accept,
|
||||||
shared_from_this()));
|
shared_from_this()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
on_accept(beast::error_code ec, tcp::socket socket)
|
on_accept(beast::error_code ec)
|
||||||
{
|
{
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
@ -218,9 +223,12 @@ public:
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Create the session and run it
|
// Create the session and run it
|
||||||
std::make_shared<session>(std::move(socket))->run();
|
std::make_shared<session>(std::move(socket_))->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure each session gets its own strand
|
||||||
|
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||||
|
|
||||||
// Accept another connection
|
// Accept another connection
|
||||||
do_accept();
|
do_accept();
|
||||||
}
|
}
|
||||||
|
@ -21,7 +21,7 @@
|
|||||||
*/
|
*/
|
||||||
class http_session : public boost::enable_shared_from_this<http_session>
|
class http_session : public boost::enable_shared_from_this<http_session>
|
||||||
{
|
{
|
||||||
beast::tcp_stream<net::io_context::strand> stream_;
|
beast::tcp_stream stream_;
|
||||||
beast::flat_buffer buffer_;
|
beast::flat_buffer buffer_;
|
||||||
boost::shared_ptr<shared_state> state_;
|
boost::shared_ptr<shared_state> state_;
|
||||||
http::request<http::string_body> req_;
|
http::request<http::string_body> req_;
|
||||||
|
@ -16,7 +16,9 @@ listener(
|
|||||||
net::io_context& ioc,
|
net::io_context& ioc,
|
||||||
tcp::endpoint endpoint,
|
tcp::endpoint endpoint,
|
||||||
boost::shared_ptr<shared_state> const& state)
|
boost::shared_ptr<shared_state> const& state)
|
||||||
: acceptor_(ioc)
|
: ioc_(ioc)
|
||||||
|
, acceptor_(ioc)
|
||||||
|
, socket_(beast::make_strand(ioc))
|
||||||
, state_(state)
|
, state_(state)
|
||||||
{
|
{
|
||||||
beast::error_code ec;
|
beast::error_code ec;
|
||||||
@ -61,6 +63,7 @@ run()
|
|||||||
{
|
{
|
||||||
// Start accepting a connection
|
// Start accepting a connection
|
||||||
acceptor_.async_accept(
|
acceptor_.async_accept(
|
||||||
|
socket_,
|
||||||
beast::bind_front_handler(
|
beast::bind_front_handler(
|
||||||
&listener::on_accept,
|
&listener::on_accept,
|
||||||
shared_from_this()));
|
shared_from_this()));
|
||||||
@ -80,18 +83,22 @@ fail(beast::error_code ec, char const* what)
|
|||||||
// Handle a connection
|
// Handle a connection
|
||||||
void
|
void
|
||||||
listener::
|
listener::
|
||||||
on_accept(beast::error_code ec, tcp::socket socket)
|
on_accept(beast::error_code ec)
|
||||||
{
|
{
|
||||||
if(ec)
|
if(ec)
|
||||||
return fail(ec, "accept");
|
return fail(ec, "accept");
|
||||||
else
|
else
|
||||||
// Launch a new session for this connection
|
// Launch a new session for this connection
|
||||||
boost::make_shared<http_session>(
|
boost::make_shared<http_session>(
|
||||||
std::move(socket),
|
std::move(socket_),
|
||||||
state_)->run();
|
state_)->run();
|
||||||
|
|
||||||
|
// Make sure each session gets its own strand
|
||||||
|
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||||
|
|
||||||
// Accept another connection
|
// Accept another connection
|
||||||
acceptor_.async_accept(
|
acceptor_.async_accept(
|
||||||
|
socket_,
|
||||||
beast::bind_front_handler(
|
beast::bind_front_handler(
|
||||||
&listener::on_accept,
|
&listener::on_accept,
|
||||||
shared_from_this()));
|
shared_from_this()));
|
||||||
|
@ -22,11 +22,13 @@ class shared_state;
|
|||||||
// Accepts incoming connections and launches the sessions
|
// Accepts incoming connections and launches the sessions
|
||||||
class listener : public boost::enable_shared_from_this<listener>
|
class listener : public boost::enable_shared_from_this<listener>
|
||||||
{
|
{
|
||||||
|
net::io_context& ioc_;
|
||||||
tcp::acceptor acceptor_;
|
tcp::acceptor acceptor_;
|
||||||
|
tcp::socket socket_;
|
||||||
boost::shared_ptr<shared_state> state_;
|
boost::shared_ptr<shared_state> state_;
|
||||||
|
|
||||||
void fail(beast::error_code ec, char const* what);
|
void fail(beast::error_code ec, char const* what);
|
||||||
void on_accept(beast::error_code ec, tcp::socket socket);
|
void on_accept(beast::error_code ec);
|
||||||
|
|
||||||
public:
|
public:
|
||||||
listener(
|
listener(
|
||||||
|
@ -83,17 +83,22 @@ void
|
|||||||
websocket_session::
|
websocket_session::
|
||||||
send(boost::shared_ptr<std::string const> const& ss)
|
send(boost::shared_ptr<std::string const> const& ss)
|
||||||
{
|
{
|
||||||
// Get on the strand if we aren't already,
|
// Post our work to the strand, this ensures
|
||||||
// otherwise we will concurrently access
|
// that the members of `this` will not be
|
||||||
// objects which are not thread-safe.
|
// accessed concurrently.
|
||||||
if(! ws_.get_executor().running_in_this_thread())
|
|
||||||
return net::post(
|
|
||||||
ws_.get_executor(),
|
|
||||||
beast::bind_front_handler(
|
|
||||||
&websocket_session::send,
|
|
||||||
shared_from_this(),
|
|
||||||
ss));
|
|
||||||
|
|
||||||
|
net::post(
|
||||||
|
ws_.get_executor(),
|
||||||
|
beast::bind_front_handler(
|
||||||
|
&websocket_session::on_send,
|
||||||
|
shared_from_this(),
|
||||||
|
ss));
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
websocket_session::
|
||||||
|
on_send(boost::shared_ptr<std::string const> const& ss)
|
||||||
|
{
|
||||||
// Always add to queue
|
// Always add to queue
|
||||||
queue_.push_back(ss);
|
queue_.push_back(ss);
|
||||||
|
|
||||||
|
@ -27,7 +27,7 @@ class shared_state;
|
|||||||
class websocket_session : public boost::enable_shared_from_this<websocket_session>
|
class websocket_session : public boost::enable_shared_from_this<websocket_session>
|
||||||
{
|
{
|
||||||
beast::flat_buffer buffer_;
|
beast::flat_buffer buffer_;
|
||||||
websocket::stream<beast::tcp_stream<net::io_context::strand>> ws_;
|
websocket::stream<beast::tcp_stream> ws_;
|
||||||
boost::shared_ptr<shared_state> state_;
|
boost::shared_ptr<shared_state> state_;
|
||||||
std::vector<boost::shared_ptr<std::string const>> queue_;
|
std::vector<boost::shared_ptr<std::string const>> queue_;
|
||||||
|
|
||||||
@ -50,6 +50,10 @@ public:
|
|||||||
// Send a message
|
// Send a message
|
||||||
void
|
void
|
||||||
send(boost::shared_ptr<std::string const> const& ss);
|
send(boost::shared_ptr<std::string const> const& ss);
|
||||||
|
|
||||||
|
private:
|
||||||
|
void
|
||||||
|
on_send(boost::shared_ptr<std::string const> const& ss);
|
||||||
};
|
};
|
||||||
|
|
||||||
template<class Body, class Allocator>
|
template<class Body, class Allocator>
|
||||||
|
@ -38,11 +38,6 @@ using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// The type of websocket stream to use
|
|
||||||
// Stackful coroutines are already stranded.
|
|
||||||
using ws_type = websocket::stream<beast::ssl_stream<
|
|
||||||
beast::tcp_stream<net::io_context::executor_type>>>;
|
|
||||||
|
|
||||||
// Report a failure
|
// Report a failure
|
||||||
void
|
void
|
||||||
fail(beast::error_code ec, char const* what)
|
fail(beast::error_code ec, char const* what)
|
||||||
@ -53,7 +48,8 @@ fail(beast::error_code ec, char const* what)
|
|||||||
// Echoes back all received WebSocket messages
|
// Echoes back all received WebSocket messages
|
||||||
void
|
void
|
||||||
do_session(
|
do_session(
|
||||||
ws_type& ws,
|
websocket::stream<
|
||||||
|
beast::ssl_stream<beast::tcp_stream>>& ws,
|
||||||
net::yield_context yield)
|
net::yield_context yield)
|
||||||
{
|
{
|
||||||
beast::error_code ec;
|
beast::error_code ec;
|
||||||
@ -153,10 +149,11 @@ do_listen(
|
|||||||
fail(ec, "accept");
|
fail(ec, "accept");
|
||||||
else
|
else
|
||||||
net::spawn(
|
net::spawn(
|
||||||
acceptor.get_executor().context(),
|
acceptor.get_executor(),
|
||||||
std::bind(
|
std::bind(
|
||||||
&do_session,
|
&do_session,
|
||||||
ws_type(std::move(socket), ctx),
|
websocket::stream<beast::ssl_stream<
|
||||||
|
beast::tcp_stream>>(std::move(socket), ctx),
|
||||||
std::placeholders::_1));
|
std::placeholders::_1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,11 +33,6 @@ using tcp = boost::asio::ip::tcp; // from <boost/asio/ip/tcp.hpp>
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// The type of websocket stream to use
|
|
||||||
// Stackful coroutines are already stranded.
|
|
||||||
using ws_type = websocket::stream<
|
|
||||||
beast::tcp_stream<net::io_context::executor_type>>;
|
|
||||||
|
|
||||||
// Report a failure
|
// Report a failure
|
||||||
void
|
void
|
||||||
fail(beast::error_code ec, char const* what)
|
fail(beast::error_code ec, char const* what)
|
||||||
@ -47,7 +42,9 @@ fail(beast::error_code ec, char const* what)
|
|||||||
|
|
||||||
// Echoes back all received WebSocket messages
|
// Echoes back all received WebSocket messages
|
||||||
void
|
void
|
||||||
do_session(ws_type& ws, net::yield_context yield)
|
do_session(
|
||||||
|
websocket::stream<beast::tcp_stream>& ws,
|
||||||
|
net::yield_context yield)
|
||||||
{
|
{
|
||||||
beast::error_code ec;
|
beast::error_code ec;
|
||||||
|
|
||||||
@ -133,10 +130,11 @@ do_listen(
|
|||||||
fail(ec, "accept");
|
fail(ec, "accept");
|
||||||
else
|
else
|
||||||
net::spawn(
|
net::spawn(
|
||||||
acceptor.get_executor().context(),
|
acceptor.get_executor(),
|
||||||
std::bind(
|
std::bind(
|
||||||
&do_session,
|
&do_session,
|
||||||
ws_type(std::move(socket)),
|
websocket::stream<
|
||||||
|
beast::tcp_stream>(std::move(socket)),
|
||||||
std::placeholders::_1));
|
std::placeholders::_1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -157,7 +155,7 @@ int main(int argc, char* argv[])
|
|||||||
auto const threads = std::max<int>(1, std::atoi(argv[3]));
|
auto const threads = std::max<int>(1, std::atoi(argv[3]));
|
||||||
|
|
||||||
// The io_context is required for all I/O
|
// The io_context is required for all I/O
|
||||||
net::io_context ioc{threads};
|
net::io_context ioc(threads);
|
||||||
|
|
||||||
// Spawn a listening port
|
// Spawn a listening port
|
||||||
net::spawn(ioc,
|
net::spawn(ioc,
|
||||||
|
@ -78,13 +78,8 @@ setup_stream(websocket::stream<NextLayer>& ws)
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
// The type of websocket stream to use
|
|
||||||
// Stackful coroutines are already stranded.
|
|
||||||
using ws_type = websocket::stream<
|
|
||||||
beast::tcp_stream<net::io_context::executor_type>>;
|
|
||||||
|
|
||||||
void
|
void
|
||||||
do_sync_session(ws_type& ws)
|
do_sync_session(websocket::stream<beast::tcp_stream>& ws)
|
||||||
{
|
{
|
||||||
beast::error_code ec;
|
beast::error_code ec;
|
||||||
|
|
||||||
@ -135,7 +130,8 @@ do_sync_listen(
|
|||||||
|
|
||||||
std::thread(std::bind(
|
std::thread(std::bind(
|
||||||
&do_sync_session,
|
&do_sync_session,
|
||||||
ws_type(std::move(socket)))).detach();
|
websocket::stream<beast::tcp_stream>(
|
||||||
|
std::move(socket)))).detach();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -144,13 +140,13 @@ do_sync_listen(
|
|||||||
// Echoes back all received WebSocket messages
|
// Echoes back all received WebSocket messages
|
||||||
class async_session : public std::enable_shared_from_this<async_session>
|
class async_session : public std::enable_shared_from_this<async_session>
|
||||||
{
|
{
|
||||||
websocket::stream<beast::tcp_stream<net::io_context::strand>> ws_;
|
websocket::stream<beast::tcp_stream> ws_;
|
||||||
beast::multi_buffer buffer_;
|
beast::multi_buffer buffer_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
// Take ownership of the socket
|
// Take ownership of the socket
|
||||||
explicit
|
explicit
|
||||||
async_session(tcp::socket socket)
|
async_session(tcp::socket&& socket)
|
||||||
: ws_(std::move(socket))
|
: ws_(std::move(socket))
|
||||||
{
|
{
|
||||||
setup_stream(ws_);
|
setup_stream(ws_);
|
||||||
@ -160,6 +156,11 @@ public:
|
|||||||
void
|
void
|
||||||
run()
|
run()
|
||||||
{
|
{
|
||||||
|
// Set suggested timeout settings for the websocket
|
||||||
|
ws_.set_option(
|
||||||
|
websocket::stream_base::suggested_settings(
|
||||||
|
websocket::role_type::server));
|
||||||
|
|
||||||
// Set a decorator to change the Server of the handshake
|
// Set a decorator to change the Server of the handshake
|
||||||
ws_.set_option(websocket::stream_base::decorator(
|
ws_.set_option(websocket::stream_base::decorator(
|
||||||
[](websocket::response_type& res)
|
[](websocket::response_type& res)
|
||||||
@ -240,13 +241,17 @@ public:
|
|||||||
// Accepts incoming connections and launches the sessions
|
// Accepts incoming connections and launches the sessions
|
||||||
class async_listener : public std::enable_shared_from_this<async_listener>
|
class async_listener : public std::enable_shared_from_this<async_listener>
|
||||||
{
|
{
|
||||||
|
net::io_context& ioc_;
|
||||||
tcp::acceptor acceptor_;
|
tcp::acceptor acceptor_;
|
||||||
|
tcp::socket socket_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
async_listener(
|
async_listener(
|
||||||
net::io_context& ioc,
|
net::io_context& ioc,
|
||||||
tcp::endpoint endpoint)
|
tcp::endpoint endpoint)
|
||||||
: acceptor_(ioc)
|
: ioc_(ioc)
|
||||||
|
, acceptor_(beast::make_strand(ioc))
|
||||||
|
, socket_(beast::make_strand(ioc))
|
||||||
{
|
{
|
||||||
beast::error_code ec;
|
beast::error_code ec;
|
||||||
|
|
||||||
@ -297,13 +302,14 @@ public:
|
|||||||
do_accept()
|
do_accept()
|
||||||
{
|
{
|
||||||
acceptor_.async_accept(
|
acceptor_.async_accept(
|
||||||
|
socket_,
|
||||||
beast::bind_front_handler(
|
beast::bind_front_handler(
|
||||||
&async_listener::on_accept,
|
&async_listener::on_accept,
|
||||||
shared_from_this()));
|
shared_from_this()));
|
||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
on_accept(beast::error_code ec, tcp::socket socket)
|
on_accept(beast::error_code ec)
|
||||||
{
|
{
|
||||||
if(ec)
|
if(ec)
|
||||||
{
|
{
|
||||||
@ -312,9 +318,12 @@ public:
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
// Create the async_session and run it
|
// Create the async_session and run it
|
||||||
std::make_shared<async_session>(std::move(socket))->run();
|
std::make_shared<async_session>(std::move(socket_))->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure each session gets its own strand
|
||||||
|
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||||
|
|
||||||
// Accept another connection
|
// Accept another connection
|
||||||
do_accept();
|
do_accept();
|
||||||
}
|
}
|
||||||
@ -323,12 +332,19 @@ public:
|
|||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
void
|
void
|
||||||
do_coro_session(ws_type& ws, net::yield_context yield)
|
do_coro_session(
|
||||||
|
websocket::stream<beast::tcp_stream>& ws,
|
||||||
|
net::yield_context yield)
|
||||||
{
|
{
|
||||||
beast::error_code ec;
|
beast::error_code ec;
|
||||||
|
|
||||||
setup_stream(ws);
|
setup_stream(ws);
|
||||||
|
|
||||||
|
// Set suggested timeout settings for the websocket
|
||||||
|
ws.set_option(
|
||||||
|
websocket::stream_base::suggested_settings(
|
||||||
|
websocket::role_type::server));
|
||||||
|
|
||||||
// Set a decorator to change the Server of the handshake
|
// Set a decorator to change the Server of the handshake
|
||||||
ws.set_option(websocket::stream_base::decorator(
|
ws.set_option(websocket::stream_base::decorator(
|
||||||
[](websocket::response_type& res)
|
[](websocket::response_type& res)
|
||||||
@ -395,10 +411,11 @@ do_coro_listen(
|
|||||||
}
|
}
|
||||||
|
|
||||||
net::spawn(
|
net::spawn(
|
||||||
acceptor.get_executor().context(),
|
acceptor.get_executor(),
|
||||||
std::bind(
|
std::bind(
|
||||||
&do_coro_session,
|
&do_coro_session,
|
||||||
ws_type(std::move(socket)),
|
websocket::stream<
|
||||||
|
beast::tcp_stream>(std::move(socket)),
|
||||||
std::placeholders::_1));
|
std::placeholders::_1));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,8 +51,7 @@ class session
|
|||||||
: public net::coroutine
|
: public net::coroutine
|
||||||
, public std::enable_shared_from_this<session>
|
, public std::enable_shared_from_this<session>
|
||||||
{
|
{
|
||||||
websocket::stream<beast::ssl_stream<
|
websocket::stream<beast::ssl_stream<beast::tcp_stream>> ws_;
|
||||||
beast::tcp_stream<net::io_context::strand>>> ws_;
|
|
||||||
beast::multi_buffer buffer_;
|
beast::multi_buffer buffer_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -166,6 +165,7 @@ class listener
|
|||||||
: public net::coroutine
|
: public net::coroutine
|
||||||
, public std::enable_shared_from_this<listener>
|
, public std::enable_shared_from_this<listener>
|
||||||
{
|
{
|
||||||
|
net::io_context& ioc_;
|
||||||
ssl::context& ctx_;
|
ssl::context& ctx_;
|
||||||
tcp::acceptor acceptor_;
|
tcp::acceptor acceptor_;
|
||||||
tcp::socket socket_;
|
tcp::socket socket_;
|
||||||
@ -175,7 +175,8 @@ public:
|
|||||||
net::io_context& ioc,
|
net::io_context& ioc,
|
||||||
ssl::context& ctx,
|
ssl::context& ctx,
|
||||||
tcp::endpoint endpoint)
|
tcp::endpoint endpoint)
|
||||||
: ctx_(ctx)
|
: ioc_(ioc)
|
||||||
|
, ctx_(ctx)
|
||||||
, acceptor_(ioc)
|
, acceptor_(ioc)
|
||||||
, socket_(ioc)
|
, socket_(ioc)
|
||||||
{
|
{
|
||||||
@ -247,6 +248,9 @@ public:
|
|||||||
// Create the session and run it
|
// Create the session and run it
|
||||||
std::make_shared<session>(std::move(socket_), ctx_)->run();
|
std::make_shared<session>(std::move(socket_), ctx_)->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure each session gets its own strand
|
||||||
|
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -46,8 +46,7 @@ class session
|
|||||||
: public net::coroutine
|
: public net::coroutine
|
||||||
, public std::enable_shared_from_this<session>
|
, public std::enable_shared_from_this<session>
|
||||||
{
|
{
|
||||||
websocket::stream<
|
websocket::stream<beast::tcp_stream> ws_;
|
||||||
beast::tcp_stream<net::io_context::strand>> ws_;
|
|
||||||
beast::multi_buffer buffer_;
|
beast::multi_buffer buffer_;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
@ -143,6 +142,7 @@ class listener
|
|||||||
: public net::coroutine
|
: public net::coroutine
|
||||||
, public std::enable_shared_from_this<listener>
|
, public std::enable_shared_from_this<listener>
|
||||||
{
|
{
|
||||||
|
net::io_context& ioc_;
|
||||||
tcp::acceptor acceptor_;
|
tcp::acceptor acceptor_;
|
||||||
tcp::socket socket_;
|
tcp::socket socket_;
|
||||||
|
|
||||||
@ -150,8 +150,9 @@ public:
|
|||||||
listener(
|
listener(
|
||||||
net::io_context& ioc,
|
net::io_context& ioc,
|
||||||
tcp::endpoint endpoint)
|
tcp::endpoint endpoint)
|
||||||
: acceptor_(ioc)
|
: ioc_(ioc)
|
||||||
, socket_(ioc)
|
, acceptor_(beast::make_strand(ioc))
|
||||||
|
, socket_(beast::make_strand(ioc))
|
||||||
{
|
{
|
||||||
beast::error_code ec;
|
beast::error_code ec;
|
||||||
|
|
||||||
@ -221,6 +222,9 @@ public:
|
|||||||
// Create the session and run it
|
// Create the session and run it
|
||||||
std::make_shared<session>(std::move(socket_))->run();
|
std::make_shared<session>(std::move(socket_))->run();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Make sure each session gets its own strand
|
||||||
|
socket_ = tcp::socket(beast::make_strand(ioc_));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#define BOOST_BEAST_TEST_TCP_HPP
|
#define BOOST_BEAST_TEST_TCP_HPP
|
||||||
|
|
||||||
#include <boost/beast/core/detail/config.hpp>
|
#include <boost/beast/core/detail/config.hpp>
|
||||||
|
#include <boost/beast/core/detail/get_io_context.hpp>
|
||||||
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||||
#include <boost/beast/_experimental/test/handler.hpp>
|
#include <boost/beast/_experimental/test/handler.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
@ -60,26 +61,28 @@ run_for(
|
|||||||
ioc.restart();
|
ioc.restart();
|
||||||
}
|
}
|
||||||
|
|
||||||
/** Connect two TCP/IP sockets together.
|
/** Connect two TCP sockets together.
|
||||||
*/
|
*/
|
||||||
inline
|
template<class Executor>
|
||||||
bool
|
bool
|
||||||
connect(
|
connect(
|
||||||
net::ip::tcp::socket& s1,
|
net::basic_stream_socket<net::ip::tcp, Executor>& s1,
|
||||||
net::ip::tcp::socket& s2)
|
net::basic_stream_socket<net::ip::tcp, Executor>& s2)
|
||||||
|
|
||||||
{
|
{
|
||||||
// Sockets must use the same I/O context
|
auto ioc1 = beast::detail::get_io_context(s1);
|
||||||
BOOST_ASSERT(
|
auto ioc2 = beast::detail::get_io_context(s2);
|
||||||
std::addressof(s1.get_executor().context()) ==
|
if(! BEAST_EXPECT(ioc1 != nullptr))
|
||||||
std::addressof(s2.get_executor().context()));
|
return false;
|
||||||
auto& ioc = s1.get_executor().context();
|
if(! BEAST_EXPECT(ioc2 != nullptr))
|
||||||
s1 = net::ip::tcp::socket(ioc);
|
return false;
|
||||||
s2 = net::ip::tcp::socket(ioc);
|
if(! BEAST_EXPECT(ioc1 == ioc2))
|
||||||
|
return false;
|
||||||
|
auto& ioc = *ioc1;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
net::ip::tcp::acceptor a(
|
net::basic_socket_acceptor<
|
||||||
s1.get_executor().context());
|
net::ip::tcp, Executor> a(s1.get_executor());
|
||||||
auto ep = net::ip::tcp::endpoint(
|
auto ep = net::ip::tcp::endpoint(
|
||||||
net::ip::make_address_v4("127.0.0.1"), 0);
|
net::ip::make_address_v4("127.0.0.1"), 0);
|
||||||
a.open(ep.protocol());
|
a.open(ep.protocol());
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include <boost/beast/core/detail/config.hpp>
|
#include <boost/beast/core/detail/config.hpp>
|
||||||
#include <boost/beast/core/detail/stream_base.hpp>
|
#include <boost/beast/core/detail/stream_base.hpp>
|
||||||
#include <boost/beast/core/error.hpp>
|
#include <boost/beast/core/error.hpp>
|
||||||
|
#include <boost/beast/core/stream_traits.hpp>
|
||||||
#include <boost/beast/websocket/role.hpp> // VFALCO This is unfortunate
|
#include <boost/beast/websocket/role.hpp> // VFALCO This is unfortunate
|
||||||
#include <boost/asio/async_result.hpp>
|
#include <boost/asio/async_result.hpp>
|
||||||
#include <boost/asio/basic_stream_socket.hpp>
|
#include <boost/asio/basic_stream_socket.hpp>
|
||||||
@ -21,7 +22,6 @@
|
|||||||
#include <boost/asio/is_executor.hpp>
|
#include <boost/asio/is_executor.hpp>
|
||||||
#include <boost/core/empty_value.hpp>
|
#include <boost/core/empty_value.hpp>
|
||||||
#include <boost/config/workaround.hpp>
|
#include <boost/config/workaround.hpp>
|
||||||
#include <boost/optional.hpp>
|
|
||||||
#include <boost/enable_shared_from_this.hpp>
|
#include <boost/enable_shared_from_this.hpp>
|
||||||
#include <boost/shared_ptr.hpp>
|
#include <boost/shared_ptr.hpp>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
@ -42,14 +42,14 @@ namespace beast {
|
|||||||
/** A stream socket wrapper with timeouts and associated executor.
|
/** A stream socket wrapper with timeouts and associated executor.
|
||||||
|
|
||||||
This stream wraps a `net::basic_stream_socket` to provide
|
This stream wraps a `net::basic_stream_socket` to provide
|
||||||
the following additional features:
|
the following features:
|
||||||
|
|
||||||
@li Optional timeouts may be specified for each logical asynchronous
|
@li Optional timeouts may be specified for each logical asynchronous
|
||||||
operation performing any reading, writing, or connecting.
|
operation performing any reading, writing, or connecting.
|
||||||
|
|
||||||
@li An <em>Executor</em> may be associated with the stream, which will
|
@li An <em>Executor</em> may be associated with the stream, which will
|
||||||
be used to invoke any completion handlers which do not already have
|
be used to invoke any completion handlers which do not already have
|
||||||
an associated executor. This achieves partial support for
|
an associated executor. This achieves support for
|
||||||
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1322r0.html">[P1322R0] Networking TS enhancement to enable custom I/O executors</a>.
|
<a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1322r0.html">[P1322R0] Networking TS enhancement to enable custom I/O executors</a>.
|
||||||
|
|
||||||
Although the stream supports multiple concurrent outstanding asynchronous
|
Although the stream supports multiple concurrent outstanding asynchronous
|
||||||
@ -109,7 +109,7 @@ namespace beast {
|
|||||||
HTTP response with a different timeout.
|
HTTP response with a different timeout.
|
||||||
|
|
||||||
@code
|
@code
|
||||||
void process_http_1 (tcp_stream<net::io_context::executor_type>& stream, net::yield_context yield)
|
void process_http_1 (tcp_stream& stream, net::yield_context yield)
|
||||||
{
|
{
|
||||||
flat_buffer buffer;
|
flat_buffer buffer;
|
||||||
http::request<http::empty_body> req;
|
http::request<http::empty_body> req;
|
||||||
@ -133,7 +133,7 @@ namespace beast {
|
|||||||
applies to the entire combined operation of reading and writing:
|
applies to the entire combined operation of reading and writing:
|
||||||
|
|
||||||
@code
|
@code
|
||||||
void process_http_2 (tcp_stream<net::io_context::executor_type>& stream, net::yield_context yield)
|
void process_http_2 (tcp_stream& stream, net::yield_context yield)
|
||||||
{
|
{
|
||||||
flat_buffer buffer;
|
flat_buffer buffer;
|
||||||
http::request<http::empty_body> req;
|
http::request<http::empty_body> req;
|
||||||
@ -155,7 +155,7 @@ namespace beast {
|
|||||||
thusly:
|
thusly:
|
||||||
|
|
||||||
@code
|
@code
|
||||||
void do_ssl_handshake (net::ssl::stream<tcp_stream<net::io_context::executor_type>>& stream, net::yield_context yield)
|
void do_ssl_handshake (net::ssl::stream<tcp_stream>& stream, net::yield_context yield)
|
||||||
{
|
{
|
||||||
// Require that the SSL handshake take no longer than 10 seconds
|
// Require that the SSL handshake take no longer than 10 seconds
|
||||||
stream.expires_after(std::chrono::seconds(10));
|
stream.expires_after(std::chrono::seconds(10));
|
||||||
@ -176,7 +176,8 @@ namespace beast {
|
|||||||
|
|
||||||
@tparam Executor A type meeting the requirements of <em>Executor</em> to
|
@tparam Executor A type meeting the requirements of <em>Executor</em> to
|
||||||
be used for submitting all completion handlers which do not already have an
|
be used for submitting all completion handlers which do not already have an
|
||||||
associated executor.
|
associated executor. If this type is omitted, the default of `net::executor`
|
||||||
|
will be used.
|
||||||
|
|
||||||
@par Thread Safety
|
@par Thread Safety
|
||||||
<em>Distinct objects</em>: Safe.@n
|
<em>Distinct objects</em>: Safe.@n
|
||||||
@ -190,12 +191,33 @@ namespace beast {
|
|||||||
|
|
||||||
@li <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1322r0.html">[P1322R0] Networking TS enhancement to enable custom I/O executors</a>.
|
@li <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1322r0.html">[P1322R0] Networking TS enhancement to enable custom I/O executors</a>.
|
||||||
*/
|
*/
|
||||||
template<class Protocol, class Executor>
|
template<
|
||||||
|
class Protocol,
|
||||||
|
class Executor = net::executor>
|
||||||
class basic_stream
|
class basic_stream
|
||||||
#if ! BOOST_BEAST_DOXYGEN
|
#if ! BOOST_BEAST_DOXYGEN
|
||||||
: private detail::stream_base
|
: private detail::stream_base
|
||||||
#endif
|
#endif
|
||||||
{
|
{
|
||||||
|
public:
|
||||||
|
/// The type of the underlying socket.
|
||||||
|
using socket_type =
|
||||||
|
net::basic_stream_socket<Protocol, Executor>;
|
||||||
|
|
||||||
|
/** The type of the executor associated with the stream.
|
||||||
|
|
||||||
|
This will be the type of executor used to invoke completion
|
||||||
|
handlers which do not have an explicit associated executor.
|
||||||
|
*/
|
||||||
|
using executor_type = beast::executor_type<socket_type>;
|
||||||
|
|
||||||
|
/// The protocol type.
|
||||||
|
using protocol_type = Protocol;
|
||||||
|
|
||||||
|
/// The endpoint type.
|
||||||
|
using endpoint_type = typename Protocol::endpoint;
|
||||||
|
|
||||||
|
private:
|
||||||
static_assert(net::is_executor<Executor>::value,
|
static_assert(net::is_executor<Executor>::value,
|
||||||
"Executor requirements not met");
|
"Executor requirements not met");
|
||||||
|
|
||||||
@ -206,33 +228,26 @@ public:
|
|||||||
#endif
|
#endif
|
||||||
struct impl_type
|
struct impl_type
|
||||||
: boost::enable_shared_from_this<impl_type>
|
: boost::enable_shared_from_this<impl_type>
|
||||||
, boost::empty_value<Executor>
|
|
||||||
{
|
{
|
||||||
|
// must come first
|
||||||
|
net::basic_stream_socket<
|
||||||
|
Protocol, Executor> socket;
|
||||||
|
|
||||||
op_state read;
|
op_state read;
|
||||||
op_state write;
|
op_state write;
|
||||||
|
|
||||||
net::basic_stream_socket<Protocol> socket;
|
|
||||||
|
|
||||||
impl_type(impl_type&&) = default;
|
impl_type(impl_type&&) = default;
|
||||||
|
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
explicit
|
explicit
|
||||||
impl_type(Executor const&, Args&&...);
|
impl_type(Args&&...);
|
||||||
|
|
||||||
template<class OtherProtocol>
|
|
||||||
impl_type(net::basic_stream_socket<OtherProtocol>&& socket_,
|
|
||||||
std::true_type);
|
|
||||||
|
|
||||||
template<class OtherProtocol>
|
|
||||||
impl_type(net::basic_stream_socket<OtherProtocol>&& socket_,
|
|
||||||
std::false_type);
|
|
||||||
|
|
||||||
impl_type& operator=(impl_type&&) = delete;
|
impl_type& operator=(impl_type&&) = delete;
|
||||||
|
|
||||||
Executor const&
|
beast::executor_type<socket_type>
|
||||||
ex() const noexcept
|
ex() noexcept
|
||||||
{
|
{
|
||||||
return this->boost::empty_value<Executor>::get();
|
return this->socket.get_executor();
|
||||||
}
|
}
|
||||||
|
|
||||||
void reset(); // set timeouts to never
|
void reset(); // set timeouts to never
|
||||||
@ -248,13 +263,6 @@ private:
|
|||||||
// but the implementation is still waiting on a timer.
|
// but the implementation is still waiting on a timer.
|
||||||
boost::shared_ptr<impl_type> impl_;
|
boost::shared_ptr<impl_type> impl_;
|
||||||
|
|
||||||
// Restricted until P1322R0 is incorporated into Boost.Asio.
|
|
||||||
static_assert(
|
|
||||||
std::is_convertible<
|
|
||||||
decltype(std::declval<Executor const&>().context()),
|
|
||||||
net::io_context&>::value,
|
|
||||||
"Only net::io_context is currently supported for executor_type::context()");
|
|
||||||
|
|
||||||
template<bool, class, class> class async_op;
|
template<bool, class, class> class async_op;
|
||||||
|
|
||||||
template<class, class, class>
|
template<class, class, class>
|
||||||
@ -287,22 +295,6 @@ private:
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/** The type of the executor associated with the stream.
|
|
||||||
|
|
||||||
This will be the type of executor used to invoke completion
|
|
||||||
handlers which do not have an explicit associated executor.
|
|
||||||
*/
|
|
||||||
using executor_type = Executor;
|
|
||||||
|
|
||||||
/// The type of the underlying socket.
|
|
||||||
using socket_type = net::basic_stream_socket<Protocol>;
|
|
||||||
|
|
||||||
/// The protocol type.
|
|
||||||
using protocol_type = Protocol;
|
|
||||||
|
|
||||||
/// The endpoint type.
|
|
||||||
using endpoint_type = typename Protocol::endpoint;
|
|
||||||
|
|
||||||
/** Destructor
|
/** Destructor
|
||||||
|
|
||||||
This function destroys the stream, cancelling any outstanding
|
This function destroys the stream, cancelling any outstanding
|
||||||
@ -311,106 +303,20 @@ public:
|
|||||||
*/
|
*/
|
||||||
~basic_stream();
|
~basic_stream();
|
||||||
|
|
||||||
/** Construct the stream from an execution context.
|
/** Constructor
|
||||||
|
|
||||||
This constructor creates the stream from an execution context.
|
This constructor creates the stream by forwarding all arguments
|
||||||
The underlying socket needs to be open and connected or accepted
|
to the underlying socket. The socket then needs to be open and
|
||||||
before data can be sent or received on it.
|
connected or accepted before data can be sent or received on it.
|
||||||
|
|
||||||
@param ctx An object whose type meets the requirements of
|
|
||||||
<em>ExecutionContext</em>, which the stream will use to dispatch
|
|
||||||
handlers that do not have an explicit associated executor.
|
|
||||||
Currently, the only supported type for `ctx` is `net::io_context`.
|
|
||||||
|
|
||||||
@param args A list of parameters forwarded to the constructor of
|
@param args A list of parameters forwarded to the constructor of
|
||||||
the underlying socket.
|
the underlying socket.
|
||||||
|
|
||||||
@note This function does not participate in overload resolution unless:
|
|
||||||
|
|
||||||
@li `std::is_convertible<ExecutionContext&, net::execution_context&>::value` is `true`, and
|
|
||||||
|
|
||||||
@li `std::is_constructible<executor_type, typename ExecutionContext::executor_type>::value` is `true`.
|
|
||||||
|
|
||||||
@see <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1322r0.html">[P1322R0] Networking TS enhancement to enable custom I/O executors</a>
|
|
||||||
*/
|
|
||||||
template<
|
|
||||||
class ExecutionContext,
|
|
||||||
class... Args
|
|
||||||
#if ! BOOST_BEAST_DOXYGEN
|
|
||||||
, class = typename std::enable_if<
|
|
||||||
std::is_convertible<
|
|
||||||
ExecutionContext&,
|
|
||||||
net::execution_context&>::value &&
|
|
||||||
std::is_constructible<
|
|
||||||
executor_type,
|
|
||||||
typename ExecutionContext::executor_type>::value
|
|
||||||
>::type
|
|
||||||
#endif
|
|
||||||
>
|
|
||||||
explicit
|
|
||||||
basic_stream(ExecutionContext& ctx, Args&&... args);
|
|
||||||
|
|
||||||
/** Construct the stream from an executor.
|
|
||||||
|
|
||||||
This constructor creates the stream from an executor.
|
|
||||||
The underlying socket needs to be open and connected or accepted
|
|
||||||
before data can be sent or received on it.
|
|
||||||
|
|
||||||
@param ex The executor to use when dispatching handlers that do
|
|
||||||
not have an explicit associated executor.
|
|
||||||
Currently, only executors that return a `net::io_context&` from
|
|
||||||
`ex.context()` are supported.
|
|
||||||
|
|
||||||
@param args A list of parameters forwarded to the constructor of
|
|
||||||
the underlying socket.
|
|
||||||
|
|
||||||
@see <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2018/p1322r0.html">[P1322R0] Networking TS enhancement to enable custom I/O executors</a>
|
|
||||||
*/
|
*/
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
explicit
|
explicit
|
||||||
basic_stream(
|
basic_stream(Args&&... args);
|
||||||
executor_type const& ex, Args&&... args);
|
|
||||||
|
|
||||||
/** Construct the stream from an existing socket.
|
/** Move constructor
|
||||||
|
|
||||||
This constructor creates the stream from an existing socket.
|
|
||||||
The underlying socket needs to be open and connected or accepted
|
|
||||||
before data can be sent or received on it.
|
|
||||||
|
|
||||||
@param socket The socket to construct from. Ownership of the
|
|
||||||
socket will be transferred by move-construction.
|
|
||||||
|
|
||||||
@param args A list of parameters forwarded to the constructor of
|
|
||||||
the underlying socket.
|
|
||||||
|
|
||||||
@note This function does not participate in overload resolution unless:
|
|
||||||
|
|
||||||
@li `OtherProtocol` is convertible to `Protocol`, and one of:
|
|
||||||
|
|
||||||
@li `executor_type` of the stream is constructible from the type of
|
|
||||||
context returned by calling `socket.get_executor().context()`, or
|
|
||||||
|
|
||||||
@li `executor_type` of the stream is constructible from the type of
|
|
||||||
executor returned by calling `socket.get_executor()`.
|
|
||||||
*/
|
|
||||||
template<
|
|
||||||
class OtherProtocol
|
|
||||||
#if ! BOOST_BEAST_DOXYGEN
|
|
||||||
,class = typename std::enable_if<
|
|
||||||
std::is_convertible<OtherProtocol, Protocol>::value && (
|
|
||||||
std::is_constructible<Executor,
|
|
||||||
decltype(std::declval<net::basic_stream_socket<
|
|
||||||
Protocol>&>().get_executor().context())>::value ||
|
|
||||||
std::is_constructible<Executor,
|
|
||||||
decltype(std::declval<net::basic_stream_socket<
|
|
||||||
Protocol>&>().get_executor())>::value)
|
|
||||||
>::type
|
|
||||||
#endif
|
|
||||||
>
|
|
||||||
explicit
|
|
||||||
basic_stream(net::basic_stream_socket<OtherProtocol>&& socket);
|
|
||||||
|
|
||||||
/** Move constructor.
|
|
||||||
|
|
||||||
@param other The other object from which the move will occur.
|
@param other The other object from which the move will occur.
|
||||||
|
|
||||||
|
107
include/boost/beast/core/detail/get_io_context.hpp
Normal file
107
include/boost/beast/core/detail/get_io_context.hpp
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
|
||||||
|
#ifndef BOOST_BEAST_DETAIL_GET_IO_CONTEXT_HPP
|
||||||
|
#define BOOST_BEAST_DETAIL_GET_IO_CONTEXT_HPP
|
||||||
|
|
||||||
|
#include <boost/beast/core/stream_traits.hpp>
|
||||||
|
#include <boost/asio/executor.hpp>
|
||||||
|
#include <boost/asio/io_context.hpp>
|
||||||
|
#include <boost/asio/strand.hpp>
|
||||||
|
#include <memory>
|
||||||
|
#include <type_traits>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace beast {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
inline
|
||||||
|
net::io_context*
|
||||||
|
get_io_context(net::io_context& ioc)
|
||||||
|
{
|
||||||
|
return std::addressof(ioc);
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
net::io_context*
|
||||||
|
get_io_context(net::io_context::executor_type const& ex)
|
||||||
|
{
|
||||||
|
return std::addressof(ex.context());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
net::io_context*
|
||||||
|
get_io_context(net::strand<
|
||||||
|
net::io_context::executor_type> const& ex)
|
||||||
|
{
|
||||||
|
return std::addressof(
|
||||||
|
ex.get_inner_executor().context());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class Executor>
|
||||||
|
net::io_context*
|
||||||
|
get_io_context(net::strand<Executor> const& ex)
|
||||||
|
{
|
||||||
|
return get_io_context(ex.get_inner_executor());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<
|
||||||
|
class T,
|
||||||
|
class = typename std::enable_if<
|
||||||
|
std::is_same<T, net::executor>::value>::type>
|
||||||
|
net::io_context*
|
||||||
|
get_io_context(T const& ex)
|
||||||
|
{
|
||||||
|
auto p = ex.template target<typename
|
||||||
|
net::io_context::executor_type>();
|
||||||
|
if(! p)
|
||||||
|
return nullptr;
|
||||||
|
return std::addressof(p->context());
|
||||||
|
}
|
||||||
|
|
||||||
|
inline
|
||||||
|
net::io_context*
|
||||||
|
get_io_context(...)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
net::io_context*
|
||||||
|
get_io_context_impl(T& t, std::true_type)
|
||||||
|
{
|
||||||
|
return get_io_context(
|
||||||
|
t.get_executor());
|
||||||
|
}
|
||||||
|
|
||||||
|
template<class T>
|
||||||
|
net::io_context*
|
||||||
|
get_io_context_impl(T const&, std::false_type)
|
||||||
|
{
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Returns the io_context*, or nullptr, for any object.
|
||||||
|
template<class T>
|
||||||
|
net::io_context*
|
||||||
|
get_io_context(T& t)
|
||||||
|
{
|
||||||
|
return get_io_context_impl(t,
|
||||||
|
has_get_executor<T>{});
|
||||||
|
}
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // beast
|
||||||
|
} // boost
|
||||||
|
|
||||||
|
#endif
|
@ -15,6 +15,7 @@
|
|||||||
#include <boost/core/exchange.hpp>
|
#include <boost/core/exchange.hpp>
|
||||||
#include <chrono>
|
#include <chrono>
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
#include <utility>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
@ -48,9 +49,10 @@ struct stream_base
|
|||||||
bool pending = false; // if op is pending
|
bool pending = false; // if op is pending
|
||||||
bool timeout = false; // if timed out
|
bool timeout = false; // if timed out
|
||||||
|
|
||||||
|
template<class... Args>
|
||||||
explicit
|
explicit
|
||||||
op_state(net::io_context& ioc)
|
op_state(Args&&... args)
|
||||||
: timer(ioc)
|
: timer(std::forward<Args>(args)...)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -32,44 +32,10 @@ template<class Protocol, class Executor>
|
|||||||
template<class... Args>
|
template<class... Args>
|
||||||
basic_stream<Protocol, Executor>::
|
basic_stream<Protocol, Executor>::
|
||||||
impl_type::
|
impl_type::
|
||||||
impl_type(
|
impl_type(Args&&... args)
|
||||||
Executor const& ex_,
|
: socket(std::forward<Args>(args)...)
|
||||||
Args&&... args)
|
, read(ex())
|
||||||
: boost::empty_value<Executor>(
|
, write(ex())
|
||||||
boost::empty_init_t{}, ex_)
|
|
||||||
, read(ex().context())
|
|
||||||
, write(ex().context())
|
|
||||||
, socket(std::forward<Args>(args)...)
|
|
||||||
{
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
|
||||||
template<class OtherProtocol>
|
|
||||||
basic_stream<Protocol, Executor>::
|
|
||||||
impl_type::
|
|
||||||
impl_type(net::basic_stream_socket<OtherProtocol>&& socket_,
|
|
||||||
std::true_type)
|
|
||||||
: boost::empty_value<Executor>(
|
|
||||||
boost::empty_init_t{}, socket_.get_executor())
|
|
||||||
, read(ex().context())
|
|
||||||
, write(ex().context())
|
|
||||||
, socket(std::move(socket_))
|
|
||||||
{
|
|
||||||
reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
|
||||||
template<class OtherProtocol>
|
|
||||||
basic_stream<Protocol, Executor>::
|
|
||||||
impl_type::
|
|
||||||
impl_type(net::basic_stream_socket<OtherProtocol>&& socket_,
|
|
||||||
std::false_type)
|
|
||||||
: boost::empty_value<Executor>(boost::empty_init_t{},
|
|
||||||
socket_.get_executor().context())
|
|
||||||
, read(ex().context())
|
|
||||||
, write(ex().context())
|
|
||||||
, socket(std::move(socket_))
|
|
||||||
{
|
{
|
||||||
reset();
|
reset();
|
||||||
}
|
}
|
||||||
@ -434,40 +400,12 @@ basic_stream<Protocol, Executor>::
|
|||||||
impl_->close();
|
impl_->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
|
||||||
template<class ExecutionContext, class... Args, class>
|
|
||||||
basic_stream<Protocol, Executor>::
|
|
||||||
basic_stream(ExecutionContext& ctx, Args&&... args)
|
|
||||||
: impl_(boost::make_shared<impl_type>(
|
|
||||||
ctx.get_executor(),
|
|
||||||
ctx, std::forward<Args>(args)...))
|
|
||||||
{
|
|
||||||
// Restriction is necessary until Asio fully supports P1322R0
|
|
||||||
static_assert(
|
|
||||||
std::is_same<ExecutionContext, net::io_context>::value,
|
|
||||||
"Only net::io_context is currently supported for ExecutionContext");
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
template<class Protocol, class Executor>
|
||||||
template<class... Args>
|
template<class... Args>
|
||||||
basic_stream<Protocol, Executor>::
|
basic_stream<Protocol, Executor>::
|
||||||
basic_stream(
|
basic_stream(Args&&... args)
|
||||||
executor_type const& ex, Args&&... args)
|
|
||||||
: impl_(boost::make_shared<impl_type>(
|
: impl_(boost::make_shared<impl_type>(
|
||||||
ex,
|
std::forward<Args>(args)...))
|
||||||
ex.context(), std::forward<Args>(args)...))
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
template<class Protocol, class Executor>
|
|
||||||
template<class OtherProtocol, class>
|
|
||||||
basic_stream<Protocol, Executor>::
|
|
||||||
basic_stream(net::basic_stream_socket<OtherProtocol>&& socket)
|
|
||||||
: impl_(boost::make_shared<impl_type>(
|
|
||||||
std::move(socket),
|
|
||||||
std::is_constructible<Executor,
|
|
||||||
decltype(std::declval<net::basic_stream_socket<
|
|
||||||
Protocol>&>().get_executor())>{}))
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -438,10 +438,10 @@ using is_async_stream = std::integral_constant<bool,
|
|||||||
|
|
||||||
@see close_socket
|
@see close_socket
|
||||||
*/
|
*/
|
||||||
template<class Protocol BOOST_ASIO_SVC_TPARAM>
|
template<class Protocol>
|
||||||
void
|
void
|
||||||
beast_close_socket(
|
beast_close_socket(
|
||||||
net::basic_socket<Protocol BOOST_ASIO_SVC_TPARAM>& sock)
|
net::basic_socket<Protocol>& sock)
|
||||||
{
|
{
|
||||||
boost::system::error_code ec;
|
boost::system::error_code ec;
|
||||||
sock.close(ec);
|
sock.close(ec);
|
||||||
|
@ -12,20 +12,17 @@
|
|||||||
|
|
||||||
#include <boost/beast/core/detail/config.hpp>
|
#include <boost/beast/core/detail/config.hpp>
|
||||||
#include <boost/beast/core/basic_stream.hpp>
|
#include <boost/beast/core/basic_stream.hpp>
|
||||||
|
#include <boost/asio/executor.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/ip/tcp.hpp>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
namespace beast {
|
namespace beast {
|
||||||
|
|
||||||
/** A TCP/IP stream socket with timeouts, rate limits, and executor.
|
/** A TCP/IP stream socket with timeouts, rate limits, and polymorphic executor.
|
||||||
|
|
||||||
@tparam Executor The type of executor to use for all completion
|
|
||||||
handlers which do not already have an associated executor.
|
|
||||||
|
|
||||||
@see basic_stream
|
@see basic_stream
|
||||||
*/
|
*/
|
||||||
template<class Executor>
|
using tcp_stream = basic_stream<net::ip::tcp, net::executor>;
|
||||||
using tcp_stream = basic_stream<net::ip::tcp, Executor>;
|
|
||||||
|
|
||||||
} // beast
|
} // beast
|
||||||
} // boost
|
} // boost
|
||||||
|
@ -30,6 +30,8 @@ using file_body = basic_file_body<file>;
|
|||||||
} // beast
|
} // beast
|
||||||
} // boost
|
} // boost
|
||||||
|
|
||||||
|
#ifndef BOOST_BEAST_NO_FILE_BODY_WIN32
|
||||||
#include <boost/beast/http/impl/file_body_win32.ipp>
|
#include <boost/beast/http/impl/file_body_win32.ipp>
|
||||||
|
#endif
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
@ -32,7 +32,7 @@ namespace beast {
|
|||||||
namespace http {
|
namespace http {
|
||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
template<class, class, bool, class>
|
template<class, class, class, bool, class>
|
||||||
class write_some_win32_op;
|
class write_some_win32_op;
|
||||||
} // detail
|
} // detail
|
||||||
|
|
||||||
@ -52,7 +52,7 @@ struct basic_file_body<file_win32>
|
|||||||
friend class reader;
|
friend class reader;
|
||||||
friend struct basic_file_body<file_win32>;
|
friend struct basic_file_body<file_win32>;
|
||||||
|
|
||||||
template<class, class, bool, class>
|
template<class, class, class, bool, class>
|
||||||
friend class detail::write_some_win32_op;
|
friend class detail::write_some_win32_op;
|
||||||
template<
|
template<
|
||||||
class Protocol, bool isRequest, class Fields>
|
class Protocol, bool isRequest, class Fields>
|
||||||
@ -101,7 +101,7 @@ struct basic_file_body<file_win32>
|
|||||||
|
|
||||||
class writer
|
class writer
|
||||||
{
|
{
|
||||||
template<class, class, bool, class>
|
template<class, class, class, bool, class>
|
||||||
friend class detail::write_some_win32_op;
|
friend class detail::write_some_win32_op;
|
||||||
template<
|
template<
|
||||||
class Protocol, bool isRequest, class Fields>
|
class Protocol, bool isRequest, class Fields>
|
||||||
@ -276,7 +276,6 @@ reset(file_win32&& file, error_code& ec)
|
|||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<class Unsigned>
|
template<class Unsigned>
|
||||||
inline
|
|
||||||
boost::winapi::DWORD_
|
boost::winapi::DWORD_
|
||||||
lowPart(Unsigned n)
|
lowPart(Unsigned n)
|
||||||
{
|
{
|
||||||
@ -286,7 +285,6 @@ lowPart(Unsigned n)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class Unsigned>
|
template<class Unsigned>
|
||||||
inline
|
|
||||||
boost::winapi::DWORD_
|
boost::winapi::DWORD_
|
||||||
highPart(Unsigned n, std::true_type)
|
highPart(Unsigned n, std::true_type)
|
||||||
{
|
{
|
||||||
@ -296,7 +294,6 @@ highPart(Unsigned n, std::true_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class Unsigned>
|
template<class Unsigned>
|
||||||
inline
|
|
||||||
boost::winapi::DWORD_
|
boost::winapi::DWORD_
|
||||||
highPart(Unsigned, std::false_type)
|
highPart(Unsigned, std::false_type)
|
||||||
{
|
{
|
||||||
@ -304,7 +301,6 @@ highPart(Unsigned, std::false_type)
|
|||||||
}
|
}
|
||||||
|
|
||||||
template<class Unsigned>
|
template<class Unsigned>
|
||||||
inline
|
|
||||||
boost::winapi::DWORD_
|
boost::winapi::DWORD_
|
||||||
highPart(Unsigned n)
|
highPart(Unsigned n)
|
||||||
{
|
{
|
||||||
@ -329,14 +325,17 @@ public:
|
|||||||
#if BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR
|
#if BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR
|
||||||
|
|
||||||
template<
|
template<
|
||||||
class Protocol, class Handler,
|
class Protocol, class Executor,
|
||||||
bool isRequest, class Fields>
|
class Handler, bool isRequest, class Fields>
|
||||||
class write_some_win32_op
|
class write_some_win32_op
|
||||||
: public beast::async_op_base<
|
: public beast::async_op_base<Handler, Executor>
|
||||||
Handler, typename net::basic_stream_socket<
|
|
||||||
Protocol>::executor_type>
|
|
||||||
{
|
{
|
||||||
net::basic_stream_socket<Protocol>& sock_;
|
static_assert(
|
||||||
|
std::is_same<Executor, net::io_context::executor_type>::value,
|
||||||
|
"Executor must be net::io_context::executor_type");
|
||||||
|
|
||||||
|
net::basic_stream_socket<
|
||||||
|
Protocol, Executor>& sock_;
|
||||||
serializer<isRequest,
|
serializer<isRequest,
|
||||||
basic_file_body<file_win32>, Fields>& sr_;
|
basic_file_body<file_win32>, Fields>& sr_;
|
||||||
std::size_t bytes_transferred_ = 0;
|
std::size_t bytes_transferred_ = 0;
|
||||||
@ -346,14 +345,14 @@ public:
|
|||||||
template<class Handler_>
|
template<class Handler_>
|
||||||
write_some_win32_op(
|
write_some_win32_op(
|
||||||
Handler_&& h,
|
Handler_&& h,
|
||||||
net::basic_stream_socket<Protocol>& s,
|
net::basic_stream_socket<
|
||||||
|
Protocol, Executor>& s,
|
||||||
serializer<isRequest,
|
serializer<isRequest,
|
||||||
basic_file_body<file_win32>,Fields>& sr)
|
basic_file_body<file_win32>,Fields>& sr)
|
||||||
: async_op_base<
|
: async_op_base<
|
||||||
Handler, typename net::basic_stream_socket<
|
Handler, Executor>(
|
||||||
Protocol>::executor_type>(
|
std::forward<Handler_>(h),
|
||||||
std::forward<Handler_>(h),
|
s.get_executor())
|
||||||
s.get_executor())
|
|
||||||
, sock_(s)
|
, sock_(s)
|
||||||
, sr_(sr)
|
, sr_(sr)
|
||||||
{
|
{
|
||||||
@ -442,10 +441,13 @@ public:
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
template<class Protocol, bool isRequest, class Fields>
|
template<
|
||||||
|
class Protocol, class Executor,
|
||||||
|
bool isRequest, class Fields>
|
||||||
std::size_t
|
std::size_t
|
||||||
write_some(
|
write_some(
|
||||||
net::basic_stream_socket<Protocol>& sock,
|
net::basic_stream_socket<
|
||||||
|
Protocol, Executor>& sock,
|
||||||
serializer<isRequest,
|
serializer<isRequest,
|
||||||
basic_file_body<file_win32>, Fields>& sr,
|
basic_file_body<file_win32>, Fields>& sr,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
@ -509,21 +511,23 @@ write_some(
|
|||||||
#if BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR
|
#if BOOST_ASIO_HAS_WINDOWS_OVERLAPPED_PTR
|
||||||
|
|
||||||
template<
|
template<
|
||||||
class Protocol,
|
class Protocol, class Executor,
|
||||||
bool isRequest, class Fields,
|
bool isRequest, class Fields,
|
||||||
class WriteHandler>
|
class WriteHandler>
|
||||||
BOOST_ASIO_INITFN_RESULT_TYPE(
|
BOOST_ASIO_INITFN_RESULT_TYPE(
|
||||||
WriteHandler, void(error_code, std::size_t))
|
WriteHandler, void(error_code, std::size_t))
|
||||||
async_write_some(
|
async_write_some(
|
||||||
net::basic_stream_socket<Protocol>& sock,
|
net::basic_stream_socket<
|
||||||
|
Protocol, Executor>& sock,
|
||||||
serializer<isRequest,
|
serializer<isRequest,
|
||||||
basic_file_body<file_win32>, Fields>& sr,
|
basic_file_body<file_win32>, Fields>& sr,
|
||||||
WriteHandler&& handler)
|
WriteHandler&& handler)
|
||||||
{
|
{
|
||||||
|
|
||||||
BOOST_BEAST_HANDLER_INIT(
|
BOOST_BEAST_HANDLER_INIT(
|
||||||
WriteHandler, void(error_code, std::size_t));
|
WriteHandler, void(error_code, std::size_t));
|
||||||
detail::write_some_win32_op<
|
detail::write_some_win32_op<
|
||||||
Protocol,
|
Protocol, Executor,
|
||||||
BOOST_ASIO_HANDLER_TYPE(WriteHandler,
|
BOOST_ASIO_HANDLER_TYPE(WriteHandler,
|
||||||
void(error_code, std::size_t)),
|
void(error_code, std::size_t)),
|
||||||
isRequest, Fields>{
|
isRequest, Fields>{
|
||||||
|
@ -19,7 +19,15 @@
|
|||||||
#include <boost/beast/core/static_string.hpp>
|
#include <boost/beast/core/static_string.hpp>
|
||||||
#include <boost/asio/buffer.hpp>
|
#include <boost/asio/buffer.hpp>
|
||||||
#include <boost/assert.hpp>
|
#include <boost/assert.hpp>
|
||||||
|
// This is for <boost/endian/buffers.hpp>
|
||||||
|
#if BOOST_WORKAROUND(BOOST_MSVC, > 0)
|
||||||
|
# pragma warning (push)
|
||||||
|
# pragma warning (disable: 4127) // conditional expression is constant
|
||||||
|
#endif
|
||||||
#include <boost/endian/buffers.hpp>
|
#include <boost/endian/buffers.hpp>
|
||||||
|
#if BOOST_WORKAROUND(BOOST_MSVC, > 0)
|
||||||
|
# pragma warning (pop)
|
||||||
|
#endif
|
||||||
#include <cstdint>
|
#include <cstdint>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
|
@ -103,7 +103,7 @@ struct stream<NextLayer, deflateSupported>::impl_type
|
|||||||
template<class... Args>
|
template<class... Args>
|
||||||
impl_type(Args&&... args)
|
impl_type(Args&&... args)
|
||||||
: stream(std::forward<Args>(args)...)
|
: stream(std::forward<Args>(args)...)
|
||||||
, timer(stream.get_executor().context())
|
, timer(stream.get_executor())
|
||||||
{
|
{
|
||||||
timeout_opt.handshake_timeout = none();
|
timeout_opt.handshake_timeout = none();
|
||||||
timeout_opt.idle_timeout = none();
|
timeout_opt.idle_timeout = none();
|
||||||
|
@ -25,14 +25,18 @@ namespace websocket {
|
|||||||
|
|
||||||
namespace detail {
|
namespace detail {
|
||||||
|
|
||||||
template<class Handler>
|
template<
|
||||||
|
class Protocol, class Executor,
|
||||||
|
class Handler>
|
||||||
class teardown_tcp_op
|
class teardown_tcp_op
|
||||||
: public beast::async_op_base<
|
: public beast::async_op_base<
|
||||||
Handler, beast::executor_type<
|
Handler, beast::executor_type<
|
||||||
net::ip::tcp::socket>>
|
net::basic_stream_socket<
|
||||||
|
Protocol, Executor>>>
|
||||||
, public net::coroutine
|
, public net::coroutine
|
||||||
{
|
{
|
||||||
using socket_type = net::ip::tcp::socket;
|
using socket_type =
|
||||||
|
net::basic_stream_socket<Protocol, Executor>;
|
||||||
|
|
||||||
socket_type& s_;
|
socket_type& s_;
|
||||||
role_type role_;
|
role_type role_;
|
||||||
@ -46,8 +50,10 @@ public:
|
|||||||
role_type role)
|
role_type role)
|
||||||
: async_op_base<Handler,
|
: async_op_base<Handler,
|
||||||
beast::executor_type<
|
beast::executor_type<
|
||||||
net::ip::tcp::socket>>(
|
net::basic_stream_socket<
|
||||||
std::forward<Handler_>(h), s.get_executor())
|
Protocol, Executor>>>(
|
||||||
|
std::forward<Handler_>(h),
|
||||||
|
s.get_executor())
|
||||||
, s_(s)
|
, s_(s)
|
||||||
, role_(role)
|
, role_(role)
|
||||||
{
|
{
|
||||||
@ -60,7 +66,6 @@ public:
|
|||||||
std::size_t bytes_transferred = 0,
|
std::size_t bytes_transferred = 0,
|
||||||
bool cont = true)
|
bool cont = true)
|
||||||
{
|
{
|
||||||
using tcp = net::ip::tcp;
|
|
||||||
BOOST_ASIO_CORO_REENTER(*this)
|
BOOST_ASIO_CORO_REENTER(*this)
|
||||||
{
|
{
|
||||||
nb_ = s_.non_blocking();
|
nb_ = s_.non_blocking();
|
||||||
@ -68,7 +73,7 @@ public:
|
|||||||
if(ec)
|
if(ec)
|
||||||
goto upcall;
|
goto upcall;
|
||||||
if(role_ == role_type::server)
|
if(role_ == role_type::server)
|
||||||
s_.shutdown(tcp::socket::shutdown_send, ec);
|
s_.shutdown(net::socket_base::shutdown_send, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
goto upcall;
|
goto upcall;
|
||||||
for(;;)
|
for(;;)
|
||||||
@ -81,7 +86,7 @@ public:
|
|||||||
{
|
{
|
||||||
BOOST_ASIO_CORO_YIELD
|
BOOST_ASIO_CORO_YIELD
|
||||||
s_.async_wait(
|
s_.async_wait(
|
||||||
net::ip::tcp::socket::wait_read,
|
net::socket_base::wait_read,
|
||||||
beast::detail::bind_continuation(std::move(*this)));
|
beast::detail::bind_continuation(std::move(*this)));
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -100,7 +105,7 @@ public:
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if(role_ == role_type::client)
|
if(role_ == role_type::client)
|
||||||
s_.shutdown(tcp::socket::shutdown_send, ec);
|
s_.shutdown(net::socket_base::shutdown_send, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
goto upcall;
|
goto upcall;
|
||||||
s_.close(ec);
|
s_.close(ec);
|
||||||
@ -124,15 +129,17 @@ public:
|
|||||||
|
|
||||||
//------------------------------------------------------------------------------
|
//------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
template<class Protocol, class Executor>
|
||||||
void
|
void
|
||||||
teardown(
|
teardown(
|
||||||
role_type role,
|
role_type role,
|
||||||
net::ip::tcp::socket& socket,
|
net::basic_stream_socket<
|
||||||
|
Protocol, Executor>& socket,
|
||||||
error_code& ec)
|
error_code& ec)
|
||||||
{
|
{
|
||||||
if(role == role_type::server)
|
if(role == role_type::server)
|
||||||
socket.shutdown(
|
socket.shutdown(
|
||||||
net::ip::tcp::socket::shutdown_send, ec);
|
net::socket_base::shutdown_send, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return;
|
return;
|
||||||
for(;;)
|
for(;;)
|
||||||
@ -156,25 +163,32 @@ teardown(
|
|||||||
}
|
}
|
||||||
if(role == role_type::client)
|
if(role == role_type::client)
|
||||||
socket.shutdown(
|
socket.shutdown(
|
||||||
net::ip::tcp::socket::shutdown_send, ec);
|
net::socket_base::shutdown_send, ec);
|
||||||
if(ec)
|
if(ec)
|
||||||
return;
|
return;
|
||||||
socket.close(ec);
|
socket.close(ec);
|
||||||
}
|
}
|
||||||
|
|
||||||
template<class TeardownHandler>
|
template<
|
||||||
|
class Protocol, class Executor,
|
||||||
|
class TeardownHandler>
|
||||||
void
|
void
|
||||||
async_teardown(
|
async_teardown(
|
||||||
role_type role,
|
role_type role,
|
||||||
net::ip::tcp::socket& socket,
|
net::basic_stream_socket<
|
||||||
|
Protocol, Executor>& socket,
|
||||||
TeardownHandler&& handler)
|
TeardownHandler&& handler)
|
||||||
{
|
{
|
||||||
static_assert(beast::detail::is_invocable<
|
static_assert(beast::detail::is_invocable<
|
||||||
TeardownHandler, void(error_code)>::value,
|
TeardownHandler, void(error_code)>::value,
|
||||||
"TeardownHandler requirements not met");
|
"TeardownHandler requirements not met");
|
||||||
detail::teardown_tcp_op<typename std::decay<
|
detail::teardown_tcp_op<
|
||||||
TeardownHandler>::type>(std::forward<
|
Protocol,
|
||||||
TeardownHandler>(handler), socket, role);
|
Executor,
|
||||||
|
typename std::decay<TeardownHandler>::type>(
|
||||||
|
std::forward<TeardownHandler>(handler),
|
||||||
|
socket,
|
||||||
|
role);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // websocket
|
} // websocket
|
||||||
|
@ -80,13 +80,12 @@ class frame_test;
|
|||||||
To declare the @ref stream object with a @ref tcp_stream in a
|
To declare the @ref stream object with a @ref tcp_stream in a
|
||||||
multi-threaded asynchronous program using a strand, you may write:
|
multi-threaded asynchronous program using a strand, you may write:
|
||||||
@code
|
@code
|
||||||
websocket::stream<tcp_stream<
|
websocket::stream<tcp_stream> ws{net::io_context::strand(ioc)};
|
||||||
net::io_context::strand>> ws{net::io_context::strand(ioc)};
|
|
||||||
@endcode
|
@endcode
|
||||||
Alternatively, for a single-threaded or synchronous application
|
Alternatively, for a single-threaded or synchronous application
|
||||||
you may write:
|
you may write:
|
||||||
@code
|
@code
|
||||||
websocket::stream<tcp_stream<net::io_context::executor_type>> ws(ioc);
|
websocket::stream<tcp_stream> ws(ioc);
|
||||||
@endcode
|
@endcode
|
||||||
|
|
||||||
@tparam NextLayer The type representing the next layer, to which
|
@tparam NextLayer The type representing the next layer, to which
|
||||||
|
@ -13,7 +13,7 @@
|
|||||||
#include <boost/beast/core/detail/config.hpp>
|
#include <boost/beast/core/detail/config.hpp>
|
||||||
#include <boost/beast/core/error.hpp>
|
#include <boost/beast/core/error.hpp>
|
||||||
#include <boost/beast/websocket/role.hpp>
|
#include <boost/beast/websocket/role.hpp>
|
||||||
#include <boost/asio/ip/tcp.hpp>
|
#include <boost/asio/basic_stream_socket.hpp>
|
||||||
#include <type_traits>
|
#include <type_traits>
|
||||||
|
|
||||||
namespace boost {
|
namespace boost {
|
||||||
@ -125,11 +125,12 @@ namespace websocket {
|
|||||||
|
|
||||||
@param ec Set to the error if any occurred.
|
@param ec Set to the error if any occurred.
|
||||||
*/
|
*/
|
||||||
BOOST_BEAST_DECL
|
template<class Protocol, class Executor>
|
||||||
void
|
void
|
||||||
teardown(
|
teardown(
|
||||||
role_type role,
|
role_type role,
|
||||||
net::ip::tcp::socket& socket,
|
net::basic_stream_socket<
|
||||||
|
Protocol, Executor>& socket,
|
||||||
error_code& ec);
|
error_code& ec);
|
||||||
|
|
||||||
/** Start tearing down a `net::ip::tcp::socket`.
|
/** Start tearing down a `net::ip::tcp::socket`.
|
||||||
@ -159,11 +160,14 @@ teardown(
|
|||||||
manner equivalent to using net::io_context::post().
|
manner equivalent to using net::io_context::post().
|
||||||
|
|
||||||
*/
|
*/
|
||||||
template<class TeardownHandler>
|
template<
|
||||||
|
class Protocol, class Executor,
|
||||||
|
class TeardownHandler>
|
||||||
void
|
void
|
||||||
async_teardown(
|
async_teardown(
|
||||||
role_type role,
|
role_type role,
|
||||||
net::ip::tcp::socket& socket,
|
net::basic_stream_socket<
|
||||||
|
Protocol, Executor>& socket,
|
||||||
TeardownHandler&& handler);
|
TeardownHandler&& handler);
|
||||||
|
|
||||||
} // websocket
|
} // websocket
|
||||||
|
@ -24,6 +24,7 @@ add_executable (tests-beast-core
|
|||||||
_detail_bind_continuation.cpp
|
_detail_bind_continuation.cpp
|
||||||
_detail_buffer.cpp
|
_detail_buffer.cpp
|
||||||
_detail_clamp.cpp
|
_detail_clamp.cpp
|
||||||
|
_detail_get_io_context.cpp
|
||||||
_detail_is_invocable.cpp
|
_detail_is_invocable.cpp
|
||||||
_detail_read.cpp
|
_detail_read.cpp
|
||||||
_detail_sha1.cpp
|
_detail_sha1.cpp
|
||||||
|
@ -12,6 +12,7 @@ local SOURCES =
|
|||||||
_detail_bind_continuation.cpp
|
_detail_bind_continuation.cpp
|
||||||
_detail_buffer.cpp
|
_detail_buffer.cpp
|
||||||
_detail_clamp.cpp
|
_detail_clamp.cpp
|
||||||
|
_detail_get_io_context.cpp
|
||||||
_detail_is_invocable.cpp
|
_detail_is_invocable.cpp
|
||||||
_detail_read.cpp
|
_detail_read.cpp
|
||||||
_detail_sha1.cpp
|
_detail_sha1.cpp
|
||||||
|
57
test/beast/core/_detail_get_io_context.cpp
Normal file
57
test/beast/core/_detail_get_io_context.cpp
Normal file
@ -0,0 +1,57 @@
|
|||||||
|
//
|
||||||
|
// 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
|
||||||
|
//
|
||||||
|
|
||||||
|
#include <boost/beast/core/detail/config.hpp>
|
||||||
|
#include <boost/beast/core/make_strand.hpp>
|
||||||
|
#include <boost/beast/core/detail/get_io_context.hpp>
|
||||||
|
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||||
|
#include <boost/asio/strand.hpp>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace beast {
|
||||||
|
namespace detail {
|
||||||
|
|
||||||
|
class get_io_context_test : public beast::unit_test::suite
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void
|
||||||
|
testFunction()
|
||||||
|
{
|
||||||
|
struct none
|
||||||
|
{
|
||||||
|
};
|
||||||
|
|
||||||
|
net::io_context ioc;
|
||||||
|
BEAST_EXPECT(get_io_context(5) == nullptr);
|
||||||
|
BEAST_EXPECT(get_io_context(none{}) == nullptr);
|
||||||
|
BEAST_EXPECT(get_io_context(ioc) == &ioc);
|
||||||
|
BEAST_EXPECT(get_io_context(ioc.get_executor()) == &ioc);
|
||||||
|
BEAST_EXPECT(get_io_context(make_strand(ioc)) == &ioc);
|
||||||
|
BEAST_EXPECT(get_io_context(net::executor(ioc.get_executor())) == &ioc);
|
||||||
|
#if 0
|
||||||
|
// VFALCO FIXME
|
||||||
|
BEAST_EXPECT(
|
||||||
|
get_io_context(
|
||||||
|
net::strand<net::executor>(
|
||||||
|
net::executor(ioc.get_executor()))) == &ioc);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
run() override
|
||||||
|
{
|
||||||
|
testFunction();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BEAST_DEFINE_TESTSUITE(beast,core,get_io_context);
|
||||||
|
|
||||||
|
} // detail
|
||||||
|
} // beast
|
||||||
|
} // boost
|
@ -303,7 +303,6 @@ private:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
} // (anon)
|
} // (anon)
|
||||||
|
|
||||||
class basic_stream_test
|
class basic_stream_test
|
||||||
@ -319,9 +318,6 @@ public:
|
|||||||
void
|
void
|
||||||
testSpecialMembers()
|
testSpecialMembers()
|
||||||
{
|
{
|
||||||
using stream_type = tcp_stream<
|
|
||||||
net::io_context::executor_type>;
|
|
||||||
|
|
||||||
net::io_context ioc;
|
net::io_context ioc;
|
||||||
|
|
||||||
// net::io_context::executor_type
|
// net::io_context::executor_type
|
||||||
@ -332,7 +328,8 @@ public:
|
|||||||
basic_stream<tcp, executor> s2(ex);
|
basic_stream<tcp, executor> s2(ex);
|
||||||
basic_stream<tcp, executor> s3(ioc, tcp::v4());
|
basic_stream<tcp, executor> s3(ioc, tcp::v4());
|
||||||
basic_stream<tcp, executor> s4(std::move(s1));
|
basic_stream<tcp, executor> s4(std::move(s1));
|
||||||
s2.socket() = tcp::socket(ioc);
|
s2.socket() =
|
||||||
|
net::basic_stream_socket<tcp, executor>(ioc);
|
||||||
BEAST_EXPECT(s1.get_executor() == ex);
|
BEAST_EXPECT(s1.get_executor() == ex);
|
||||||
BEAST_EXPECT(s2.get_executor() == ex);
|
BEAST_EXPECT(s2.get_executor() == ex);
|
||||||
BEAST_EXPECT(s3.get_executor() == ex);
|
BEAST_EXPECT(s3.get_executor() == ex);
|
||||||
@ -358,14 +355,19 @@ public:
|
|||||||
basic_stream<tcp, strand> s1(ex);
|
basic_stream<tcp, strand> s1(ex);
|
||||||
basic_stream<tcp, strand> s2(ex, tcp::v4());
|
basic_stream<tcp, strand> s2(ex, tcp::v4());
|
||||||
basic_stream<tcp, strand> s3(std::move(s1));
|
basic_stream<tcp, strand> s3(std::move(s1));
|
||||||
s2.socket() = tcp::socket(ioc);
|
#if 0
|
||||||
|
s2.socket() = net::basic_stream_socket<
|
||||||
|
tcp, strand>(ioc);
|
||||||
|
#endif
|
||||||
BEAST_EXPECT(s1.get_executor() == ex);
|
BEAST_EXPECT(s1.get_executor() == ex);
|
||||||
BEAST_EXPECT(s2.get_executor() == ex);
|
BEAST_EXPECT(s2.get_executor() == ex);
|
||||||
BEAST_EXPECT(s3.get_executor() == ex);
|
BEAST_EXPECT(s3.get_executor() == ex);
|
||||||
|
|
||||||
|
#if 0
|
||||||
BEAST_EXPECT((! static_cast<
|
BEAST_EXPECT((! static_cast<
|
||||||
basic_stream<tcp, strand> const&>(
|
basic_stream<tcp, strand> const&>(
|
||||||
s2).socket().is_open()));
|
s2).socket().is_open()));
|
||||||
|
#endif
|
||||||
|
|
||||||
test_sync_stream<
|
test_sync_stream<
|
||||||
basic_stream<
|
basic_stream<
|
||||||
@ -378,6 +380,7 @@ public:
|
|||||||
|
|
||||||
// construction from existing socket
|
// construction from existing socket
|
||||||
|
|
||||||
|
#if 0
|
||||||
{
|
{
|
||||||
tcp::socket sock(ioc);
|
tcp::socket sock(ioc);
|
||||||
basic_stream<tcp, executor> stream(std::move(sock));
|
basic_stream<tcp, executor> stream(std::move(sock));
|
||||||
@ -387,22 +390,13 @@ public:
|
|||||||
tcp::socket sock(ioc);
|
tcp::socket sock(ioc);
|
||||||
basic_stream<tcp, strand> stream(std::move(sock));
|
basic_stream<tcp, strand> stream(std::move(sock));
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
struct other_type
|
|
||||||
{
|
|
||||||
};
|
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT(! std::is_constructible<
|
|
||||||
stream_type, other_type>::value);
|
|
||||||
|
|
||||||
BOOST_STATIC_ASSERT(! std::is_constructible<
|
|
||||||
stream_type, other_type, tcp::socket>::value);
|
|
||||||
|
|
||||||
// layers
|
// layers
|
||||||
|
|
||||||
{
|
{
|
||||||
net::socket_base::keep_alive opt;
|
net::socket_base::keep_alive opt;
|
||||||
stream_type s(ioc);
|
tcp_stream s(ioc);
|
||||||
s.socket().open(tcp::v4());
|
s.socket().open(tcp::v4());
|
||||||
s.socket().get_option(opt);
|
s.socket().get_option(opt);
|
||||||
BEAST_EXPECT(! opt.value());
|
BEAST_EXPECT(! opt.value());
|
||||||
@ -450,7 +444,7 @@ public:
|
|||||||
void
|
void
|
||||||
testRead()
|
testRead()
|
||||||
{
|
{
|
||||||
using stream_type = tcp_stream<
|
using stream_type = basic_stream<tcp,
|
||||||
net::io_context::executor_type>;
|
net::io_context::executor_type>;
|
||||||
|
|
||||||
char buf[4];
|
char buf[4];
|
||||||
@ -585,7 +579,7 @@ public:
|
|||||||
void
|
void
|
||||||
testWrite()
|
testWrite()
|
||||||
{
|
{
|
||||||
using stream_type = tcp_stream<
|
using stream_type = basic_stream<tcp,
|
||||||
net::io_context::executor_type>;
|
net::io_context::executor_type>;
|
||||||
|
|
||||||
char buf[4];
|
char buf[4];
|
||||||
@ -667,7 +661,7 @@ public:
|
|||||||
void
|
void
|
||||||
testConnect()
|
testConnect()
|
||||||
{
|
{
|
||||||
using stream_type = tcp_stream<
|
using stream_type = basic_stream<tcp,
|
||||||
net::io_context::executor_type>;
|
net::io_context::executor_type>;
|
||||||
|
|
||||||
struct range
|
struct range
|
||||||
@ -1057,7 +1051,7 @@ public:
|
|||||||
void
|
void
|
||||||
testMembers()
|
testMembers()
|
||||||
{
|
{
|
||||||
using stream_type = tcp_stream<
|
using stream_type = basic_stream<tcp,
|
||||||
net::io_context::executor_type>;
|
net::io_context::executor_type>;
|
||||||
|
|
||||||
class handler
|
class handler
|
||||||
@ -1184,7 +1178,7 @@ public:
|
|||||||
return {};
|
return {};
|
||||||
}
|
}
|
||||||
|
|
||||||
void process_http_1 (tcp_stream<net::io_context::executor_type>& stream, net::yield_context yield)
|
void process_http_1 (tcp_stream& stream, net::yield_context yield)
|
||||||
{
|
{
|
||||||
flat_buffer buffer;
|
flat_buffer buffer;
|
||||||
http::request<http::empty_body> req;
|
http::request<http::empty_body> req;
|
||||||
@ -1201,7 +1195,7 @@ public:
|
|||||||
http::async_write (stream, res, yield);
|
http::async_write (stream, res, yield);
|
||||||
}
|
}
|
||||||
|
|
||||||
void process_http_2 (tcp_stream<net::io_context::executor_type>& stream, net::yield_context yield)
|
void process_http_2 (tcp_stream& stream, net::yield_context yield)
|
||||||
{
|
{
|
||||||
flat_buffer buffer;
|
flat_buffer buffer;
|
||||||
http::request<http::empty_body> req;
|
http::request<http::empty_body> req;
|
||||||
|
@ -9,3 +9,37 @@
|
|||||||
|
|
||||||
// Test that header file is self-contained.
|
// Test that header file is self-contained.
|
||||||
#include <boost/beast/core/tcp_stream.hpp>
|
#include <boost/beast/core/tcp_stream.hpp>
|
||||||
|
|
||||||
|
#include <boost/beast/_experimental/unit_test/suite.hpp>
|
||||||
|
|
||||||
|
namespace boost {
|
||||||
|
namespace beast {
|
||||||
|
|
||||||
|
class tcp_stream_test
|
||||||
|
: public beast::unit_test::suite
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using tcp = net::ip::tcp;
|
||||||
|
|
||||||
|
void
|
||||||
|
testStream()
|
||||||
|
{
|
||||||
|
net::io_context ioc;
|
||||||
|
{
|
||||||
|
tcp::socket s(ioc);
|
||||||
|
tcp_stream s1(std::move(s));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
run()
|
||||||
|
{
|
||||||
|
testStream();
|
||||||
|
pass();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
BEAST_DEFINE_TESTSUITE(beast,core,tcp_stream);
|
||||||
|
|
||||||
|
} // beast
|
||||||
|
} // boost
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
// Test that header file is self-contained.
|
// Test that header file is self-contained.
|
||||||
#include <boost/beast/websocket/stream.hpp>
|
#include <boost/beast/websocket/stream.hpp>
|
||||||
|
|
||||||
|
#include <boost/beast/core/make_strand.hpp>
|
||||||
#include <boost/beast/core/tcp_stream.hpp>
|
#include <boost/beast/core/tcp_stream.hpp>
|
||||||
#include <boost/asio/strand.hpp>
|
#include <boost/asio/strand.hpp>
|
||||||
|
|
||||||
@ -157,11 +158,10 @@ public:
|
|||||||
{
|
{
|
||||||
net::io_context ioc;
|
net::io_context ioc;
|
||||||
{
|
{
|
||||||
websocket::stream<tcp_stream<
|
websocket::stream<tcp_stream> ws{make_strand(ioc)};
|
||||||
net::io_context::strand>> ws{net::io_context::strand(ioc)};
|
|
||||||
}
|
}
|
||||||
{
|
{
|
||||||
websocket::stream<tcp_stream<net::io_context::executor_type>> ws(ioc);
|
websocket::stream<tcp_stream> ws(ioc);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@ public:
|
|||||||
run() override
|
run() override
|
||||||
{
|
{
|
||||||
testJavadoc();
|
testJavadoc();
|
||||||
|
pass();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -59,8 +59,8 @@ boost::ignore_unused(ec);
|
|||||||
{
|
{
|
||||||
//[ws_snippet_6
|
//[ws_snippet_6
|
||||||
std::string const host = "example.com";
|
std::string const host = "example.com";
|
||||||
net::ip::tcp::resolver r{ioc};
|
net::ip::tcp::resolver r(ioc);
|
||||||
stream<tcp_stream<net::io_context::executor_type>> ws{ioc};
|
stream<tcp_stream> ws(ioc);
|
||||||
auto const results = r.resolve(host, "ws");
|
auto const results = r.resolve(host, "ws");
|
||||||
connect(get_lowest_layer(ws), results.begin(), results.end());
|
connect(get_lowest_layer(ws), results.begin(), results.end());
|
||||||
//]
|
//]
|
||||||
@ -69,7 +69,7 @@ boost::ignore_unused(ec);
|
|||||||
{
|
{
|
||||||
//[ws_snippet_7
|
//[ws_snippet_7
|
||||||
net::ip::tcp::acceptor acceptor{ioc};
|
net::ip::tcp::acceptor acceptor{ioc};
|
||||||
stream<tcp_stream<net::io_context::executor_type>> ws{acceptor.get_executor().context()};
|
stream<tcp_stream> ws{acceptor.get_executor()};
|
||||||
acceptor.accept(get_lowest_layer(ws).socket());
|
acceptor.accept(get_lowest_layer(ws).socket());
|
||||||
//]
|
//]
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user