diff --git a/CHANGELOG.md b/CHANGELOG.md index a6bad614..e707cdb3 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -3,8 +3,9 @@ * Add missing rebind to handler_alloc * Fix error handling in http server examples * Fix CMake scripts for MinGW -* Better WebSocket decorator * Use BOOST_ASSERT +* Better WebSocket decorator +* Update and tidy documentation -------------------------------------------------------------------------------- diff --git a/doc/Jamfile b/doc/Jamfile.v2 similarity index 63% rename from doc/Jamfile rename to doc/Jamfile.v2 index 35e11311..b4eddb01 100644 --- a/doc/Jamfile +++ b/doc/Jamfile.v2 @@ -15,15 +15,15 @@ using boostbook ; using quickbook ; using doxygen ; -xml beast_boostbook : master.qbk ; +import quickbook ; -path-constant out : . ; +path-constant here : . ; install stylesheets : $(broot)/doc/src/boostbook.css : - $(out)/html + $(here)/html ; explicit stylesheets ; @@ -35,7 +35,7 @@ install images images/body.png images/message.png : - $(out)/html/images + $(here)/html/images ; explicit images ; @@ -44,40 +44,49 @@ install callouts : [ glob $(broot)/doc/src/images/callouts/*.png ] : - $(out)/html/images/callouts + $(here)/html/images/callouts ; explicit callout ; -boostbook doc +install examples : - beast_boostbook + [ glob ../examples/*.* ] : - chapter.autolabel=0 - boost.image.src=images/beast.png - boost.image.alt="Beast Logo" - boost.image.w=2400 - boost.image.h=80 - boost.root=$(broot) - chapter.autolabel=0 - chunk.first.sections=1 # Chunk the first top-level section? - chunk.section.depth=8 # Depth to which sections should be chunked - generate.section.toc.level=1 # Control depth of TOC generation in sections - toc.max.depth=2 # How many levels should be created for each TOC? - toc.section.depth=2 # How deep should recursive sections appear in the TOC? - : - temp - stylesheets - images + $(here)/html/examples ; -#explicit doc ; -# nav.layout=none -# html:location=../bin/doc/html -# generate.toc="chapter nop section nop" -# root.filename=index -# output-root="../bin/html" +explicit examples ; +xml doc + : + master.qbk + : + temp + $(broot)/tools/boostbook/dtd + ; + +boostbook boostdoc + : + doc + : + boost.root=$(broot) + boost.image.src=images/beast.png + boost.image.alt="Beast Logo" + boost.image.w=1330 + boost.image.h=80 + chapter.autolabel=0 + chunk.section.depth=8 # Depth to which sections should be chunked + chunk.first.sections=1 # Chunk the first top-level section? + toc.section.depth=8 # How deep should recursive sections appear in the TOC? + toc.max.depth=8 # How many levels should be created for each TOC? + generate.section.toc.level=8 # Control depth of TOC generation in sections + generate.toc="chapter nop section nop" + $(broot)/tools/boostbook/dtd + : + temp + examples + images + stylesheets + ; -#[include reference.qbk] -#[xinclude index.xml] diff --git a/doc/design.qbk b/doc/design.qbk index b6562090..5c669afb 100644 --- a/doc/design.qbk +++ b/doc/design.qbk @@ -25,7 +25,7 @@ libraries: * Let library users make the important decisions such as how to allocate memory or how to leverage flow control. -Beast uses the [link beast.types.DynamicBuffer [*`DynamicBuffer`]] concept +Beast uses the [link beast.ref.DynamicBuffer [*`DynamicBuffer`]] concept presented in the Netwoking TS, and relies heavily on the Boost.Asio [*`ConstBufferSequence`] and [*`MutableBufferSequence`] concepts for passing buffers to functions. The authors have found the dynamic buffer and buffer diff --git a/doc/examples.qbk b/doc/examples.qbk new file mode 100644 index 00000000..d06f40e4 --- /dev/null +++ b/doc/examples.qbk @@ -0,0 +1,111 @@ +[/ + Copyright (c) 2013-2016 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:example Examples] + +These usage examples are intended to quickly impress upon readers the +flavor of the library. They are complete programs which may be built +and run. Source code and build scripts for these programs may be found +in the examples directory. + +[heading HTTP GET] + +Use HTTP to request the root page from a website and print the response: + +``` +#include +#include +#include +#include + +int main() +{ + // Normal boost::asio setup + std::string const host = "boost.org"; + boost::asio::io_service ios; + boost::asio::ip::tcp::resolver r{ios}; + boost::asio::ip::tcp::socket sock{ios}; + boost::asio::connect(sock, + r.resolve(boost::asio::ip::tcp::resolver::query{host, "http"})); + + // Send HTTP request using beast + beast::http::request_v1 req; + req.method = "GET"; + req.url = "/"; + req.version = 11; + req.headers.replace("Host", host + ":" + std::to_string(sock.remote_endpoint().port())); + req.headers.replace("User-Agent", "Beast"); + beast::http::prepare(req); + beast::http::write(sock, req); + + // Receive and print HTTP response using beast + beast::streambuf sb; + beast::http::response_v1 resp; + beast::http::read(sock, sb, resp); + std::cout << resp; +} +``` +[heading WebSocket] + +Establish a WebSocket connection, send a message and receive the reply: +``` +#include +#include +#include +#include +#include + +int main() +{ + // Normal boost::asio setup + std::string const host = "echo.websocket.org"; + boost::asio::io_service ios; + boost::asio::ip::tcp::resolver r{ios}; + boost::asio::ip::tcp::socket sock{ios}; + boost::asio::connect(sock, + r.resolve(boost::asio::ip::tcp::resolver::query{host, "80"})); + + // WebSocket connect and send message using beast + beast::websocket::stream ws{sock}; + ws.handshake(host, "/"); + ws.write(boost::asio::buffer("Hello, world!")); + + // Receive WebSocket message, print and close using beast + beast::streambuf sb; + beast::websocket::opcode op; + ws.read(op, sb); + ws.close(beast::websocket::close_code::normal); + std::cout << to_string(sb.data()) << "\n"; +} +``` + +[heading HTTP Crawl] + +This example retrieves the page at each of the most popular domains +as measured by Alexa. + +* [@examples/http_crawl.cpp] + +[heading HTTP Server] + +This example demonstrates both synchronous and asynchronous server +implementations. It also provides an example of implementing a [*Body] +type, in `file_body`. + +* [@examples/file_body.hpp] +* [@examples/http_async_server.hpp] +* [@examples/http_sync_server.hpp] +* [@examples/http_server.cpp] + +[heading Listings] + +These are stand-alone listings of the HTTP and WebSocket examples. + +* [@examples/http_example.cpp] +* [@examples/websocket_example.cpp] + +[endsect] diff --git a/doc/http.qbk b/doc/http.qbk index 81b89f48..51e63263 100644 --- a/doc/http.qbk +++ b/doc/http.qbk @@ -5,138 +5,149 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ] -[section:http HTTP] + + +[section:http Using HTTP] + +[block ''' + + Message + Headers + Body + Algorithms + Sockets + +'''] Beast.HTTP offers programmers simple and performant models of HTTP messages and their associated operations including synchronous and asynchronous reading and writing of messages in the HTTP/1 wire format using Boost.Asio. -The HTTP protocol is described fully in -[@https://tools.ietf.org/html/rfc7230 rfc7230] - - - -[section:motivation Motivation] - -The HTTP protocol is pervasive in network applications. As C++ is a logical -choice for high performance network servers, there is great utility in solid -building blocks for manipulating, sending, and receiving HTTP messages -compliant with the Hypertext Transfer Protocol and the supplements that -follow. Unfortunately reliable implementations or industry standards do not -exist in C++. - -Beast.HTTP is built on Boost.Asio and uses its own robust header-only HTTP/1 -message parser modeled after the nodejs http-parser (written in C). A proposal -to add networking functionality to the C++ standard library, based on -Boost.Asio, is under consideration by the standards committee. Since the final -approved networking interface for the C++ standard library will likely closely -resemble the current interface of Boost.Asio, it is logical for Beast.HTTP to -use Boost.Asio as its network transport. - -[endsect] - - - -[section:scope Scope] - -This library is designed to be a building block for creating higher level -libraries. It is not designed to be end-user facing. There is no convenient -class that implements the core of a web server, nor is there a convenient -class to quickly perform common operations such as fetching a file or -connecting and retrieving a document from a secure connection. These -use-cases are important, but this library does not try to do that. Instead, -it offers primitives that can be used to build those user-facing algorithms. - A HTTP message (referred to hereafter as "message") contains request or response specific attributes, a series of zero or more name/value pairs (collectively termed "headers"), and a series of octets called the message body which may be zero in length. The HTTP protocol defines the client and server roles: clients send messages called requests and servers send back -messages called responses. `http::message` models both requests and responses. -Beast aims to offer this functionality: - -* [*Model]: Provide a universal HTTP message class model. - -* [*Build]: Construct a new message and manipulate its contents. - -* [*Parse]: Deserialize a message from a network or memory stream in HTTP/1 wire format. - -* [*Serialize]: Serialize a message into a network or memory stream in HTTP/1 wire format. - -[note The documentation which follows assumes familiarity with -both Boost.Asio and the HTTP protocol specification described in -[@https://tools.ietf.org/html/rfc7230 rfc7230] ] - -[endsect] - - - -[section:usage Usage] +messages called responses. [note - Sample code and identifiers mentioned in this section are written - as if the following declarations are in effect: + The following documentation assumes familiarity with both Boost.Asio + and the HTTP protocol specification described in __rfc7230__. Sample code + and identifiers mentioned in this section are written as if the following + declarations are in effect: ``` #include using namespace beast; + using namespace beast::http; ``` ] -In the paragraphs that follow we describe the available interfaces for -performing typical operations such as interacting with a HTTP server -or handling simple requests. Subsequent sections cover the message model -and its customization points in more depth, for advanced applications. +[section:message Message] -[heading Declarations] +The __message__ class template models HTTP/2 requests and responses, while the +derived class __message_v1__ models HTTP/1 requests and responses, adding the +required version field. These objects are complete: they contain +all the information required to permit the algorithms to operate. These objects +are first class: They may be returned from functions, moved, copied, passed +as arguments, and stored in containers. Request and response messages are +distinct types; functions may be overloaded on just one or the other if +desired. Because this class template supports HTTP/1 and HTTP/2, it is +sometimes referred to as the universal message model. -To do anything, a message must be declared. The message class template -requires at minimum, a value indicating whether the message is a request -(versus a response), and a `Body` type. The choice of `Body` determines the -kind of container used to represent the message body. Here we will -declare a HTTP/1 request that has a `std::string` for the body container: +These class templates have three template parameters: ``` - http::message_v1 req; + template + class message; + + template + class message_v1; ``` -Two type aliases are provided for notational convenience when declaring -HTTP/1 messages. These two statements declare a request and a response -respectively: +* [*`isRequest`]: Controls whether or not the message is a request or response. + Depending on the value, different data members will be present in the resulting + type. + +* [*`Body`]: determines both the kind of container used to represent the + message body and the algorithms used to parse and serialize it. + +* [*`Headers`]: determines the container used to represent the HTTP headers. + +For notational convenience, the following template type aliases are provided: ``` - http::request_v1 req; - http::response_v1 resp; + template>> + using request = message; + + template>> + using response = message; + + template>> + using request_v1 = message_v1; + + template>> + using response_v1 = message_v1; ``` -[heading Members] +Although these aliases have a common base class, they have different fields +depending on whether the message is a request or a response. These simplified +declarations notionally illustrate the members of HTTP/1 messages: -Message objects are default constructible, with public access to data members. -Request and response objects have some common members, and some members unique -to the message type. These statements set all the members in each message: ``` - http::request_v1 req; + template + struct request_v1 + { + int version; 10 or 11 + std::string method; + std::string url; + Headers headers; + typename Body::value_type body; + }; + + template + struct response_v1 + { + int version; 10 or 11 + int status; + std::string reason; + Headers headers; + typename Body::value_type body; + }; +``` + +These statements set fields in request and response message objects: +``` + request_v1 req; req.method = "GET"; req.url = "/index.html"; req.version = 11; // HTTP/1.1 - req.headers.insert("User-Agent", "hello_world"); + req.headers.insert("User-Agent", "Beast.HTTP"); req.body = ""; - http::response_v1 resp; - resp.status = 404; - resp.reason = "Not Found"; - resp.version = 10; // HTTP/1.0 - resp.headers.insert("Server", "Beast.HTTP"); - resp.body = "The requested resource was not found."; + response_v1 res; + res.status = 404; + res.reason = "Not Found"; + res.version = 10; // HTTP/1.0 + res.headers.insert("Server", "Beast.HTTP"); + res.body = "The requested resource was not found."; ``` -[heading Headers] +[endsect] -The `message::headers` member is a container for setting the field/value -pairs in the message. These statements change the values of the headers -in the message passed: + + +[section:headers Headers] + +The [*`Headers`] type represents a container that can set or retrieve the +headers in a message. Beast provides the +[link beast.ref.http__basic_headers `basic_headers`] class which serves +the needs for most users. It supports modification and inspection of values. +The field names are not case-sensitive. + +These statements change the values of the headers in the message passed: ``` template - void set_fields(http::request_v1& req) + void set_fields(request_v1& req) { if(! req.exists("User-Agent")) req.insert("User-Agent", "myWebClient"); @@ -148,17 +159,32 @@ in the message passed: } ``` -[heading Body] +[heading Advanced] -The `message::body` member represents the message body. Depending on the -`Body` template argument type, this could be a writable container. The -following types, provided by the library, are suitable choices for the -`Body` type: +This illustration shows more detail about the +[link beast.ref.http__message [*`message`]] class template (boilerplate +present in the actual declaration has been removed for clarity): + +[$images/message.png [width 580px] [height 225px]] + +User defined [*`Headers`] types are possible. To support serialization, the +type must meet the requirements of __FieldSequence__. To support parsing using +the provided parser, the type must provide the `insert` member function. + +[endsect] + + + +[section:body Body] + +The message [*`Body`] template parameter controls both the type of the data +member of the resulting message object, and the algorithms used during parsing +and serialization. Beast provides three very common [*`Body`] types: * [link beast.ref.http__empty_body [*`empty_body`:]] An empty message body. Used in GET requests where there is no message body. Example: ``` - http::request_v1 req; + request_v1 req; req.version = 11; req.method = "GET"; req.url = "/index.html"; @@ -170,36 +196,83 @@ or response with simple text in the message body (such as an error message). Has the same insertion complexity of `std::string`. This is the type of body used in the examples: ``` - http::response_v1 resp; - static_assert(std::is_same::value); - resp.body = "Here is the data you requested"; + response_v1 res; + static_assert(std::is_same::value); + res.body = "Here is the data you requested"; ``` * [link beast.ref.http__streambuf_body [*`streambuf_body`:]] A body with a `value_type` of [link beast.ref.streambuf `streambuf`]: an efficient storage object which uses multiple octet arrays of varying lengths to represent data. -[heading Sockets] +[heading Advanced] + +User-defined types are possible for the message body, where the type meets the +[link beast.ref.Body [*`Body`]] requirements. This simplified class declaration +shows the customization points available to user-defined body types: + +[$images/body.png [width 510px] [height 210px]] + +* [*`value_type`]: Determines the type of the + [link beast.ref.http__message.body `message::body`] member. If this + type defines default construction, move, copy, or swap, then message objects + declared with this [*`Body`] will have those operations defined. + +* [*`reader`]: An optional nested type meeting the requirements of + [link beast.ref.Reader [*`Reader`]]. If present, this defines the algorithm + used for parsing bodies of this type. + +* [*`writer`]: An optional nested type meeting the requirements of + [link beast.ref.Writer [*`Writer`]]. If present, this defines the algorithm + used for serializing bodies of this type. + +The examples included with this library provide a Body implementation that +serializing message bodies that come from a file. + +[endsect] + + + +[section:algorithms Algorithms] + +In addition to the universal message model, Beast provides synchronous +algorithms which operate on HTTP/1 messages: + +* [link beast.ref.http__read [*read]]: Parse a message from a stream + +* [link beast.ref.http__write [*write]]: Serialize a message into its wire format on a stream + +Asynchronous versions of these algorithms are also available: + +* [link beast.ref.http__async_read [*async_read]]: Parse a message from a stream + +* [link beast.ref.http__async_write [*async_write]]: Serialize a message into its wire format on a stream + +[endsect] + + + +[section:sockets Using Sockets] The library provides simple free functions modeled after Boost.Asio to send and receive messages on TCP/IP sockets, SSL streams, or any object which meets the Boost.Asio type requirements (SyncReadStream, SyncWriteStream, AsyncReadStream, and AsyncWriteStream depending on the types of operations -performed). To send messages synchronously, use one of the `http:write` -functions: +performed). To send messages synchronously, use one of the +[link beast.ref.http__write `write`] functions: ``` void send_request(boost::asio::ip::tcp::socket& sock) { - http::request req; + request req; req.version = 11; req.method = "GET"; req.url = "/index.html"; ... - http::write(sock, req); // Throws exception on error + write(sock, req); // Throws exception on error ... // Alternatively boost::system::error:code ec; - http::write(sock, req, ec); + write(sock, req, ec); if(ec) std::cerr << "error writing http message: " << ec.message(); } @@ -209,27 +282,27 @@ An asynchronous interface is available: ``` void handle_write(boost::system::error_code); ... - http::request_v1 req; + request_v1 req; ... - http::async_write(sock, req, std::bind(&handle_write, std::placeholders::_1)); + async_write(sock, req, std::bind(&handle_write, std::placeholders::_1)); ``` When the implementation reads messages from a socket, it can read bytes lying after the end of the message if they are present (the alternative is to read a single byte at a time which is unsuitable for performance reasons). To store and re-use these extra bytes on subsequent messages, the read interface -requires an additional parameter: a [link beast.types.DynamicBuffer [*`DynamicBuffer`]] +requires an additional parameter: a [link beast.ref.DynamicBuffer [*`DynamicBuffer`]] object. This example reads a message from the socket, with the extra bytes stored in the streambuf parameter for use in a subsequent call to read: ``` boost::asio::streambuf sb; ... - http::response_v1 resp; - http::read(sock, sb, resp); // Throws exception on error + response_v1 res; + read(sock, sb, res); // Throws exception on error ... // Alternatively boost::system::error:code ec; - http::read(sock, sb, resp, ec); + read(sock, sb, res, ec); if(ec) std::cerr << "error reading http message: " << ec.message(); ``` @@ -241,116 +314,28 @@ called: void handle_read(boost::system::error_code); ... boost::asio::streambuf sb; - http::response_v1 resp; + response_v1 res; ... - http::async_read(sock, resp, std::bind(&handle_read, std::placeholders::_1)); + async_read(sock, res, std::bind(&handle_read, std::placeholders::_1)); ``` An alternative to using a `boost::asio::streambuf` is to use a -[link beast.ref.streambuf `beast::streambuf`], which meets the requirements of -[*`DynamicBuffer`] and is optimized for performance: +__streambuf__, which meets the requirements of __DynamicBuffer__ and +is optimized for performance: ``` void handle_read(boost::system::error_code); ... beast::streambuf sb; - http::response_v1 resp; - http::read(sock, sb, resp); + response_v1 res; + read(sock, sb, res); ``` The `read` implementation can use any object meeting the requirements of -[link beast.types.DynamicBuffer [*`DynamicBuffer`]], allowing callers to define custom +__DynamicBuffer__, allowing callers to define custom memory management strategies used by the implementation. [endsect] -[section:advanced Advanced] - -The spectrum of hardware and software platforms which perform these typical -HTTP operations is vast, ranging from powerful servers in large datacenters -to tiny resource-limited embedded devices. No single concrete implementation -of a class intended to model messages can efficiently serve all needs. -For example, an object that minimizes resources during parsing may not be -able to edit and change headers dynamically. A message that represents the -message body as a disk file may support sending but not parsing. Many efficient -and correct models of messages exist, supporting some or all of the -operations listed above. - -[heading Message model] - -The message class template and provided Body types are suitable for casual -library users. This section explains the message model for advanced users -who wish to take control over aspects of the implementation. We introduce -customization points for the header and body via class template arguments. -This illustration shows more detail about the -[link beast.ref.http__message [*`message`]] class template (boilerplate -present in the actual declaration has been removed for clarity): - -[$images/message.png [width 580px] [height 225px]] - -The default constructor, move special members, and copy special members are -all defaulted. A message is movable, copyable, or default constructible based -on the capabilities of its template arguments. - -Messages modeled in this fashion are ['complete], containing all of the -information required to perform the supported set of operations. They are -['first-class types], returnable from functions and composable. HTTP -requests and responses are distinct types, allowing functions to be -overloaded on the type of message. - [endsect] - - - -[section:headers Headers Type] - -The `Headers` type represents the field/value pairs present in every HTTP -message. These types implement the -[link beast.types.FieldSequence [*`FieldSequence`]] -concept. The value type of a field sequence is an object meeting the -requirements of [link beast.types.Field [*`Field`]]. The implementation can -serialize any instance of `Headers` that meets the field sequence requirements. -This example shows a function which returns `true` if the specified field -sequence has a connect field: -``` -template -bool -has_connect(FieldSequence const& fs) -{ - return std::find_if(fs.begin(), fs.end(), - [&](auto const& field) - { - return ci_equal(field.name(), "Connect"); - }); -} -``` - -[endsect] - - - -[section:body Body Type] - -The `Body` template argument in the `message` class must meet the -[link beast.types.Body [*`Body`] requirements]. It provides customization -of the data member in the message, the algorithm for parsing, and the -algorithm for serialization: - -[$images/body.png [width 510px] [height 210px]] - -Instances of the optional nested types `writer` and `reader` perform -serialization and deserialization of the message body. If either or -both of these types are present, the message becomes serializable, parsable, -or both. They model [link beast.types.Reader [*`Reader`]] and -[link beast.types.Writer [*`Writer`]] respectively. - -For specialized applications, users may implement their own types which -meet the requirements. The examples included with this library provide a -Body implementation used to serve files in a HTTP server. - -[endsect] - - -[endsect] - diff --git a/doc/images/beast.png b/doc/images/beast.png index 604a6d9b..eb7528ec 100644 Binary files a/doc/images/beast.png and b/doc/images/beast.png differ diff --git a/doc/index.xml b/doc/index.xml index 0bbf7b76..0c0cba26 100644 --- a/doc/index.xml +++ b/doc/index.xml @@ -8,6 +8,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) --> -
+
+ Index
diff --git a/doc/master.qbk b/doc/master.qbk index 0023e72a..db1fa491 100644 --- a/doc/master.qbk +++ b/doc/master.qbk @@ -8,7 +8,7 @@ [library Beast [quickbook 1.6] [copyright 2013 - 2016 Vinnie Falco] - [purpose C++ Library] + [purpose Networking Protocol Library] [license Distributed under the Boost Software License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at @@ -22,174 +22,75 @@ [template mdash[] '''— '''] [template indexterm1[term1] ''''''[term1]''''''] [template indexterm2[term1 term2] ''''''[term1]''''''[term2]''''''] -[def __POSIX__ /POSIX/] -[def __Windows__ /Windows/] -[def __accept__ [@http://www.opengroup.org/onlinepubs/000095399/functions/accept.html `accept()`]] -[def __connect__ [@http://www.opengroup.org/onlinepubs/000095399/functions/connect.html `connect()`]] -[def __getpeername__ [@http://www.opengroup.org/onlinepubs/000095399/functions/getpeername.html `getpeername()`]] -[def __getsockname__ [@http://www.opengroup.org/onlinepubs/000095399/functions/getsockname.html `getsockname()`]] -[def __getsockopt__ [@http://www.opengroup.org/onlinepubs/000095399/functions/getsockopt.html `getsockopt()`]] -[def __ioctl__ [@http://www.opengroup.org/onlinepubs/000095399/functions/ioctl.html `ioctl()`]] -[def __recvfrom__ [@http://www.opengroup.org/onlinepubs/000095399/functions/recvfrom.html `recvfrom()`]] -[def __sendto__ [@http://www.opengroup.org/onlinepubs/000095399/functions/sendto.html `sendto()`]] -[def __setsockopt__ [@http://www.opengroup.org/onlinepubs/000095399/functions/setsockopt.html `setsockopt()`]] -[def __socket__ [@http://www.opengroup.org/onlinepubs/000095399/functions/socket.html `socket()`]] +[def __asio_handler_invoke__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/asio_handler_invoke.html `asio_handler_invoke`]] +[def __asio_handler_allocate__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/asio_handler_allocate.html `asio_handler_allocate`]] +[def __AsyncReadStream__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/AsyncReadStream.html [*AsyncReadStream]]] +[def __AsyncWriteStream__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/AsyncWriteStream.html [*AsyncWriteStream]]] +[def __Body__ [link beast.ref.Body [*`Body`]]] +[def __CompletionHandler__ [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/CompletionHandler.html [*CompletionHandler]]] +[def __ConstBufferSequence__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/ConstBufferSequence.html [*`ConstBufferSequence`]]] +[def __DynamicBuffer__ [link beast.ref.DynamicBuffer [*`DynamicBuffer`]]] +[def __FieldSequence__ [link beast.ref.FieldSequence [*`FieldSequence`]]] +[def __message__ [link beast.ref.http__message `message`]] +[def __message_v1__ [link beast.ref.http__message_v1 `message_v1`]] +[def __MutableBufferSequence [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/MutableBufferSequence.html [*MutableBufferSequence]]] +[def __rfc6455__ [@https://tools.ietf.org/html/rfc6455 rfc6455]] +[def __rfc7230__ [@https://tools.ietf.org/html/rfc7230 rfc7230]] +[def __streambuf__ [link beast.ref.streambuf `streambuf`]] +[def __SyncReadStream__ [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/SyncReadStream.html [*SyncReadStream]]] +[def __SyncWriteStream__ [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/SyncWriteStream.html [*SyncWriteStream]]] +[def __void_or_deduced__ [@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/asynchronous_operations.html#boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]] +Beast is a cross-platform, header-only C++ library built on Boost.Asio that +provides implementations of the HTTP and WebSocket protocols. -[section:intro Introduction] - -Beast is a header-only, cross-platform C++ library built on Boost.Asio and -Boost, containing two modules implementing widely used network protocols. -Beast.HTTP offers a universal model for describing, sending, and receiving -HTTP messages while Beast.WebSocket provides a complete implementation of -the WebSocket protocol. Their design achieves these goals: - -* [*Symmetry.] Interfaces are role-agnostic; the same interfaces can be -used to build clients, servers, or both. - -* [*Ease of Use.] HTTP messages are modeled using simple, readily -accessible objects. Functions and classes used to send and receive HTTP -or WebSocket messages are designed to resemble Boost.Asio as closely as -possible. Users familiar with Boost.Asio will be immediately comfortable -using this library. - -* [*Flexibility.] Interfaces do not mandate specific implementation -strategies; important decisions such as buffer or thread management are -left to users of the library. - -* [*Performance.] The implementation performs competitively, making it a -realistic choice for building high performance network servers. - -* [*Scalability.] Development of network applications that scale to thousands -of concurrent connections is possible with the implementation. - -* [*Basis for further abstraction.] The interfaces facilitate the -development of other libraries that provide higher levels of abstraction. - - - -[section:requirements Requirements] - -Beast requires: - -* [*C++11.] A minimum of C++11 is needed. -* [*Boost.] Beast is built on Boost, especially Boost.Asio. -* [*OpenSSL.] If using TLS/Secure sockets (optional). - -[note Tested compilers: msvc-14+, gcc 5+, clang 3.6+] - -The library is [*header-only]. It is not necessary to add any .cpp files, -or to edit your existing build script or project file except to provide -that the include/ directory for beast is searched for include files. - -[endsect] - - - -[section:example Examples] - -These usage examples are intended to quickly impress upon readers the -flavor of the library. They are complete programs which may be built -and run. Source code and build scripts for these programs may be found -in the examples directory. - -Use HTTP to request the root page from a website and print the response: -``` -#include -#include -#include -#include - -int main() -{ - // Normal boost::asio setup - std::string const host = "boost.org"; - boost::asio::io_service ios; - boost::asio::ip::tcp::resolver r{ios}; - boost::asio::ip::tcp::socket sock{ios}; - boost::asio::connect(sock, - r.resolve(boost::asio::ip::tcp::resolver::query{host, "http"})); - - // Send HTTP request using beast - beast::http::request_v1 req; - req.method = "GET"; - req.url = "/"; - req.version = 11; - req.headers.replace("Host", host + ":" + std::to_string(sock.remote_endpoint().port())); - req.headers.replace("User-Agent", "Beast"); - beast::http::prepare(req); - beast::http::write(sock, req); - - // Receive and print HTTP response using beast - beast::streambuf sb; - beast::http::response_v1 resp; - beast::http::read(sock, sb, resp); - std::cout << resp; -} -``` - -Establish a WebSocket connection, send a message and receive the reply: -``` -#include -#include -#include -#include -#include - -int main() -{ - // Normal boost::asio setup - std::string const host = "echo.websocket.org"; - boost::asio::io_service ios; - boost::asio::ip::tcp::resolver r{ios}; - boost::asio::ip::tcp::socket sock{ios}; - boost::asio::connect(sock, - r.resolve(boost::asio::ip::tcp::resolver::query{host, "80"})); - - // WebSocket connect and send message using beast - beast::websocket::stream ws{sock}; - ws.handshake(host, "/"); - ws.write(boost::asio::buffer("Hello, world!")); - - // Receive WebSocket message, print and close using beast - beast::streambuf sb; - beast::websocket::opcode op; - ws.read(op, sb); - ws.close(beast::websocket::close_code::normal); - std::cout << to_string(sb.data()) << "\n"; -} -``` - -[endsect] - - - -[section:credits Credits] - -Boost.Asio is the inspiration behind which all of the interfaces and -implementation strategies are built. Some parts of the documentation are -written to closely resemble the wording and presentation of Boost.Asio -documentation. Credit goes to Christopher Kohloff for the wonderful -Asio library and the ideas upon which Beast is built. - -Beast would not be possible without the considerable time and patience -contributed by David Schwartz, Edward Hennis, Howard Hinnant, Miguel Portilla, -Nikolaos Bougalis, Scott Determan, Scott Schurr, and Ripple Labs for -supporting its development. - -[endsect] - - - -[endsect] - - +[variablelist + [[ + [link beast.overview Overview] + ][ + An overview of features, requirements, and credits, plus + rationale and design information. + ]] + [[ + [link beast.http Using HTTP] + ][ + How to use Beast's HTTP interfaces in your applications. + ]] + [[ + [link beast.websocket Using WebSocket] + ][ + How to use Beast's WebSocket interfaces in your applications. + ]] + [[ + [link beast.example Examples] + ][ + Examples that illustrate the use of Beast in more complex applications. + ]] + [[ + [link beast.quickref Reference] + ][ + Detailed class and function reference. + ]] + [[ + [link beast.index Index] + ][ + Book-style text index of Beast documentation. + ]] +] +[include overview.qbk] [include http.qbk] [include websocket.qbk] +[include examples.qbk] -[section:types Type Requirements] +[include design.qbk] + +[section:quickref Reference] +[xinclude quickref.xml] +[endsect] + +[section:ref Reference] [include types/Body.qbk] [include types/BufferSequence.qbk] [include types/DynamicBuffer.qbk] @@ -199,13 +100,7 @@ supporting its development. [include types/Reader.qbk] [include types/Streams.qbk] [include types/Writer.qbk] +[include reference.qbk] [endsect] -[include design.qbk] -[section:quickref Quick Reference] -[xinclude quickref.xml] -[endsect] -[include reference.qbk] -[section:idx Index] [xinclude index.xml] -[endsect] diff --git a/doc/overview.qbk b/doc/overview.qbk new file mode 100644 index 00000000..351f0ccd --- /dev/null +++ b/doc/overview.qbk @@ -0,0 +1,114 @@ +[/ + Copyright (c) 2013-2016 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:overview Introduction] + +Beast is a header-only, cross-platform C++ library built on Boost.Asio and +parts of Boost, containing two modules implementing widely used network +protocols. Beast offers a universal HTTP message model, plus algorithms for +parsing and serializing HTTP/1 messages. Beast.WebSocket provides a complete +implementation of the WebSocket protocol. Their design achieves these goals: + +* [*Symmetry.] Interfaces are role-agnostic; the same interfaces can be +used to build clients, servers, or both. + +* [*Ease of Use.] HTTP messages are modeled using simple, readily +accessible objects. Functions and classes used to send and receive HTTP +or WebSocket messages are designed to resemble Boost.Asio as closely as +possible. Users familiar with Boost.Asio will be immediately comfortable +using this library. + +* [*Flexibility.] Interfaces do not mandate specific implementation +strategies; important decisions such as buffer or thread management are +left to users of the library. + +* [*Performance.] The implementation performs competitively, making it a +realistic choice for building high performance network servers. + +* [*Scalability.] Development of network applications that scale to thousands +of concurrent connections is possible with the implementation. + +* [*Basis for further abstraction.] The interfaces facilitate the +development of other libraries that provide higher levels of abstraction. + +The HTTP portion of Beast is designed to be a low-level building block for +creating higher level libraries. It implements only the HTTP protocol, and +does not handle domain specific features (for example: cookies, redirects, or +deflate content encodings). + +[heading Requirements] + +Beast requires: + +* [*C++11.] A minimum of C++11 is needed. +* [*Boost.] Beast is built on Boost, especially Boost.Asio. +* [*OpenSSL.] If using TLS/Secure sockets (optional). + +[note Tested compilers: msvc-14+, gcc 5+, clang 3.6+] + +The library is [*header-only]. It is not necessary to add any .cpp files, +or to add commands to your build script for building Beast. To link your +program successfully, you'll need to add the Boost.System library to link +with. If you use coroutines you'll also need the Boost.Coroutine library. +Please visit the Boost documentation for instructions on how to do this for +your particular build system. + +[heading Motivation] + +Beast is built on Boost.Asio A proposal to add networking functionality to the +C++ standard library, based on Boost.Asio, is under consideration by the +committee and on track for standardization. Since the final approved networking +interface for the C++ standard library will likely closely resemble the current +interface of Boost.Asio, the choice of Boost.Asio as the network transport +layer is prudent. + +The HTTP protocol is pervasive in network applications. As C++ is a logical +choice for high performance network servers, there is great utility in solid +building blocks for manipulating, sending, and receiving HTTP messages +compliant with the Hypertext Transfer Protocol and the supplements that +follow. Unfortunately reliable implementations or industry standards do not +exist in C++. The development of higher level libraries is stymied by the +lack of a common set of low-level algorithms and types for interacting with +the HTTP protocol. + +Today's web applications increasingly rely on alternatives to standard HTTP +to achieve performance and/or responsiveness. While WebSocket implementations +are widely available in common web development languages such as Javascript, +good implementations in C++ are scarce. A survey of existing C++ WebSocket +solutions reveals interfaces which lack symmetry, impose performance penalties, +and needlessly restrict implementation strategies. + +Beast.WebSocket takes advantage of Boost.Asio's extensible asynchronous +model, handler allocation, and handler invocation hooks. Calls to +Beast.WebSocket asynchronous initiation functions allow callers the choice +of using a completion handler, stackful or stackless coroutines, futures, +or user defined customizations (for example, Boost.Fiber). The +implementation uses handler invocation hooks (__asio_handler_invoke__), +providing execution guarantees on composed operations in a manner identical +to Boost.Asio. The implementation also uses handler allocation hooks +(__asio_handler_allocate__) when allocating memory internally for composed +operations. + +There is no need for inheritance or virtual members in a +[link beast.ref.websocket__stream `websocket::stream`]. +All operations are templated and transparent to the compiler, allowing for +maximum inlining and optimization. + +[heading Credits] + +Boost.Asio is the inspiration behind which all of the interfaces and +implementation strategies are built. Some parts of the documentation are +written to closely resemble the wording and presentation of Boost.Asio +documentation. Credit goes to Christopher Kohloff for the wonderful +Asio library and the ideas upon which Beast is built. + +Beast would not be possible without the considerable time and patience +contributed by David Schwartz, Edward Hennis, Howard Hinnant, Miguel Portilla, +Nikolaos Bougalis, Scott Determan, Scott Schurr, and Ripple Labs for +supporting its development. + +[endsect] diff --git a/doc/quickref.xml b/doc/quickref.xml index 729a0ad5..cf3f12cf 100644 --- a/doc/quickref.xml +++ b/doc/quickref.xml @@ -71,12 +71,12 @@ Concepts - Body - Field - FieldSequence - Parser - Reader - Writer + Body + Field + FieldSequence + Parser + Reader + Writer @@ -181,11 +181,11 @@ Concepts - AsyncStream - BufferSequence - DynamicBuffer - Stream - SyncStream + AsyncStream + BufferSequence + DynamicBuffer + Stream + SyncStream diff --git a/doc/reference.xsl b/doc/reference.xsl index 4c37e306..fa9703bc 100644 --- a/doc/reference.xsl +++ b/doc/reference.xsl @@ -31,8 +31,6 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ] -[section:ref Reference] - - ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/asynchronous_operations.html#boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]`` + __void_or_deduced__ @@ -1528,47 +1525,50 @@ - class ``[link beast.types.streams.AsyncStream [*AsyncStream]]`` + class ``[link beast.ref.streams.AsyncStream [*AsyncStream]]`` - class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/AsyncReadStream.html [*AsyncReadStream]]`` + class __AsyncReadStream__ - class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/AsyncWriteStream.html [*AsyncWriteStream]]`` + class __AsyncWriteStream__ - class ``[link beast.types.Body [*Body]]`` + class ``[link beast.ref.Body [*Body]]`` - class ``[link beast.types.BufferSequence [*BufferSequence]]`` + class ``[link beast.ref.BufferSequence [*BufferSequence]]`` - ``[link beast.types.BufferSequence [*BufferSequence]]`` + ``[link beast.ref.BufferSequence [*BufferSequence]]`` - class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/CompletionHandler.html [*CompletionHandler]]`` + class __CompletionHandler__ - class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/ConstBufferSequence.html [*ConstBufferSequence]]`` + class __ConstBufferSequence__ - class ``[link beast.types.DynamicBuffer [*DynamicBuffer]]`` + class ``[link beast.ref.DynamicBuffer [*DynamicBuffer]]`` - class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/MutableBufferSequence.html [*MutableBufferSequence]]`` + class __MutableBufferSequence__ + + + class ``[link beast.ref.Parser [*Parser]]`` - class ``[link beast.types.streams.Stream [*Stream]]`` + class ``[link beast.ref.streams.Stream [*Stream]]`` - class ``[link beast.types.streams.SyncStream [*SyncStream]]`` + class ``[link beast.ref.streams.SyncStream [*SyncStream]]`` - class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/SyncReadStream.html [*SyncReadStream]]`` + class __SyncReadStream__ - class ``[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/SyncWriteStream.html [*SyncWriteStream]]`` + class __SyncWriteStream__ diff --git a/doc/source.dox b/doc/source.dox index 6e56005f..240c61de 100644 --- a/doc/source.dox +++ b/doc/source.dox @@ -109,51 +109,6 @@ INPUT = \ ../include/beast/websocket \ ../include/beast/doc_debug.hpp \ - ../include/beast/async_completion.hpp \ - ../include/beast/basic_streambuf.hpp \ - ../include/beast/bind_handler.hpp \ - ../include/beast/buffer_cat.hpp \ - ../include/beast/buffers_adapter.hpp \ - ../include/beast/consuming_buffers.hpp \ - ../include/beast/handler_alloc.hpp \ - ../include/beast/http.hpp \ - ../include/beast/placeholders.hpp \ - ../include/beast/prepare_buffers.hpp \ - ../include/beast/static_streambuf.hpp \ - ../include/beast/streambuf.hpp \ - ../include/beast/streambuf_readstream.hpp \ - ../include/beast/to_string.hpp \ - ../include/beast/type_check.hpp \ - ../include/beast/websocket.hpp \ - ../include/beast/write_streambuf.hpp \ - ../include/beast/http/basic_headers.hpp \ - ../include/beast/http/basic_parser_v1.hpp \ - ../include/beast/http/body_writer.hpp \ - ../include/beast/http/chunk_encode.hpp \ - ../include/beast/http/empty_body.hpp \ - ../include/beast/http/error.hpp \ - ../include/beast/http/fields.hpp \ - ../include/beast/http/headers.hpp \ - ../include/beast/http/message.hpp \ - ../include/beast/http/message_v1.hpp \ - ../include/beast/http/method.hpp \ - ../include/beast/http/parse_error.hpp \ - ../include/beast/http/parser.hpp \ - ../include/beast/http/read.hpp \ - ../include/beast/http/resume_context.hpp \ - ../include/beast/http/rfc2616.hpp \ - ../include/beast/http/streambuf_body.hpp \ - ../include/beast/http/string_body.hpp \ - ../include/beast/http/type_check.hpp \ - ../include/beast/http/write.hpp \ - ../include/beast/websocket/error.hpp \ - ../include/beast/websocket/option.hpp \ - ../include/beast/websocket/rfc6455.hpp \ - ../include/beast/websocket/ssl.hpp \ - ../include/beast/websocket/static_string.hpp \ - ../include/beast/websocket/stream.hpp \ - ../include/beast/websocket/teardown.hpp \ - INPUT_ENCODING = UTF-8 FILE_PATTERNS = RECURSIVE = NO diff --git a/doc/types/Body.qbk b/doc/types/Body.qbk index 95c91417..41560e67 100644 --- a/doc/types/Body.qbk +++ b/doc/types/Body.qbk @@ -5,7 +5,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ] -[section:Body Body] +[section:Body Body requirements] + +A [*Body] type is supplied as a template argument to the __message__ class. It +controls both the type of the data member of the resulting message object, and +the algorithms used during parsing and serialization. In this table: @@ -22,17 +26,12 @@ In this table: will be not movable or not copyable. ] ] -[ - [`X:value_type{}`] - [] - [`DefaultConstructible`] -] [ [`Body::reader`] [] [ If present, a type meeting the requirements of - [link beast.types.Reader [*`Reader`]]. + [link beast.ref.Reader [*`Reader`]]. Provides an implementation to parse the body. ] ] @@ -41,7 +40,7 @@ In this table: [] [ If present, a type meeting the requirements of - [link beast.types.Writer [*`Writer`]]. + [link beast.ref.Writer [*`Writer`]]. Provides an implementation to serialize the body. ] ] diff --git a/doc/types/BufferSequence.qbk b/doc/types/BufferSequence.qbk index 04457281..ae493f48 100644 --- a/doc/types/BufferSequence.qbk +++ b/doc/types/BufferSequence.qbk @@ -5,7 +5,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ] -[section:BufferSequence BufferSequence] +[section:BufferSequence BufferSequence requirements] A `BufferSequence` is a type meeting either of the following requirements: diff --git a/doc/types/DynamicBuffer.qbk b/doc/types/DynamicBuffer.qbk index dd0243bf..ff8c1225 100644 --- a/doc/types/DynamicBuffer.qbk +++ b/doc/types/DynamicBuffer.qbk @@ -5,7 +5,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ] -[section:DynamicBuffer DynamicBuffer] +[section:DynamicBuffer DynamicBuffer requirements] A dynamic buffer encapsulates memory storage that may be automatically resized as required, where the memory is divided into an input sequence followed by an @@ -27,7 +27,7 @@ implementation strategies: * A sequence of one or more octet arrays of varying sizes. Additional octet array objects are appended to the sequence to accommodate changes in the - size of the character sequence. This is the implementation approached + size of the character sequence. This is the implementation approach currently offered by [link beast.ref.basic_streambuf `basic_streambuf`]. In the table below: @@ -88,7 +88,7 @@ In the table below: ] [ [`a.prepare(n)`] - [`X:mutable_buffers_type`] + [`X::mutable_buffers_type`] [ Returns a mutable buffer sequence u representing the output sequence, and where `buffer_size(u) == n`. The dynamic buffer reallocates memory diff --git a/doc/types/Field.qbk b/doc/types/Field.qbk index e5d8b22c..c2492527 100644 --- a/doc/types/Field.qbk +++ b/doc/types/Field.qbk @@ -5,7 +5,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ] -[section:Field Field] +[section:Field Field requirements] A [*`Field`] represents a single HTTP header field/value pair. diff --git a/doc/types/FieldSequence.qbk b/doc/types/FieldSequence.qbk index c0cd123b..31eea252 100644 --- a/doc/types/FieldSequence.qbk +++ b/doc/types/FieldSequence.qbk @@ -5,10 +5,11 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ] -[section:FieldSequence FieldSequence] +[section:FieldSequence FieldSequence requirements] A [*`FieldSequence`] is an iterable container whose value type meets -the requirements of [link beast.types.Field [*`Field`]]. +the requirements of [link beast.ref.Field [*`Field`]]. Objects meeting +these requirements are serializable. In this table: diff --git a/doc/types/Parser.qbk b/doc/types/Parser.qbk index 0690f23f..30962690 100644 --- a/doc/types/Parser.qbk +++ b/doc/types/Parser.qbk @@ -5,9 +5,9 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ] -[section:Parser Parser] +[section:Parser Parser requirements] -A [*`Parser`] is used to deserialize HTTP/1 messages from [link beast.types.streams streams]. +A [*`Parser`] is used to deserialize HTTP/1 messages from [link beast.ref.streams streams]. Objects of this type are used with [link beast.ref.http__parse http::parse] and [link beast.ref.http__async_parse http::async_parse]. @@ -17,7 +17,7 @@ In this table: * `a` denotes a value of type `X`. -* `b` is a value meeting the requirements of [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/ConvertibleToConstBuffer.html [*`ConvertibleToConstBuffer`]]. +* `b` is a value meeting the requirements of [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/ConstBufferSequence.html [*`ConstBufferSequence`]]. * `ec` is a value of type [link beast.ref.error_code `error_code&`]. @@ -34,11 +34,11 @@ In this table: [`a.write(b, ec)`] [`std::size_t`] [ - Parses the octets in the specified input buffer sequentially until - an error occurs, the end of the buffer is reached, or a complete - HTTP/1 message has been parsed. If an error occurs, `ec` is set - to the error code and parsing stops. This function returns the - number of bytes consumed from the input buffer. + Sequentially parses the octets in the specified input buffer or input + buffer sequence until an error occurs, the end of the buffer is reached, + or a complete HTTP/1 message has been parsed. If an error occurs, `ec` + is set to the error code and parsing stops. Upon success, this function + returns the number of bytes used from the input. ] ] [ diff --git a/doc/types/Reader.qbk b/doc/types/Reader.qbk index a94db4d0..48ee847f 100644 --- a/doc/types/Reader.qbk +++ b/doc/types/Reader.qbk @@ -5,7 +5,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ] -[section:Reader Reader] +[section:Reader Reader requirements] Parser implementations will construct the corresponding `reader` object during the parse. This customization point allows the Body to determine diff --git a/doc/types/Streams.qbk b/doc/types/Streams.qbk index fb0920a1..a5493600 100644 --- a/doc/types/Streams.qbk +++ b/doc/types/Streams.qbk @@ -5,7 +5,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ] -[section:streams Streams] +[section:streams Streams requirements] Stream types represent objects capable of performing synchronous or asynchronous I/O. They are based on concepts from `boost::asio`. diff --git a/doc/types/Writer.qbk b/doc/types/Writer.qbk index f2756527..b4cd3eb0 100644 --- a/doc/types/Writer.qbk +++ b/doc/types/Writer.qbk @@ -5,7 +5,7 @@ file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) ] -[section:Writer Writer] +[section:Writer Writer requirements] A `Writer` serializes the message body. The implementation creates an instance of this type when serializing a message, and calls into it zero or more times diff --git a/doc/websocket.qbk b/doc/websocket.qbk index ff9c235e..057c919b 100644 --- a/doc/websocket.qbk +++ b/doc/websocket.qbk @@ -7,6 +7,22 @@ [section:websocket WebSocket] +[block ''' + + Creation + Making connections + Handshaking + Messages + Frames + Control frames + Pong messages + Buffers + Asynchronous interface + The io_service + Thread Safety + +'''] + The WebSocket Protocol enables two-way communication between a client running untrusted code in a controlled environment to a remote host that has opted-in to communications from that code. The protocol consists of an opening @@ -22,48 +38,12 @@ C++ approach. The WebSocket protocol is described fully in [@https://tools.ietf.org/html/rfc6455 rfc6455] +[note + The following documentation assumes familiarity with both + Boost.Asio and the WebSocket protocol specification described in __rfc6455__. +] -[section:motivation Motivation] - -Today's web applications increasingly rely on alternatives to standard HTTP -to achieve performance and/or responsiveness. While WebSocket implementations -are widely available in common web development languages such as Javascript, -good implementations in C++ are scarce. A survey of existing C++ WebSocket -solutions reveals interfaces which lack symmetry, impose performance penalties, -and needlessly restrict implementation strategies. - -Beast.WebSocket is built on Boost.Asio, a robust cross platform networking -framework that is part of Boost and also offered as a standalone library. -A proposal to add networking functionality to the C++ standard library, -based on Boost.Asio, is under consideration by the standards committee. -Since the final approved networking interface for the C++ standard library -will likely closely resemble the current interface of Boost.Asio, it is -logical for Beast.WebSocket to use Boost.Asio as its network transport. - -Beast.WebSocket takes advantage of Boost.Asio's extensible asynchronous -model, handler allocation, and handler invocation hooks. Calls to -Beast.WebSocket asynchronous initiation functions allow callers the choice -of using a completion handler, stackful or stackless coroutines, futures, -or user defined customizations (for example, Boost.Fiber). The -implementation uses handler invocation hooks -([@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/asio_handler_invoke.html `asio_handler_invoke`]), -providing execution guarantees on composed operations in a manner -identical to Boost.Asio. The implementation also uses handler allocation hooks -([@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/asio_handler_allocate.html `asio_handler_allocate`]) -when allocating memory internally for composed operations. - -There is no need for inheritance or virtual members in a -[link beast.ref.websocket__stream `beast::websocket::stream`]. -All operations are templated and transparent to the compiler, allowing for -maximum inlining and optimization. - -[note The documentation which follows assumes familiarity with -both Boost.Asio and the WebSocket protocol specification described in -[@https://tools.ietf.org/html/rfc6455 rfc6455] ] - -[endsect] - [section:creation Creation] @@ -71,15 +51,15 @@ both Boost.Asio and the WebSocket protocol specification described in The interface to Beast's WebSocket implementation is a single template class [link beast.ref.websocket__stream `beast::websocket::stream`] which wraps a "next layer" object. The next layer object must meet the requirements -of [link beast.types.streams.SyncStream [*`SyncReadStream`]] if synchronous +of [link beast.ref.streams.SyncStream [*`SyncReadStream`]] if synchronous operations are performed, or -[link beast.types.streams.AsyncStream [*`AsyncStream`]] if asynchronous +[link beast.ref.streams.AsyncStream [*`AsyncStream`]] if asynchronous operations are performed, or both. Arguments supplied during construction are 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); +beast::websocket::stream ws{ios}; ``` [heading Using SSL] @@ -92,8 +72,8 @@ argument when constructing the stream. #include boost::asio::io_service ios; -boost::asio::ssl::context ctx(boost::asio::ssl::context::sslv23); -beast::websocket::stream ws(ios, ctx); +boost::asio::ssl::context ctx{boost::asio::ssl::context::sslv23}; +beast::websocket::stream ws{ios, ctx}; ``` [note @@ -108,7 +88,7 @@ to wrap an object that already exists. This socket can be moved in: ``` boost::asio::ip::tcp::socket&& sock; ... - beast::websocket::stream ws(std::move(sock)); + beast::websocket::stream ws{std::move(sock)}; ``` Or, the wrapper can be constructed with a non-owning reference. In @@ -117,35 +97,37 @@ underlying socket being wrapped: ``` boost::asio::ip::tcp::socket sock; ... - beast::websocket::stream ws(sock); + beast::websocket::stream ws{sock}; ``` 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> ws(ios, ctx); + boost::asio::ssl::context ctx{boost::asio::ssl::context::sslv23}; + beast::websocket::stream> ws{ios, ctx}; ... ws.next_layer().shutdown(); // ssl::stream shutdown ``` -[important Initiating read and write operations on the next layer while -websocket operations are being performed can break invariants, and -result in undefined behavior. ] +[warning + Initiating read and write operations on the next layer while + stream operations are being performed can break invariants, and + result in undefined behavior. +] [endsect] -[section:connecting Making connections] +[section:connections Making connections] Connections are established by using the interfaces which already exist for the next layer. For example, making an outgoing connection: ``` std::string const host = "mywebapp.com"; boost::asio::io_service ios; - boost::asio::ip::tcp::resolver r(ios); - beast::websocket::stream ws(ios); + boost::asio::ip::tcp::resolver r{ios}; + beast::websocket::stream ws{ios}; boost::asio::connect(ws.next_layer(), r.resolve(boost::asio::ip::tcp::resolver::query{host, "ws"})); ``` @@ -154,12 +136,14 @@ Accepting an incoming connection: ``` void do_accept(boost::asio::ip::tcp::acceptor& acceptor) { - beast::websocket::stream ws(acceptor.get_io_service()); + beast::websocket::stream ws{acceptor.get_io_service()}; acceptor.accept(ws.next_layer()); } ``` -[note Examples use synchronous interfaces for clarity of exposition. ] +[note + Examples use synchronous interfaces for clarity of exposition. +] [endsect] @@ -171,16 +155,17 @@ A WebSocket session begins when one side sends the HTTP Upgrade request for websocket, and the other side sends an appropriate HTTP response indicating that the request was accepted and that the connection has been upgraded. The HTTP Upgrade request must include the Host HTTP field, -and the URI of the resource to request. `handshake` is used to send the +and the URI of the resource to request. +[link beast.ref.websocket__stream.handshake `handshake`] is used to send the request with the required host and resource strings. ``` - beast::websocket::stream ws(ios); + beast::websocket::stream ws{ios}; ... ws.set_option(beast::websocket::keep_alive(true)); ws.handshake("ws.example.com:80", "/cgi-bin/bitcoin-prices"); ``` -The [link beast.ref.websocket__stream `beast::websocket::stream`] automatically +The [link beast.ref.websocket__stream `stream`] automatically handles receiving and processing the HTTP response to the handshake request. The call to handshake is successful if a HTTP response is received with the 101 "Switching Protocols" status code. On failure, an error is returned or an @@ -190,7 +175,7 @@ open for a subsequent handshake attempt Performing a handshake for an incoming websocket upgrade request operates similarly. If the handshake fails, an error is returned or exception thrown: ``` - beast::websocket::stream ws(ios); + beast::websocket::stream ws{ios}; ... ws.accept(); ``` @@ -205,7 +190,7 @@ void do_accept(boost::asio::ip::tcp::socket& sock) boost::asio::streambuf sb; boost::asio::read_until(sock, sb, "\r\n\r\n"); ... - beast::websocket::stream ws(sock); + beast::websocket::stream ws{sock}; ws.accept(sb.data()); ... } @@ -218,10 +203,10 @@ void do_accept(boost::asio::ip::tcp::socket& sock) { boost::asio::streambuf sb; beast::http::request request; - beast::http::read(sock, request); + beast::http::read(sock, sb, request); if(beast::http::is_upgrade(request)) { - websocket::stream ws(sock); + websocket::stream ws{sock}; ws.accept(request); ... } @@ -244,15 +229,17 @@ void echo(beast::websocket::stream& ws) beast::websocket::opcode::value op; ws.read(sb); - ws.set_option(beast::websocket::message_type(op)); + ws.set_option(beast::websocket::message_type{op}); ws.write(sb.data()); sb.consume(sb.size()); } ``` -[important Calls to [link beast.ref.websocket__stream.set_option `set_option`] -must be made from the same implicit or explicit strand as that used to perform -other operations. ] +[important + Calls to [link beast.ref.websocket__stream.set_option `set_option`] + must be made from the same implicit or explicit strand as that used + to perform other operations. +] [endsect] @@ -280,9 +267,9 @@ void echo(beast::websocket::stream& ws) if(fi.fin) break; } - ws.set_option(beast::websocket::message_type(fi.op)); + ws.set_option(beast::websocket::message_type{fi.op}); beast::consuming_buffers< - beast::streambuf::const_buffers_type> cb(sb.data()); + beast::streambuf::const_buffers_type> cb{sb.data()}; for(;;) { using boost::asio::buffer_size; @@ -321,7 +308,7 @@ of the frames making up the message. The automatic fragment size option gives callers control over the size of these frames: ``` ... - ws.set_option(beast::websocket::auto_fragment_size(8192)); + ws.set_option(beast::websocket::auto_fragment_size{8192}); ``` The WebSocket protocol defines a procedure and control message for initiating @@ -342,9 +329,8 @@ error, a read operation is required. ] [section:pongs Pong messages] To receive pong control frames, callers may register a "pong callback" using -[link beast.ref.websocket__stream.set_option `set_option`]: - -the following signature: +[link beast.ref.websocket__stream.set_option `set_option`]. The object provided +with this option should be callable with the following signature: ``` void on_pong(ping_data const& payload); ... @@ -373,7 +359,7 @@ handler of the corresponding read function.] Because calls to read data may return a variable amount of bytes, the interface to calls that read data require an object that meets the requirements -of [link beast.types.DynamicBuffer [*`DynamicBuffer`]]. This concept is modeled on +of [link beast.ref.DynamicBuffer [*`DynamicBuffer`]]. This concept is modeled on [@http://www.boost.org/doc/libs/1_61_0/doc/html/boost_asio/reference/basic_streambuf.html `boost::asio::basic_streambuf`]. The implementation does not perform queueing or buffering of messages. If @@ -429,7 +415,7 @@ use or require threads. -[section:safety Thread Safety] +[section:threads Thread Safety] Like a regular asio socket, a [link beast.ref.websocket__stream `stream`] is not thread safe. Callers are responsible for synchronizing operations on the diff --git a/include/beast/http/concepts.hpp b/include/beast/http/concepts.hpp index d8641050..fc457a3f 100644 --- a/include/beast/http/concepts.hpp +++ b/include/beast/http/concepts.hpp @@ -71,9 +71,7 @@ template struct is_Body { using type = std::integral_constant::value && - std::is_default_constructible< - typename extract_value_type::type>::value + has_value_type::value >; }; @@ -92,7 +90,7 @@ class is_Parser template().write( - std::declval(), + std::declval(), std::declval())), std::size_t>> static R check2(int); diff --git a/include/beast/websocket/stream.hpp b/include/beast/websocket/stream.hpp index b3dee5d7..d182aed9 100644 --- a/include/beast/websocket/stream.hpp +++ b/include/beast/websocket/stream.hpp @@ -72,8 +72,8 @@ struct frame_info For asynchronous operations, the type must support the @b `AsyncStream` concept. - @note A stream object must not be destroyed while there are - pending asynchronous operations associated with it. + @note A stream object must not be moved or destroyed while there + are pending asynchronous operations associated with it. @par Concepts @b `AsyncStream`, @@ -1018,7 +1018,8 @@ public: hold all the message payload bytes (which may be zero in length). Control frames encountered while reading frame or message data - are handled automatically. Pings are replied to, pongs are noted, + are handled automatically. Pings are replied to automatically, + pongs are routed to the pong callback if the option is set, and close frames initiate the WebSocket close procedure. When a close frame is received, this call will eventually return @ref error::closed. Because of the need to handle control frames, @@ -1053,7 +1054,8 @@ public: hold all the message payload bytes (which may be zero in length). Control frames encountered while reading frame or message data - are handled automatically. Pings are replied to, pongs are noted, + are handled automatically. Pings are replied to automatically, + pongs are routed to the pong callback if the option is set, and close frames initiate the WebSocket close procedure. When a close frame is received, this call will eventually return @ref error::closed. Because of the need to handle control frames, @@ -1152,7 +1154,8 @@ public: fi.fin == true, and zero bytes placed into the stream buffer. Control frames encountered while reading frame or message data - are handled automatically. Pings are replied to, pongs are noted, + are handled automatically. Pings are replied to automatically, + pongs are routed to the pong callback if the option is set, and close frames initiate the WebSocket close procedure. When a close frame is received, this call will eventually return @ref error::closed. Because of the need to handle control frames, @@ -1190,7 +1193,8 @@ public: fi.fin == true, and zero bytes placed into the stream buffer. Control frames encountered while reading frame or message data - are handled automatically. Pings are replied to, pongs are noted, + are handled automatically. Pings are replied to automatically, + pongs are routed to the pong callback if the option is set, and close frames initiate the WebSocket close procedure. When a close frame is received, this call will eventually return @ref error::closed. Because of the need to handle control frames, @@ -1233,7 +1237,8 @@ public: the stream buffer. Control frames encountered while reading frame or message data - are handled automatically. Pings are replied to, pongs are noted, + are handled automatically. Pings are replied to automatically, + pongs are routed to the pong callback if the option is set, and close frames initiate the WebSocket close procedure. When a close frame is received, this call will eventually return @ref error::closed. Because of the need to handle control frames, diff --git a/index.html b/index.html new file mode 100644 index 00000000..97143c8d --- /dev/null +++ b/index.html @@ -0,0 +1,20 @@ + + + + + +Automatic redirection failed, please go to +doc/html/index.html +
+ +Boost.Beast
+
+Copyright (C) 2013-2016 Vinnie Falco
+
+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)
+
+
+ +