Documentation work

This commit is contained in:
Vinnie Falco
2017-06-12 05:01:24 -07:00
parent a49c096042
commit 7bde07a850
16 changed files with 180 additions and 177 deletions

View File

@@ -88,7 +88,6 @@
[include 1_overview.qbk]
[include 2_examples.qbk]
[include 3_0_core.qbk]
[include 4_0_network.qbk]
[include 5_00_http.qbk]
[include 6_0_http_examples.qbk]
[include 7_0_websocket.qbk]

View File

@@ -7,15 +7,10 @@
[section:overview Introduction]
[important
Beast is a cross-platform, header-only C++11 library for
[*low-level HTTP/1, WebSocket, and network protocol] programming
using the consistent asynchronous model of __Asio__. Beast is
not an HTTP client or HTTP server, but it can be used to build
those things. It is a foundation for writing interoperable
libraries by providing HTTP vocabulary types and algorithms. The
examples show how client and server applications might be built.
]
Beast is a C++ header-only library serving as a foundation for writing
interoperable networking libraries by providing [*low-level HTTP/1,
WebSocket, and networking protocol] vocabulary types and algorithms
using the consistent asynchronous model of __Asio__.
This library is designed for:
@@ -30,46 +25,36 @@ This library is designed for:
* [*Basis for Further Abstraction.] Components are well-suited for building upon.
[heading Audience]
Beast is for network programmers who have some familiarity with
__Asio__. In particular, users who wish to write asynchronous programs
with Beast should already know how to use Asio sockets and streams,
and should know how to create concurrent network programs using
Asio callbacks or coroutines.
Beast is not an HTTP client or HTTP server, but it can be used to build
those things.
[heading Motivation]
An absence of high quality C++ network protocol libraries has led
to a patchwork of open-source solutions lacking suitable conciseness
and expressive power for standardization. Part of this problem is a
lack of common C++ networking interfaces. This is changing soon with
the Networking Technical Specification (__N4588__): a uniform interface
on track to become standardized. This technical specification is modeled
closely after Boost.Asio.
Beast empowers users to create their own libraries, clients, and servers
using HTTP/1 and WebSocket. Code will be easier and faster to implement,
understand, and maintain, because Beast takes care of the low-level
protocol details.
The HTTP and WebSocket protocols drive most of the World Wide Web.
Every web browser implements these protocols to load webpages and
to enable client side programs (often written in JavaScript) to
communicate interactively. C++ benefits greatly from having a
standardized implementation of these protocols.
[note
The Beast roadmap includes a port to the networking
interface based on __N4588__.
]
[heading Requirements]
This library is for programmers familiar with __Asio__. Users who
wish to use asynchronous interfaces should already know how to
create concurrent network programs using callbacks or coroutines.
Beast requires:
* [*C++11:] Robust support for most language features.
* [*Boost:] Boost.Asio and some other parts of Boost.
* [*Boost:] Beast only works with Boost, not stand-alone Asio
* [*OpenSSL:] Optional, for using TLS/Secure sockets.
[note Supported compilers: msvc-14+, gcc 4.8+, clang 3.6+]
Supported compilers: msvc-14+, gcc 4.8+, clang 3.6+
This library is [*header-only]. To link a program using Beast
successfully, add the
Sources are [*header-only]. To link a program using Beast successfully, add the
[@http://www.boost.org/libs/system/doc/reference.html Boost.System]
library to the list of linked libraries. If you use coroutines
you'll also need the
@@ -78,13 +63,6 @@ library. Please visit the
[@http://www.boost.org/doc/ Boost documentation]
for instructions on how to do this for your particular build system.
[note
Beast does not compile using the
[@https://github.com/chriskohlhoff/asio stand-alone Asio],
since it relies on other Boost parts. There are no immediate
plans to offer a version that works with stand-alone Asio.
]
[heading Credits]
Boost.Asio is the inspiration behind which all of the interfaces and

View File

@@ -26,6 +26,7 @@ with descriptions.
[include 3_1_asio.qbk]
[include 3_2_streams.qbk]
[include 3_3_buffers.qbk]
[include 3_4_async.qbk]
[include 3_4_composed.qbk]
[include 3_5_detect_ssl.qbk]
[endsect]

View File

@@ -15,13 +15,6 @@
left to the interfaces already existing on the underlying streams.
]
Library stream algorithms require a __socket__, __ssl_stream__, or other
__Stream__ object that has already established communication with an
endpoint. This example is provided as a reminder of how to work with
sockets:
[snippet_core_2]
Throughout this documentation identifiers with the following names have
special meaning:
@@ -59,4 +52,11 @@ special meaning:
]]
]
Library stream algorithms require a __socket__, __ssl_stream__, or other
__Stream__ object that has already established communication with an
endpoint. This example is provided as a reminder of how to work with
sockets:
[snippet_core_2]
[endsect]

View File

@@ -5,7 +5,7 @@
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
]
[section:streams Using Streams]
[section:streams Stream Types]
A __Stream__ is a communication channel where data is transferred as
an ordered sequence of octet buffers. Streams are either synchronous

View File

@@ -5,7 +5,7 @@
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
]
[section:buffers Using Buffers]
[section:buffers Buffer Types]
__Asio__ provides the __ConstBufferSequence__ and __MutableBufferSequence__
concepts, whose models provide ranges of buffers, as well as the __streambuf__

View File

@@ -5,7 +5,7 @@
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
]
[section:async Asynchronous I/O]
[section:composed Composed Operations]
Asynchronous operations are started by calling a free function or member
function known as an ['asynchronous initiation function]. The initiation
@@ -101,4 +101,56 @@ available:
]]
]
[heading Example: Asynchronous Echo]
Here we develop an asynchronous composed operation called [*echo].
This operation will read up to the first newline on a stream, and
then write the same line including the newline back on the stream.
The implementation performs both reading and writing, and has a
non-trivially-copyable state.
First we define the input parameters and results, then declare our
initiation function. For our echo operation the only inputs are the
stream and the completion token. The output is the error code which
is usually included in all completion handler signatures.
[core_sample_echo_op_1]
Now that we have a declaration, we will define the body of the function.
We want to achieve the following goals: perform static type checking on
the input parameters, set up the return value as per __N3747__, and launch
the composed operation by constructing the object and invoking it.
[core_sample_echo_op_2]
The initiation function contains a few relatively simple parts. There is
the customization of the return value type, static type checking, building
the return value type using the helper, and creating and launching the
composed operation object. The [*`echo_op`] object does most of the work
here, and has a somewhat non-trivial structure. This structure is necessary
to meet the stringent requirements of composed operations (described in more
detail in the __Asio__ documentation). We will touch on these requirements
without explaining them in depth.
Here is the boilerplate present in all composed operations written
in this style:
[core_sample_echo_op_3]
We have the common boilerplate for a composed operation and now we just need
to implement the function call operator. Our strategy is to make our composed
object meet the requirements of a completion handler by being copyable (also
movable), and by providing the function call operator with the correct
signature. Rather than using `std::bind` or `boost::bind`, which destroys
the type information and therefore breaks the allocation and invocation
hooks, we will simply pass `std::move(*this)` as the completion handler
parameter for any operations that we initiate. For the move to work correctly,
care must be taken to ensure that no access to data members are made after the
move takes place. Here is the implementation of the function call operator for
this echo operation:
[core_sample_echo_op_4]
A complete, runnable version of this example may be found in the examples
directory.
[endsect]

View File

@@ -5,13 +5,13 @@
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
]
[section:detect_tls TLS/SSL Detector Composed Operation]
[section:detect_tls Example: Detect SSL]
In this example we will build a simple function to detect the presence
of the TLS handshake given an input buffer sequence. Then we build on
of the SSL handshake given an input buffer sequence. Then we build on
the example by adding synchronous stream algorithms. Finally, we
implemement an asynchronous detection function using a composed operation.
This SSL detector may be used to allow a server to accept both TLS and
This SSL detector may be used to allow a server to accept both SSL/TLS and
unencrypted connections at the same port.
Here is the declaration for a function to detect the SSL client handshake.

View File

@@ -1,17 +0,0 @@
[/
Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
]
[section:network Network Examples]
These examples in this section are working functions that may be found
in the examples directory. They demonstrate the usage of the library
for a variety of scenarios.
[include 4_1_detect_tls.qbk]
[include 4_2_echo.qbk]
[endsect]

View File

@@ -1,61 +0,0 @@
[/
Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
Distributed under the Boost Software License, Version 1.0. (See accompanying
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
]
[section:echo Echo Composed Operation]
Here we developed a more advanced asynchronous composed operation called
[*echo]. This operation will read up to the first newline on a stream, and
then write the same line including the newline back on the stream. The
implementation performs both reading and writing, and has a
non-trivially-copyable state.
First we define the input parameters and results, then declare our initiation
function. For our echo operation the only inputs are the stream and the
completion token. The output is the error code which is usually included in
all completion handler signatures.
[core_sample_echo_op_1]
Now that we have a declaration, we will define the body of the function. We
want to achieve the following goals: perform static type checking on the input
parameters, set up the return value as per __N3747__, and launch the composed
operation by constructing the object and invoking it.
[core_sample_echo_op_2]
The initiation function contains a few relatively simple parts. There is the
customization of the return value type, static type checking, building the
return value type using the helper, and creating and launching the composed
operation object. The [*`echo_op`] object does most of the work here, and has
a somewhat non-trivial structure. This structure is necessary to meet the
stringent requirements of composed operations (described in more detail in
the __Asio__ documentation). We will touch on these requirements without
explaining them in depth.
First we will create boilerplate which is present in all composed operations
written in this style:
[core_sample_echo_op_3]
We have the common boilerplate for a composed operation and now we just need
to implement the function call operator. Our strategy is to make our composed
object meet the requirements of a completion handler by being copyable (also
movable), and by providing the function call operator with the correct
signature. Rather than using `std::bind` or `boost::bind`, which destroys
the type information and therefore breaks the allocation and invocation
hooks, we will simply pass `std::move(*this)` as the completion handler
parameter for any operations that we initiate. For the move to work correctly,
care must be taken to ensure that no access to data members are made after the
move takes place. Here is the implementation of the function call operator for
this echo operation:
[core_sample_echo_op_4]
A complete, runnable version of this example may be found in the examples
directory.
[endsect]

View File

@@ -9,7 +9,7 @@
An instance of __serializer__ can be invoked directly, without using
the provided stream operations. This could be useful for implementing
algorithms on streams whose interface does not conform to __Stream__.
algorithms on objects whose interface does not conform to __Stream__.
For example, a
[@https://github.com/libuv/libuv *libuv* socket].
The serializer interface is interactive; the caller invokes it repeatedly

View File

@@ -9,7 +9,7 @@
A subclass of __basic_parser__ can be invoked directly, without using
the provided stream operations. This could be useful for implementing
algorithms on objects whose interface does not conform to any __Stream__.
algorithms on objects whose interface does not conform to __Stream__.
For example, a
[@http://zeromq.org/ *ZeroMQ* socket].
The basic parser interface is interactive; the caller invokes the function

View File

@@ -147,12 +147,18 @@ detect_ssl(
// The algorithm should never need more than 4 bytes
BOOST_ASSERT(buffer.size() < 4);
// We need more bytes, but no more than four total.
buffer.commit(stream.read_some(buffer.prepare(4 - buffer.size()), ec));
// Create up to 4 bytes of space in the buffer's output area.
auto const mutable_buffer = buffer.prepare(4 - buffer.size());
// Try to fill our buffer by reading from the stream
std::size_t const bytes_transferred = stream.read_some(mutable_buffer, ec);
// Check for an error
if(ec)
break;
// Commit what we read into the buffer's input area.
buffer.commit(bytes_transferred);
}
// error

View File

@@ -13,11 +13,51 @@
//[core_sample_echo_op_1
// Read a line and echo it back
//
template<class AsyncStream, class CompletionToken>
beast::async_return_type<CompletionToken, void(beast::error_code)>
async_echo(AsyncStream& stream, CompletionToken&& token);
/** Asynchronously read a line and echo it back.
This function is used to asynchronously read a line ending
in a carriage-return linefeed ("CRLF") from the stream,
and then write it back. The function call always returns
immediately. The asynchronous operation will continue until
one of the following conditions is true:
@li A line was read in and sent back on the stream
@li An error occurs.
This operation is implemented in terms of one or more calls to
the stream's `async_read_some` and `async_write_some` functions,
and is known as a <em>composed operation</em>. The program must
ensure that the stream performs no other operations until this
operation completes. The implementation may read additional octets
that lie past the end of the line being read. These octets are
silently discarded.
@param The stream to operate on. The type must meet the
requirements of @b AsyncReadStream and @AsyncWriteStream
@param token The completion token to use. If this is a
completion handler, copies will be made as required.
The signature of the handler must be:
@code
void handler(
error_code& ec // 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<
class AsyncStream,
class CompletionToken>
beast::async_return_type< /*< The [link beast.ref.async_return_type `async_return_type`] customizes the return value based on the completion token >*/
CompletionToken,
void(beast::error_code)> /*< This is the signature for the completion handler >*/
async_echo(
AsyncStream& stream,
CompletionToken&& token);
//]

View File

@@ -42,10 +42,6 @@ using response_type = http::response<http::string_body>;
The @ref stream class template provides asynchronous and blocking
message-oriented functionality necessary for clients and servers
to utilize the WebSocket protocol.
@par Thread Safety
@e Distinct @e objects: Safe.@n
@e Shared @e objects: Unsafe.
For asynchronous operations, the application must ensure
that they are are all performed within the same implicit
@@ -56,6 +52,12 @@ using response_type = http::response<http::string_body>;
To use the @ref stream template with an `ip::tcp::socket`,
you would write:
@tparam NextLayer The type representing the next layer, to which
data will be read and written during operations. For synchronous
operations, the type must support the @b SyncStream concept.
For asynchronous operations, the type must support the
@b AsyncStream concept.
@code
websocket::stream<ip::tcp::socket> ws{io_service};
@endcode
@@ -65,11 +67,9 @@ using response_type = http::response<http::string_body>;
websocket::stream<ip::tcp::socket&> ws{sock};
@endcode
@tparam NextLayer The type representing the next layer, to which
data will be read and written during operations. For synchronous
operations, the type must support the @b SyncStream concept.
For asynchronous operations, the type must support the
@b AsyncStream concept.
@par Thread Safety
@e Distinct @e objects: Safe.@n
@e Shared @e objects: Unsafe.
@note A stream object must not be moved or destroyed while there
are pending asynchronous operations associated with it.
@@ -95,7 +95,7 @@ public:
using lowest_layer_type =
typename get_lowest_layer<next_layer_type>::type;
/** Move-construct a stream.
/** Move constructor
If @c NextLayer is move constructible, this function
will move-construct a new stream from the existing stream.
@@ -105,17 +105,17 @@ public:
*/
stream(stream&&) = default;
/** Move assignment.
/** Move assignment
If `NextLayer` is move constructible, this function
will move-construct a new stream from the existing stream.
If `NextLayer` is move assignable, this function
will move-assign a new stream from the existing stream.
@note The behavior of move assignment on or from streams
with active or pending operations is undefined.
*/
stream& operator=(stream&&) = default;
/** Construct a WebSocket stream.
/** Constructor
This constructor creates a websocket stream and initializes
the next layer object.
@@ -130,22 +130,21 @@ public:
explicit
stream(Args&&... args);
/** Destructor.
/** Destructor
@note A stream object must not be destroyed while there
are pending asynchronous operations associated with it.
*/
~stream() = default;
/** Get the io_service associated with the stream.
/** Return the `io_service` associated with the stream
This function may be used to obtain the io_service object
This function may be used to obtain the `io_service` object
that the stream uses to dispatch handlers for asynchronous
operations.
@return A reference to the io_service object that the stream
will use to dispatch handlers. Ownership is not transferred
to the caller.
will use to dispatch handlers.
*/
boost::asio::io_service&
get_io_service()
@@ -153,13 +152,13 @@ public:
return stream_.get_io_service();
}
/** Get a reference to the next layer.
/** Get a reference to the next layer
This function returns a reference to the next layer
in a stack of stream layers.
@return A reference to the next layer in the stack of
stream layers. Ownership is not transferred to the caller.
stream layers.
*/
next_layer_type&
next_layer()
@@ -167,13 +166,13 @@ public:
return stream_.next_layer();
}
/** Get a reference to the next layer.
/** Get a reference to the next layer
This function returns a reference to the next layer in a
stack of stream layers.
@return A reference to the next layer in the stack of
stream layers. Ownership is not transferred to the caller.
stream layers.
*/
next_layer_type const&
next_layer() const
@@ -181,13 +180,13 @@ public:
return stream_.next_layer();
}
/** Get a reference to the lowest layer.
/** Get a reference to the lowest layer
This function returns a reference to the lowest layer
in a stack of stream layers.
@return A reference to the lowest layer in the stack of
stream layers. Ownership is not transferred to the caller.
stream layers.
*/
lowest_layer_type&
lowest_layer()
@@ -195,7 +194,7 @@ public:
return stream_.lowest_layer();
}
/** Get a reference to the lowest layer.
/** Get a reference to the lowest layer
This function returns a reference to the lowest layer
in a stack of stream layers.
@@ -2571,9 +2570,11 @@ public:
This call is implemented in terms of one or more calls to the
stream's `read_some` and `write_some` operations.
Upon a success, op is set to either binary or text depending on
the message type, and the input area of the stream buffer will
hold all the message payload bytes (which may be zero in length).
Upon a success, the input area of the stream buffer will
hold the received message payload bytes (which may be zero
in length). The functions @ref got_binary and @ref got_text
may be used to query the stream and determine the type
of the last received message.
During reads, the implementation handles control frames as
follows:
@@ -2608,9 +2609,11 @@ public:
This call is implemented in terms of one or more calls to the
stream's `read_some` and `write_some` operations.
Upon a success, op is set to either binary or text depending on
the message type, and the input area of the stream buffer will
hold all the message payload bytes (which may be zero in length).
Upon a success, the input area of the stream buffer will
hold the received message payload bytes (which may be zero
in length). The functions @ref got_binary and @ref got_text
may be used to query the stream and determine the type
of the last received message.
During reads, the implementation handles control frames as
follows:
@@ -2650,9 +2653,11 @@ public:
ensure that the stream performs no other reads until this operation
completes.
Upon a success, op is set to either binary or text depending on
the message type, and the input area of the stream buffer will
hold all the message payload bytes (which may be zero in length).
Upon a success, the input area of the stream buffer will
hold the received message payload bytes (which may be zero
in length). The functions @ref got_binary and @ref got_text
may be used to query the stream and determine the type
of the last received message.
During reads, the implementation handles control frames as
follows:

View File

@@ -37,7 +37,7 @@ boost::asio::ip::tcp::socket sock{ios};
{
//[snippet_core_2
auto host = "www.example.com";
char const* const host = "www.example.com";
boost::asio::ip::tcp::resolver r{ios};
boost::asio::ip::tcp::socket stream{ios};
boost::asio::connect(stream, r.resolve(