diff --git a/doc/quickref.xml b/doc/quickref.xml index d025b356..7662a357 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -85,6 +85,7 @@ ping_data stream reason_string + teardown_tag Options diff --git a/doc/websocket.qbk b/doc/websocket.qbk index da2808cc..ff9c235e 100644 --- a/doc/websocket.qbk +++ b/doc/websocket.qbk @@ -66,7 +66,7 @@ both Boost.Asio and the WebSocket protocol specification described in -[section:creating Creating the socket] +[section:creation Creation] The interface to Beast's WebSocket implementation is a single template class [link beast.ref.websocket__stream `beast::websocket::stream`] which @@ -75,24 +75,40 @@ of [link beast.types.streams.SyncStream [*`SyncReadStream`]] if synchronous operations are performed, or [link beast.types.streams.AsyncStream [*`AsyncStream`]] if asynchronous operations are performed, or both. Arguments supplied during construction are -passed to next layer's constructor. Here we declare two websockets which have -ownership of the next layer: +passed to next layer's constructor. Here we declare a websocket stream over +a TCP/IP socket with ownership of the socket: ``` boost::asio::io_service ios; beast::websocket::stream ws(ios); - -boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); -beast::websocket::stream< - boost::asio::ssl::stream> wss(ios, ctx); ``` +[heading Using SSL] + +To use WebSockets over SSL, choose an SSL stream for the next layer template +argument when constructing the stream. +``` +#include +#include +#include + +boost::asio::io_service ios; +boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); +beast::websocket::stream ws(ios, ctx); +``` + +[note + When creating websocket stream objects using SSL, it is necessary + to include the file ``. +] + +[heading Non-owning references] + For servers that can handshake in multiple protocols, it may be desired to wrap an object that already exists. This socket can be moved in: ``` boost::asio::ip::tcp::socket&& sock; ... - beast::websocket::stream< - boost::asio::ip::tcp::socket> ws(std::move(sock)); + beast::websocket::stream ws(std::move(sock)); ``` Or, the wrapper can be constructed with a non-owning reference. In @@ -108,8 +124,7 @@ The layer being wrapped can be accessed through the websocket's "next layer", permitting callers to interact directly with its interface. ``` boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); - beast::websocket::stream< - boost::asio::ssl::stream> ws(ios, ctx); + beast::websocket::stream> ws(ios, ctx); ... ws.next_layer().shutdown(); // ssl::stream shutdown ``` diff --git a/extras/beast/test/fail_stream.hpp b/extras/beast/test/fail_stream.hpp index 1c3a34e2..47742d06 100644 --- a/extras/beast/test/fail_stream.hpp +++ b/extras/beast/test/fail_stream.hpp @@ -161,19 +161,21 @@ public: friend void - teardown(fail_stream& stream, - boost::system::error_code& ec) + teardown(websocket::teardown_tag, + fail_stream& stream, + boost::system::error_code& ec) { if(stream.pfc_->fail(ec)) return; - websocket_helpers::call_teardown(stream.next_layer(), ec); + beast::websocket_helpers::call_teardown(stream.next_layer(), ec); } template friend void - async_teardown(fail_stream& stream, - TeardownHandler&& handler) + async_teardown(websocket::teardown_tag, + fail_stream& stream, + TeardownHandler&& handler) { error_code ec; if(stream.pfc_->fail(ec)) @@ -182,7 +184,7 @@ public: bind_handler(std::move(handler), ec)); return; } - websocket_helpers::call_async_teardown( + beast::websocket_helpers::call_async_teardown( stream.next_layer(), std::forward(handler)); } }; diff --git a/include/beast/websocket/impl/ssl.ipp b/include/beast/websocket/impl/ssl.ipp index 681ecd34..a7cd3259 100644 --- a/include/beast/websocket/impl/ssl.ipp +++ b/include/beast/websocket/impl/ssl.ipp @@ -129,7 +129,7 @@ operator()(error_code ec, bool again) template void -teardown( +teardown(teardown_tag, boost::asio::ssl::stream& stream, error_code& ec) { @@ -138,7 +138,7 @@ teardown( template void -async_teardown( +async_teardown(teardown_tag, boost::asio::ssl::stream& stream, TeardownHandler&& handler) { diff --git a/include/beast/websocket/impl/teardown.ipp b/include/beast/websocket/impl/teardown.ipp index fa7133b2..1d0389b0 100644 --- a/include/beast/websocket/impl/teardown.ipp +++ b/include/beast/websocket/impl/teardown.ipp @@ -128,7 +128,7 @@ operator()(error_code ec, std::size_t, bool again) inline void -teardown( +teardown(teardown_tag, boost::asio::ip::tcp::socket& socket, error_code& ec) { @@ -151,7 +151,7 @@ teardown( template inline void -async_teardown( +async_teardown(teardown_tag, boost::asio::ip::tcp::socket& socket, TeardownHandler&& handler) { diff --git a/include/beast/websocket/ssl.hpp b/include/beast/websocket/ssl.hpp index 5ed57222..ef94ed9a 100644 --- a/include/beast/websocket/ssl.hpp +++ b/include/beast/websocket/ssl.hpp @@ -31,7 +31,7 @@ namespace websocket { */ template void -teardown( +teardown(teardown_tag, boost::asio::ssl::stream& stream, error_code& ec); @@ -62,7 +62,7 @@ teardown( template inline void -async_teardown( +async_teardown(teardown_tag, boost::asio::ssl::stream& stream, TeardownHandler&& handler); diff --git a/include/beast/websocket/teardown.hpp b/include/beast/websocket/teardown.hpp index ecb6dba3..95a54f5e 100644 --- a/include/beast/websocket/teardown.hpp +++ b/include/beast/websocket/teardown.hpp @@ -13,8 +13,17 @@ #include namespace beast { + namespace websocket { +/** Tag type used to find teardown and async_teardown overloads + + Overloads of @ref teardown and @async_teardown for user defined + types must take a value of type @ref teardown_tag in the first + argument in order to be found by the implementation. +*/ +struct teardown_tag {}; + /** Tear down a connection. This tears down a connection. The implementation will call @@ -30,7 +39,19 @@ namespace websocket { */ template void -teardown(Socket& socket, error_code& ec) = delete; +teardown(teardown_tag, Socket& socket, error_code& ec) +{ +/* + If you are trying to use OpenSSL and this goes off, you need to + add an include for . + + If you are creating an instance of beast::websocket::stream with your + own user defined type, you must provide an overload of teardown with + the corresponding signature (including the teardown_tag). +*/ + static_assert(sizeof(Socket)==-1, + "Unknown Socket type in teardown."); +}; /** Start tearing down a connection. @@ -49,7 +70,8 @@ teardown(Socket& socket, error_code& ec) = delete; function signature of the handler must be: @code void handler( error_code const& error // result of operation - ); @endcode + ); + @endcode Regardless of whether the asynchronous operation completes immediately or not, the handler will not be invoked from within this function. Invocation of the handler will be performed in a @@ -58,57 +80,19 @@ teardown(Socket& socket, error_code& ec) = delete; */ template void -async_teardown(Socket& socket, TeardownHandler&& handler) = delete; +async_teardown(teardown_tag, Socket& socket, TeardownHandler&& handler) +{ +/* + If you are trying to use OpenSSL and this goes off, you need to + add an include for . -//------------------------------------------------------------------------------ - -/** Tear down a `boost::asio::ip::tcp::socket`. - - This tears down a connection. The implementation will call - the overload of this function based on the `Stream` parameter - used to consruct the socket. When `Stream` is a user defined - type, and not a `boost::asio::ip::tcp::socket` or any - `boost::asio::ssl::stream`, callers are responsible for - providing a suitable overload of this function. - - @param socket The socket to tear down. - - @param ec Set to the error if any occurred. + If you are creating an instance of beast::websocket::stream with your + own user defined type, you must provide an overload of teardown with + the corresponding signature (including the teardown_tag). */ -void -teardown( - boost::asio::ip::tcp::socket& socket, - error_code& ec); - -/** Start tearing down a `boost::asio::ip::tcp::socket`. - - This begins tearing down a connection asynchronously. - The implementation will call the overload of this function - based on the `Stream` parameter used to consruct the socket. - When `Stream` is a user defined type, and not a - `boost::asio::ip::tcp::socket` or any `boost::asio::ssl::stream`, - callers are responsible for providing a suitable overload - of this function. - - @param socket The socket to tear down. - - @param handler The handler to be called when the request completes. - Copies will be made of the handler as required. The equivalent - function signature of the handler must be: - @code void handler( - error_code const& error // result of operation - ); @endcode - Regardless of whether the asynchronous operation completes - immediately or not, the handler will not be invoked from within - this function. Invocation of the handler will be performed in a - manner equivalent to using boost::asio::io_service::post(). - -*/ -template -void -async_teardown( - boost::asio::ip::tcp::socket& socket, - TeardownHandler&& handler); + static_assert(sizeof(Socket)==-1, + "Unknown Socket type in async_teardown."); +} } // websocket @@ -127,7 +111,7 @@ void call_teardown(Socket& socket, error_code& ec) { using websocket::teardown; - teardown(socket, ec); + teardown(websocket::teardown_tag{}, socket, ec); } template @@ -136,12 +120,65 @@ void call_async_teardown(Socket& socket, TeardownHandler&& handler) { using websocket::async_teardown; - async_teardown(socket, + async_teardown(websocket::teardown_tag{}, socket, std::forward(handler)); } } // websocket_helpers +//------------------------------------------------------------------------------ + +namespace websocket { + +/** Tear down a `boost::asio::ip::tcp::socket`. + + This tears down a connection. The implementation will call + the overload of this function based on the `Stream` parameter + used to consruct the socket. When `Stream` is a user defined + type, and not a `boost::asio::ip::tcp::socket` or any + `boost::asio::ssl::stream`, callers are responsible for + providing a suitable overload of this function. + + @param socket The socket to tear down. + + @param ec Set to the error if any occurred. +*/ +void +teardown(teardown_tag, + boost::asio::ip::tcp::socket& socket, error_code& ec); + +/** Start tearing down a `boost::asio::ip::tcp::socket`. + + This begins tearing down a connection asynchronously. + The implementation will call the overload of this function + based on the `Stream` parameter used to consruct the socket. + When `Stream` is a user defined type, and not a + `boost::asio::ip::tcp::socket` or any `boost::asio::ssl::stream`, + callers are responsible for providing a suitable overload + of this function. + + @param socket The socket to tear down. + + @param handler The handler to be called when the request completes. + Copies will be made of the handler as required. The equivalent + function signature of the handler must be: + @code void handler( + error_code const& error // result of operation + ); + @endcode + Regardless of whether the asynchronous operation completes + immediately or not, the handler will not be invoked from within + this function. Invocation of the handler will be performed in a + manner equivalent to using boost::asio::io_service::post(). + +*/ +template +void +async_teardown(teardown_tag, + boost::asio::ip::tcp::socket& socket, TeardownHandler&& handler); + +} // websocket + } // beast #include