Documentation work

This commit is contained in:
Vinnie Falco
2017-06-07 16:30:49 -07:00
parent 38c36ac655
commit cff5be3837
31 changed files with 510 additions and 353 deletions

View File

@@ -13,6 +13,7 @@
## Contents
- [Introduction](#introduction)
- [Audience](audience)
- [Appearances](#appearances)
- [Description](#description)
- [Requirements](#requirements)
@@ -24,37 +25,36 @@
## 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:
Beast is a cross-platform, header-only C++11 library for low-level
HTTP/1 and WebSocket protocol programming
using the consistent asynchronous networking model of Boost.Asio.
Beast is not an HTTP client or HTTP server, but it can be used to
build those things. It is intended to be a foundation for writing
other interoperable libraries by providing HTTP vocabulary types
and algorithms. The provided examples show how clients and servers
might be built.
* **Symmetry.** Interfaces are role-agnostic; the same interfaces can be
used to build clients, servers, or both.
This library is designed for:
* **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.
* **Symmetry:** Interfaces are role-agnostic; build clients, servers, or both.
* **Flexibility.** Interfaces do not mandate specific implementation
strategies; important decisions such as buffer or thread management are
left to users of the library.
* **Ease of Use:** Boost.Asio users will immediately understand Beast.
* **Performance.** The implementation performs competitively, making it a
realistic choice for building high performance network servers.
* **Flexibility:** Users make the important decisions such as buffer or
thread management.
* **Scalability.** Development of network applications that scale to thousands
of concurrent connections is possible with the implementation.
* **Performance:** Build applications handling thousands of connections or more.
* **Basis for further abstraction.** The interfaces facilitate the
development of other libraries that provide higher levels of abstraction.
* **Basis for Further Abstraction.** Components are open-ended and
suited for building higher level libraries.
Beast is used in [rippled](https://github.com/ripple/rippled), an
open source server application that implements a decentralized
cryptocurrency system.
## Audience
Beast is for network programmers who have some familiarity with
Boost.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.
## Appearances
@@ -76,17 +76,16 @@ The library has been submitted to the
## Requirements
* Boost 1.58.0 or later
* C++11 or later
* **C++11:** Robust support for most language features.
* **Boost:** Boost.Asio and some other parts of Boost.
* **OpenSSL:** Optional, for using TLS/Secure sockets.
When using Microsoft Visual C++, Visual Studio 2015 Update 3 or later is required.
These components are optionally required in order to build the
tests and examples:
These components are required in order to build the tests and examples:
* OpenSSL (optional)
* CMake 3.7.2 or later (optional)
* Properly configured bjam/b2 (optional)
* CMake 3.7.2 or later
* Properly configured bjam/b2
## Building
@@ -210,10 +209,10 @@ int main()
req.method(beast::http::verb::get);
req.target("/");
req.version = 11;
req.fields.replace("Host", host + ":" +
req.insert(beast::http::field::host, host + ":" +
boost::lexical_cast<std::string>(sock.remote_endpoint().port()));
req.fields.replace("User-Agent", "Beast");
beast::http::prepare(req);
req.insert(beast::http::field::user_agent, "Beast");
req.prepare();
beast::http::write(sock, req);
// Receive and print HTTP response using beast

View File

@@ -32,11 +32,11 @@
[def __asio_handler_invoke__ [@http://www.boost.org/doc/html/boost_asio/reference/asio_handler_invoke.html `asio_handler_invoke`]]
[def __asio_handler_allocate__ [@http://www.boost.org/doc/html/boost_asio/reference/asio_handler_allocate.html `asio_handler_allocate`]]
[def __void_or_deduced__ [@http://www.boost.org/doc/html/boost_asio/reference/asynchronous_operations.html#boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]]
[def __use_future__ [@http://www.boost.org/doc/html/boost_asio/reference/use_future_t.html `boost::asio::use_future`]]
[def __yield_context__ [@http://www.boost.org/doc/html/boost_asio/reference/yield_context.html `boost::asio::yield_context`]]
[def __io_service__ [@http://www.boost.org/doc/html/boost_asio/reference/io_service.html `io_service`]]
[def __streambuf__ [@http://www.boost.org/doc/html/boost_asio/reference/streambuf.html [*boost::asio::streambuf]]]
[def __use_future__ [@http://www.boost.org/doc/html/boost_asio/reference/use_future_t.html `boost::asio::use_future`]]
[def __void_or_deduced__ [@http://www.boost.org/doc/html/boost_asio/reference/asynchronous_operations.html#boost_asio.reference.asynchronous_operations.return_type_of_an_initiating_function ['void-or-deduced]]]
[def __yield_context__ [@http://www.boost.org/doc/html/boost_asio/reference/yield_context.html `boost::asio::yield_context`]]
[def __AsyncReadStream__ [@http://www.boost.org/doc/html/boost_asio/reference/AsyncReadStream.html [*AsyncReadStream]]]
[def __AsyncWriteStream__ [@http://www.boost.org/doc/html/boost_asio/reference/AsyncWriteStream.html [*AsyncWriteStream]]]
@@ -47,27 +47,29 @@
[def __SyncReadStream__ [@http://www.boost.org/doc/html/boost_asio/reference/SyncReadStream.html [*SyncReadStream]]]
[def __SyncWriteStream__ [@http://www.boost.org/doc/html/boost_asio/reference/SyncWriteStream.html [*SyncWriteStream]]]
[def __AsyncStream__ [link beast.concept.streams.AsyncStream [*AsyncStream]]]
[def __Body__ [link beast.concept.Body [*Body]]]
[def __BodyReader__ [link beast.concept.BodyReader [*BodyReader]]]
[def __BodyWriter__ [link beast.concept.BodyWriter [*BodyWriter]]]
[def __DynamicBuffer__ [link beast.concept.DynamicBuffer [*DynamicBuffer]]]
[def __Fields__ [link beast.concept.Fields [*Fields]]]
[def __FieldsReader__ [link beast.concept.FieldsReader [*FieldsReader]]]
[def __Stream__ [link beast.concept.streams [*Stream]]]
[def __SyncStream__ [link beast.concept.streams.SyncStream [*SyncStream]]]
[def __AsyncStream__ [link beast.concept.streams.AsyncStream [*AsyncStream]]]
[def __Body__ [link beast.concept.Body [*Body]]]
[def __BodyReader__ [link beast.concept.BodyReader [*BodyReader]]]
[def __BodyWriter__ [link beast.concept.BodyWriter [*BodyWriter]]]
[def __DynamicBuffer__ [link beast.concept.DynamicBuffer [*DynamicBuffer]]]
[def __Fields__ [link beast.concept.Fields [*Fields]]]
[def __FieldsReader__ [link beast.concept.FieldsReader [*FieldsReader]]]
[def __Stream__ [link beast.concept.streams [*Stream]]]
[def __SyncStream__ [link beast.concept.streams.SyncStream [*SyncStream]]]
[def __basic_fields__ [link beast.ref.http__basic_fields `basic_fields`]]
[def __basic_multi_buffer__ [link beast.ref.basic_multi_buffer `basic_multi_buffer`]]
[def __basic_parser__ [link beast.ref.http__basic_parser `basic_parser`]]
[def __buffer_body__ [link beast.ref.http__buffer_body `buffer_body`]]
[def __fields__ [link beast.ref.http__fields `fields`]]
[def __flat_buffer__ [link beast.ref.flat_buffer `flat_buffer`]]
[def __header__ [link beast.ref.http__header `header`]]
[def __message__ [link beast.ref.http__message `message`]]
[def __multi_buffer__ [link beast.ref.multi_buffer `multi_buffer`]]
[def __parser__ [link beast.ref.http__parser `parser`]]
[def __serializer__ [link beast.ref.http__serializer `serializer`]]
[def __basic_fields__ [link beast.ref.http__basic_fields `basic_fields`]]
[def __basic_multi_buffer__ [link beast.ref.basic_multi_buffer `basic_multi_buffer`]]
[def __basic_parser__ [link beast.ref.http__basic_parser `basic_parser`]]
[def __buffer_body__ [link beast.ref.http__buffer_body `buffer_body`]]
[def __fields__ [link beast.ref.http__fields `fields`]]
[def __flat_buffer__ [link beast.ref.flat_buffer `flat_buffer`]]
[def __header__ [link beast.ref.http__header `header`]]
[def __message__ [link beast.ref.http__message `message`]]
[def __multi_buffer__ [link beast.ref.multi_buffer `multi_buffer`]]
[def __parser__ [link beast.ref.http__parser `parser`]]
[def __serializer__ [link beast.ref.http__serializer `serializer`]]
[def __static_buffer__ [link beast.ref.static_buffer `static_buffer`]]
[def __static_buffer_n__ [link beast.ref.static_buffer_n `static_buffer_n`]]
[import ../examples/http_example.cpp]
[import ../examples/websocket_example.cpp]
@@ -75,6 +77,8 @@
[import ../examples/doc_http_samples.hpp]
[import ../test/core/doc_snippets.cpp]
[import ../test/http/doc_snippets.cpp]
[import ../test/websocket/doc_snippets.cpp]
[import ../test/websocket/ssl/doc_snippets.cpp]
[include 1_overview.qbk]
[include 2_examples.qbk]

View File

@@ -8,107 +8,94 @@
[section:overview Introduction]
[important
Beast is a cross-platform, header-only C++11 library for low-level HTTP
and WebSocket protocol programming that uses the consistent network and
asynchronous model of __Asio__.
Beast is a cross-platform, header-only C++11 library for low-level
[*HTTP/1 and WebSocket protocol] programming
using the consistent asynchronous networking model of __Asio__.
Beast is not an HTTP client or HTTP server, but it can be used to
build those things. The library is intended to be a foundation upon
which new libraries may be built. It is a goal that other architects
will create interoperable solutions on top of Beast. The provided
example programs shows how a client or server might be built.
build those things. It is intended to be a foundation for writing
other interoperable libraries by providing HTTP vocabulary types
and algorithms. The provided examples show how clients and servers
might be built.
]
The design of the library achieves these goals:
This library is designed for:
* [*Symmetry.] Interfaces are role-agnostic; the same interfaces can be
used to build clients, servers, or both.
* [*Symmetry:] Interfaces are role-agnostic; build clients, servers, or both.
* [*Ease of Use.] HTTP messages are modeled using a simple, expressive
container. Algorithms used to send and receive HTTP or WebSocket
messages are designed to make users already familiar with __Asio__
immediately comfortable using this library.
* [*Ease of Use:] __Asio__ users will immediately understand Beast.
* [*Flexibility.] Interfaces do not mandate specific implementation
strategies; users make the important decisions such as buffer or
* [*Flexibility:] Users make the important decisions such as buffer or
thread management.
* [*Performance.] The implementation performs competitively, making it
a realistic choice for building high performance network servers.
* [*Performance:] Build applications handling thousands of connections or more.
* [*Scalability.] Development of network applications that scale to
thousands of concurrent connections is possible with the implementation.
* [*Basis for Further Abstraction.] Components are open-ended and
suited for building higher level libraries.
* [*Basis for Further Abstraction.] The interfaces facilitate the
development of other libraries that provide higher levels of abstraction.
[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.
[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
caused by the lack of a standardized C++ networking interface. This
will change soon with the Networking Technical Specification
(__N4588__): a uniform interface for networking on track to become
standardized. This technical specification is modeled closely after
Boost.Asio.
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 standardized C++
networking interface based on __N4588__.
]
[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).
* [*C++11:] Robust support for most language features.
* [*Boost:] Boost.Asio and some other parts of Boost.
* [*OpenSSL:] Optional, for using TLS/Secure sockets.
[note Supported compilers: msvc-14+, gcc 4.8+, 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.
This library is [*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
[@http://www.boost.org/libs/coroutine/doc/html/index.html Boost.Coroutine]
library. Please visit the
[@http://www.boost.org/doc/ Boost documentation]
for instructions on how to do this for your particular build system.
Beast does not compile using the stand-alone version of Asio, since it
relies on other Boost parts. There are no immediate plans to offer a
version that works with stand-alone Asio.
[heading Motivation]
There is a noted shortage of high quality C++ networking libraries,
especially for the HTTP and WebSocket protocols. The author theorizes
that previous attempts to build such libraries focused too much on end
user needs instead of applying principles of computer science to solve
the problem more formally. Another factor is that there no current
standardized interface for networking. This may change soon; with the
the introduction of the Networking Technical Specification (__N4588__),
a uniform interface for networking is on track to become standardized.
This technical specification is modeled closely after Boost.Asio.
Beast is built on Boost.Asio, with plans to adapt it to the networking
interfaces which become part of the C++ Standard.
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.
[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 have knowledge and experience with Asio's asynchronous
model and style of asynchronous programming using callbacks or coroutines.
The protocol interfaces are low level. There are no out of the box solutions
for implementing clients or servers. For example, users must provide their
own code to make connections, handle timeouts, reconnect a dropped connection,
accept incoming connections, or manage connection resources on a server.
The HTTP interfaces provide functionality only for modelling HTTP
messages and serializing or parsing them on streams, including TCP/IP
sockets or OpenSSL streams. Higher level functions such as Basic
Authentication, mime/multipart encoding, cookies, automatic handling
of redirects, gzipped transfer encodings, caching, or proxying (to name
a few) are not directly provided, but nothing stops users from creating
these features using Beast's HTTP message types.
[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
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 Kohlhoff for the wonderful
Asio library and the ideas upon which Beast is built.
documentation. Credit goes to
[@https://github.com/chriskohlhoff Christopher Kohlhoff]
for his wonderful Asio library and the ideas in __N4588__ which power Beast.
Beast would not be possible without the support of
[@https://www.ripple.com Ripple]
@@ -120,12 +107,12 @@ contributed by
[@https://github.com/miguelportilla Miguel Portilla],
[@https://github.com/nbougalis Nik Bougalis],
[@https://github.com/seelabs Scott Determan],
[@https://github.com/scottschurr],
[@https://github.com/scottschurr Scott Schurr],
Many thanks to
[@https://github.com/K-ballo Agustín Bergé],
[@http://www.boost.org/users/people/glen_fernandes.html Glen Fernandes],
and
[https://github.com/pdimov Peter Dimov]
[@https://github.com/pdimov Peter Dimov]
for tirelessly answering questions on
[@https://cpplang.slack.com/ Cpplang-Slack].

View File

@@ -7,6 +7,14 @@
[section:http Using HTTP]
[warning
Higher level functions such as Basic
Authentication, mime/multipart encoding, cookies, automatic handling
of redirects, gzipped transfer encodings, caching, or proxying (to name
a few) are not directly provided, but nothing stops users from creating
these features using Beast's HTTP message types.
]
This library offers programmers simple and performant models of HTTP messages
and their associated operations including synchronous, asynchronous, and
buffer-oriented parsing and serialization of messages in the HTTP/1 wire

View File

@@ -24,7 +24,7 @@ Every message contains a set of zero or more field name/value pairs,
collectively called "fields". The names and values are represented using
text strings with various requirements. A serialized field contains the
field name, then a colon followed by a space (`": "`), and finally the field
value.
value with a trailing CRLF.
When a client and server have established a connection and intend to
use HTTP, the client sends a series of requests while the server reads

View File

@@ -53,10 +53,12 @@ possible value of `isRequest`:
[$images/message.png [width 730px] [height 410px]]
For notational convenience, the template type aliases
The template type aliases
[link beast.ref.http__request `request`] and
[link beast.ref.http__response `response`]
are provided, which also supply commonly chosen __fields__ type as a default:
are provided for notational convenience. They also come with the default
__fields__, a common choice.
```
/// A typical HTTP request
template<class Body, class Fields = fields>
@@ -138,8 +140,8 @@ Here we create an HTTP response indicating success. Note that this
message has a body. The function
[link beast.ref.http__message.prepare prepare]
automatically sets the Content-Length or Transfer-Encoding field
depending on the body type. The use of prepare is optional, the
fields may be set manually if desired.
depending on the content and type of the `body` member. The use
of prepare is optional; these fields may also be set.
[table Create Response
[[Statements] [Serialized Result]]

View File

@@ -8,31 +8,30 @@
[section:streams Message Stream Operations]
Beast provides synchronous and asynchronous algorithms to serialize and
parse HTTP/1 wire format messages on streams. These functions form the
basic interface which works on the entire header or message at once,
requiring no separately managed state objects:
parse HTTP/1 wire format messages on streams. These functions form a
basic interface for operating on entire messages:
[table Basic Interface
[[Name][Description]]
[[
[link beast.ref.http__read.overload3 [*read]]
][
Parse a __message__ from a __SyncReadStream__.
Read a __message__ from a __SyncReadStream__.
]]
[[
[link beast.ref.http__async_read.overload2 [*async_read]]
][
Parse a __message__ from an __AsyncReadStream__.
Read a __message__ from an __AsyncReadStream__.
]]
[[
[link beast.ref.http__write.overload1 [*write]]
][
Serialize a __message__ to a __SyncWriteStream__.
Write a __message__ to a __SyncWriteStream__.
]]
[[
[link beast.ref.http__async_write [*async_write]]
][
Serialize a __message__ to an __AsyncWriteStream__.
Write a __message__ to an __AsyncWriteStream__.
]]
]
@@ -45,13 +44,13 @@ occurs this argument will be set to contain the error code.
[heading Reading]
Because a serialized header is not length-prefixed, algorithms which parse
messages from a stream may read past the end of a message for efficiency.
To hold this surplus data, all stream read operations use a passed-in
__DynamicBuffer__ which persists between calls. Each read operation may
consume bytes remaining in the buffer, and leave behind new bytes. In this
example we declare the buffer and a message variable, then read a complete
HTTP request synchronously:
Because a serialized header is not length-prefixed, algorithms which
parse messages from a stream may read past the end of a message for
efficiency. To hold this surplus data, all stream read operations use
a passed-in __DynamicBuffer__ which must be persisted between calls.
Each read operation may consume bytes remaining in the buffer, and
leave behind new bytes. In this example we declare the buffer and a
message variable, then read a complete HTTP request synchronously:
[http_snippet_4]

View File

@@ -7,21 +7,20 @@
[section:serializer_streams Serializer Stream Operations]
Algorithms for sending entire messages to streams are intended for light
duty use-cases such as simple clients and low utilization servers.
Sophisticated algorithms will need to do more:
Message oriented stream operations provide for limited control.
Sophisticated algorithms may need to do more, such as:
* Send the message header first.
* Send the header first, and the body later.
* Set chunk extensions or trailers using a chunk decorator.
* Send a message incrementally: bounded work in each I/O cycle.
* Use a custom chunk decorator or allocator when sending messages.
* Use a series of caller-provided buffers to represent the body.
All of these operations require callers to manage the lifetime of state
information associated with the operation, by constructing a __serializer__
object with the message to be sent. The serializer type has this declaration:
These tasks may be performed by using the serializer stream interfaces.
To use these interfaces, first construct a __serializer__ object with
the message to be sent. The serializer type has this declaration:
[http_snippet_9]
@@ -30,10 +29,9 @@ This code creates an HTTP response and the corresponding serializer:
[http_snippet_10]
The convenience function
The function
[link beast.ref.http__make_serializer `make_serializer`]
is provided to avoid repetition of template argument types. The declaration
for `sr` in the code above may be written as:
is provided to simplify creation of variables:
[http_snippet_11]
@@ -64,12 +62,12 @@ The stream operations which work on serializers are:
[[
[link beast.ref.http__write_some.overload1 [*write_some]]
][
Send some __serializer__ buffer data to a __SyncWriteStream__.
Send part of a __serializer__ to a __SyncWriteStream__.
]]
[[
[link beast.ref.http__async_write_some [*async_write_some]]
][
Send some __serializer__ buffer data asynchronously to an __AsyncWriteStream__.
Send part of a __serializer__ asynchronously to an __AsyncWriteStream__.
]]
]
@@ -78,4 +76,41 @@ synchronously. This performs the same operation as calling `write(stream, m)`:
[http_snippet_12]
[heading Chunk Decorators]
When the message used to construct the serializer indicates the chunked
transfer encoding, the serializer will automatically generate the proper
encoding in the output buffers. __rfc7230__ defines additional fields
called the
[@https://tools.ietf.org/html/rfc7230#section-4.1.1 chunk extensions]
in chunks with body octets, and the
[@https://tools.ietf.org/html/rfc7230#section-4.1.2 chunked trailer part]
for the final chunk. Applications that wish to emit chunk extensions
and trailers may instantiate the serializer with a "chunk decorator" type,
and pass an instance of the type upon construction. This decorator is
a function object which, when invoked with a __ConstBufferSequence__,
returns a
[link beast.ref.string_view `string_view`] containing either the extensions
or the trailer. For chunks containing body data, the passed buffer will
contain one or more corresponding body octets. The decorator may use this
information as needed. For example, to compute a digest on the data and
store it as a chunk extension. For the trailers, the serializer will
invoke the decorator with a buffer sequence of size zero. Or more
specifically, with an object of type
[@http://www.boost.org/doc/html/boost_asio/reference/null_buffers.html `boost::asio::null_buffers`].
For body chunks the string returned by the decorator must follow the
[@https://tools.ietf.org/html/rfc7230#section-4.1.1 correct syntax]
for the entire chunk extension. For the trailer, the returned string
should consist of zero or more lines ending in a CRLF and containing
a field name/value pair in the format prescribed by __rfc7230__. It
is the responsibility of the decorator to manage returned string buffers.
The implementation guarantees it will not reference previous strings
after subsequent calls.
Here, we declare a decorator which sets an extension variable `x` equal
to the size of the chunk in bytes, and returns a single trailer field:
[http_snippet_17]
[endsect]

View File

@@ -7,15 +7,15 @@
[section:parser_streams Parser Stream Operations]
Algorithms for receiving entire messages from streams are helpful for simple
use-cases. Sophisticated algorithms will need to do more:
Message oriented stream operations provide for limited control.
Sophisticated algorithms may need to do more, such as:
* Receive the message header first.
* Receive the header first, then the body later.
* Receive a large body using a fixed-size buffer.
* Receive a message incrementally: bounded work in each I/O cycle.
* Receive an arbitrarily-sized body using a fixed-size buffer.
* Defer the commitment to a __Body__ type until after reading the header.
All of these operations require callers to manage the lifetime of state
@@ -99,21 +99,20 @@ The stream operations which work on parsers are:
]]
]
As with the stream parse algorithms which operate on entire messages, stream
operations for parsers require a passed-in __DynamicBuffer__ which persists
between calls to hold unused octets from the stream. The basic parser
implementation is optimized for the case where this dynamic buffer stores
its input sequence in a single contiguous memory buffer. It is advised to
use an instance of __flat_buffer__ for this purpose, although a user defined
instance of __DynamicBuffer__ which produces input sequences of length one
is also suitable.
As with message stream operations, parser stream operations require a
persisted __DynamicBuffer__ for holding unused octets from the stream.
The basic parser implementation is optimized for the case where this dynamic
buffer stores its input sequence in a single contiguous memory buffer. It is
advised to use an instance of __flat_buffer__, __static_buffer__, or
__static_buffer_n__ for this purpose, although a user defined instance of
__DynamicBuffer__ which produces input sequences of length one is also suitable.
The provided parsers use a "captive object" model, acting as container for
the __message__ or __header__ produced as a result of parsing. The caller
accesses the contained object, and depending on the types used to instantiate
the parser, it may be possible to acquire ownership of the header or message
captive object and destroy the parser. In this example we read an HTTP
response with a string body using a parser, then print the response:
the __message__ produced as a result of parsing. The caller accesses the
contained object, and depending on the types used to instantiate the parser,
it may be possible to acquire ownership of the header or message captive
object and destroy the parser. In this example we read an HTTP response
with a string body using a parser, then print the response:
[http_snippet_13]

View File

@@ -55,41 +55,4 @@ C++14 example we print the header first, followed by the body:
[http_snippet_16]
[heading Chunk Decorators]
When the message used to construct the serializer indicates the chunked
transfer encoding, the serializer will automatically generate the proper
encoding in the output buffers. __rfc7230__ defines additional fields
called the
[@https://tools.ietf.org/html/rfc7230#section-4.1.1 chunk extensions]
in chunks with body octets, and the
[@https://tools.ietf.org/html/rfc7230#section-4.1.2 chunked trailer part]
for the final chunk. Applications that wish to emit chunk extensions
and trailers may instantiate the serializer with a "chunk decorator" type,
and pass an instance of the type upon construction. This decorator is
a function object which, when invoked with a __ConstBufferSequence__,
returns a
[link beast.ref.string_view `string_view`] containing either the extensions
or the trailer. For chunks containing body data, the passed buffer will
contain one or more corresponding body octets. The decorator may use this
information as needed. For example, to compute a digest on the data and
store it as a chunk extension. For the trailers, the serializer will
invoke the decorator with a buffer sequence of size zero. Or more
specifically, with an object of type
[@http://www.boost.org/doc/html/boost_asio/reference/null_buffers.html `boost::asio::null_buffers`].
For body chunks the string returned by the decorator must follow the
[@https://tools.ietf.org/html/rfc7230#section-4.1.1 correct syntax]
for the entire chunk extension. For the trailer, the returned string
should consist of zero or more lines ending in a CRLF and containing
a field name/value pair in the format prescribed by __rfc7230__. It
is the responsibility of the decorator to manage returned string buffers.
The implementation guarantees it will not reference previous strings
after subsequent calls.
Here, we declare a decorator which sets an extension variable `x` equal
to the size of the chunk in bytes, and returns a single trailer field:
[http_snippet_17]
[endsect]

View File

@@ -10,7 +10,7 @@
In some cases, users may wish to create an instance of __parser__, or a
user-defined type derived from __basic_parser__ and invoke its methods
directly instead of using the provided stream algorithms. This could be
useful for implementing algorithms on streams whose interface does not
useful for implementing algorithms on objects whose interface does not
conform to any __Stream__. For example, a
[@http://zeromq.org/ *ZeroMQ* socket].
The basic parser interface is interactive; the caller invokes the function

View File

@@ -7,6 +7,10 @@
[section HTTP 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.
[section Expect 100-continue (Client)]
The Expect field with the value "100-continue" in a request is special. It

View File

@@ -19,12 +19,12 @@ Beast provides developers with a robust WebSocket implementation built on
Boost.Asio with a consistent asynchronous model using a modern C++ approach.
[note
The WebSocket documentation assumes familiarity the WebSocket protocol
specification described in __rfc6455__. Code appearing in these
sections is written as if the following declarations are in effect:
```
#include <beast/websocket.hpp>
```
This documentation assumes familiarity with __Asio__ and
the protocol specification described in __rfc6455__.
Sample code and identifiers appearing in this section is written
as if these declarations are in effect:
[ws_snippet_1]
]
[include 6_1_streams.qbk]

View File

@@ -8,7 +8,7 @@
[section:streams Creating Streams]
The interface to the WebSocket implementation is a single template class
[link beast.ref.websocket__stream `websocket::stream`]
[link beast.ref.websocket__stream `stream`]
which wraps an existing network transport object or other type of
octet oriented stream. The wrapped object is called the "next layer"
and must meet the requirements of __SyncStream__ if synchronous
@@ -19,28 +19,21 @@ the stream wrapper are passed to next layer's constructor.
Here we declare a websocket stream over a TCP/IP socket with ownership
of the socket. The `io_service` argument is forwarded to the wrapped
socket's constructor:
```
boost::asio::io_service ios;
beast::websocket::stream<boost::asio::ip::tcp::socket> ws{ios};
```
[ws_snippet_2]
[heading Using SSL]
To use WebSockets over SSL, use an instance of the `boost::asio::ssl::stream`
class template as the template type for the stream. The required `io_service`
and `ssl::context` arguments are forwarded to the wrapped stream's constructor:
```
#include <beast/websocket/ssl.hpp>
#include <boost/asio/ssl.hpp>
boost::asio::io_service ios;
boost::asio::ssl::context ctx{boost::asio::ssl::context::sslv23};
beast::websocket::stream<boost::asio::ssl::stream<boost::asio::ip::tcp::socket> ws{ios, ctx};
```
[wss_snippet_1]
[wss_snippet_2]
[note
Code which declares stream objects using Asio SSL types must
to include the file `<beast/websocket/ssl.hpp>`.
Code which declares stream objects using Asio SSL types
must include the file `<beast/websocket/ssl.hpp>`.
]
[heading Non-owning References]
@@ -48,27 +41,20 @@ and `ssl::context` arguments are forwarded to the wrapped stream's constructor:
If a socket type supports move construction, a websocket stream may be
constructed around the already existing socket by invoking the move
constructor signature:
```
...
beast::websocket::stream<boost::asio::ip::tcp::socket> ws{std::move(sock)};
```
[ws_snippet_3]
Or, the wrapper can be constructed with a non-owning reference. In
this case, the caller is responsible for managing the lifetime of the
underlying socket being wrapped:
```
...
beast::websocket::stream<boost::asio::ip::tcp::socket&> ws{sock};
```
[ws_snippet_4]
Once the WebSocket stream wrapper is created, the wrapped object may be
accessed by calling [link beast.ref.websocket__stream.next_layer.overload1 `stream::next_layer`]:
```
boost::asio::ssl::context ctx{boost::asio::ssl::context::sslv23};
beast::websocket::stream<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> ws{ios, ctx};
...
ws.next_layer().shutdown(); // ssl::stream shutdown
```
accessed by calling
[link beast.ref.websocket__stream.next_layer.overload1 `stream::next_layer`]:
[ws_snippet_5]
[warning
Initiating operations on the next layer while websocket

View File

@@ -10,42 +10,20 @@
Connections are established by invoking functions directly on the next layer
object. For example, to make an outgoing connection using a standard TCP/IP
socket:
```
std::string const host = "mywebapp.com";
boost::asio::io_service ios;
boost::asio::ip::tcp::resolver r{ios};
beast::websocket::stream<boost::asio::ip::tcp::socket> ws{ios};
boost::asio::connect(ws.next_layer(),
r.resolve(boost::asio::ip::tcp::resolver::query{host, "ws"}));
```
[ws_snippet_6]
Similarly, to accept an incoming connection using a standard TCP/IP
socket, pass the next layer object to the acceptor:
```
void do_accept(boost::asio::ip::tcp::acceptor& acceptor)
{
beast::websocket::stream<boost::asio::ip::tcp::socket> ws{acceptor.get_io_service()};
acceptor.accept(ws.next_layer());
}
```
[ws_snippet_7]
When using SSL, which itself wraps a next layer object that is usually a
TCP/IP socket, multiple calls to retrieve the next layer may be required.
In this example, the websocket stream wraps the SSL stream which wraps
the TCP/IP socket:
```
beast::websocket::stream<boost::asio::ssl::stream<
boost::asio::ip::tcp::socket>> ws{ios, ctx};
// connect the underlying TCP/IP socket
ws.next_layer().next_layer().connect(ep);
// perform SSL handshake
ws.next_layer().handshake(boost::asio::ssl::stream_base::client);
// perform WebSocket handshake
ws.handshake("localhost", "/");
```
[wss_snippet_3]
[note
Examples use synchronous interfaces for clarity of exposition.

View File

@@ -7,13 +7,9 @@
#include <beast.hpp>
/*
This file contains all of the example code snippets contained
in the documentation, which directly includes this source code.
*/
// Contains the HTTP Examples from the documentation.
// The documentation assumes the beast::http namespace
namespace beast {
namespace http {
@@ -194,7 +190,7 @@ send_cgi_response(
// Set up the response. We use the buffer_body type,
// allowing serialization to use manually provided buffers.
message<false, buffer_body, fields> res;
response<buffer_body> res;
res.result(status::ok);
res.version = 11;

View File

@@ -0,0 +1,19 @@
//
// 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)
//
#include <beast.hpp>
// Contains the WebSocket Examples from the documentation.
// The documentation assumes the beast::websocket namespace
namespace beast {
namespace websocket {
} // websocket
} // beast

View File

@@ -29,9 +29,9 @@ int main()
req.method(beast::http::verb::get);
req.target("/");
req.version = 11;
req.replace("Host", host + ":" +
req.insert(beast::http::field::host, host + ":" +
boost::lexical_cast<std::string>(sock.remote_endpoint().port()));
req.replace("User-Agent", "Beast");
req.insert(beast::http::field::user_agent, "Beast");
req.prepare();
beast::http::write(sock, req);

View File

@@ -39,7 +39,11 @@ namespace http {
@li @ref error::end_of_stream if no octets were parsed, or
@li @ref error::partial_message if any octets were parsed.
@li @ref error::partial_message if any octets were parsed but the
message was incomplete, otherwise:
@li A successful result. A subsequent attempt to read will
return @ref error::end_of_stream
@param stream The stream from which the data is to be read.
The type must support the @b SyncReadStream concept.
@@ -86,7 +90,11 @@ read_some(
@li @ref error::end_of_stream if no octets were parsed, or
@li @ref error::partial_message if any octets were parsed.
@li @ref error::partial_message if any octets were parsed but the
message was incomplete, otherwise:
@li A successful result. A subsequent attempt to read will
return @ref error::end_of_stream
The function returns the number of bytes processed from the dynamic
buffer. The caller should remove these bytes by calling `consume` on
@@ -141,7 +149,11 @@ read_some(
@li @ref error::end_of_stream if no octets were parsed, or
@li @ref error::partial_message if any octets were parsed.
@li @ref error::partial_message if any octets were parsed but the
message was incomplete, otherwise:
@li A successful result. A subsequent attempt to read will
return @ref error::end_of_stream
@param stream The stream from which the data is to be read.
The type must support the @b AsyncReadStream concept.
@@ -212,7 +224,11 @@ async_read_some(
@li @ref error::end_of_stream if no octets were parsed, or
@li @ref error::partial_message if any octets were parsed.
@li @ref error::partial_message if any octets were parsed but the
message was incomplete, otherwise:
@li A successful result. A subsequent attempt to read will
return @ref error::end_of_stream
@param stream The stream from which the data is to be read.
The type must support the @b SyncReadStream concept.
@@ -261,7 +277,11 @@ read_header(
@li @ref error::end_of_stream if no octets were parsed, or
@li @ref error::partial_message if any octets were parsed.
@li @ref error::partial_message if any octets were parsed but the
message was incomplete, otherwise:
@li A successful result. A subsequent attempt to read will
return @ref error::end_of_stream
@param stream The stream from which the data is to be read.
The type must support the @b SyncReadStream concept.
@@ -314,7 +334,11 @@ read_header(
@li @ref error::end_of_stream if no octets were parsed, or
@li @ref error::partial_message if any octets were parsed.
@li @ref error::partial_message if any octets were parsed but the
message was incomplete, otherwise:
@li A successful result. A subsequent attempt to read will
return @ref error::end_of_stream
@param stream The stream from which the data is to be read.
The type must support the @b AsyncReadStream concept.
@@ -383,7 +407,11 @@ async_read_header(
@li @ref error::end_of_stream if no octets were parsed, or
@li @ref error::partial_message if any octets were parsed.
@li @ref error::partial_message if any octets were parsed but the
message was incomplete, otherwise:
@li A successful result. A subsequent attempt to read will
return @ref error::end_of_stream
@param stream The stream from which the data is to be read.
The type must support the @b SyncReadStream concept.
@@ -432,7 +460,11 @@ read(
@li @ref error::end_of_stream if no octets were parsed, or
@li @ref error::partial_message if any octets were parsed.
@li @ref error::partial_message if any octets were parsed but the
message was incomplete, otherwise:
@li A successful result. A subsequent attempt to read will
return @ref error::end_of_stream
@param stream The stream from which the data is to be read.
The type must support the @b SyncReadStream concept.
@@ -485,7 +517,11 @@ read(
@li @ref error::end_of_stream if no octets were parsed, or
@li @ref error::partial_message if any octets were parsed.
@li @ref error::partial_message if any octets were parsed but the
message was incomplete, otherwise:
@li A successful result. A subsequent attempt to read will
return @ref error::end_of_stream
@param stream The stream from which the data is to be read.
The type must support the @b AsyncReadStream concept.
@@ -553,7 +589,11 @@ async_read(
@li @ref error::end_of_stream if no octets were parsed, or
@li @ref error::partial_message if any octets were parsed.
@li @ref error::partial_message if any octets were parsed but the
message was incomplete, otherwise:
@li A successful result. A subsequent attempt to read will
return @ref error::end_of_stream
@param stream The stream from which the data is to be read.
The type must support the @b SyncReadStream concept.
@@ -599,7 +639,11 @@ read(
@li @ref error::end_of_stream if no octets were parsed, or
@li @ref error::partial_message if any octets were parsed.
@li @ref error::partial_message if any octets were parsed but the
message was incomplete, otherwise:
@li A successful result. A subsequent attempt to read will
return @ref error::end_of_stream
@param stream The stream from which the data is to be read.
The type must support the @b SyncReadStream concept.
@@ -650,7 +694,11 @@ read(
@li @ref error::end_of_stream if no octets were parsed, or
@li @ref error::partial_message if any octets were parsed.
@li @ref error::partial_message if any octets were parsed but the
message was incomplete, otherwise:
@li A successful result. A subsequent attempt to read will
return @ref error::end_of_stream
@param stream The stream from which the data is to be read.
The type must support the @b AsyncReadStream concept.

View File

@@ -39,8 +39,7 @@ class stream<NextLayer>::response_op
{
bool cont;
stream<NextLayer>& ws;
http::message<false,
http::empty_body, http::fields> res;
http::response<http::empty_body> res;
int state = 0;
template<class Fields, class Decorator>

View File

@@ -39,8 +39,7 @@ class stream<NextLayer>::handshake_op
stream<NextLayer>& ws;
response_type* res_p;
detail::sec_ws_key_type key;
http::message<true,
http::empty_body, http::fields> req;
http::request<http::empty_body> req;
response_type res;
int state = 0;

View File

@@ -70,6 +70,7 @@ unit-test http-bench :
unit-test websocket-tests :
../extras/beast/unit_test/main.cpp
websocket/doc_snippets.cpp
websocket/error.cpp
websocket/option.cpp
websocket/rfc6455.cpp

View File

@@ -23,14 +23,14 @@ void fxx()
//[snippet_core_1b
//
using namespace beast;
using namespace beast;
boost::asio::io_service ios;
boost::asio::io_service::work work{ios};
std::thread t{[&](){ ios.run(); }};
boost::asio::io_service ios;
boost::asio::io_service::work work{ios};
std::thread t{[&](){ ios.run(); }};
error_code ec;
boost::asio::ip::tcp::socket sock{ios};
error_code ec;
boost::asio::ip::tcp::socket sock{ios};
//]

View File

@@ -122,7 +122,6 @@ void fxx() {
//[http_snippet_10
response<string_body> res;
serializer<false, string_body, fields> sr{res};
//]

View File

@@ -74,63 +74,63 @@ public:
testMessage()
{
BOOST_STATIC_ASSERT(std::is_constructible<
message<true, default_body, fields>>::value);
request<default_body>>::value);
BOOST_STATIC_ASSERT(std::is_constructible<
message<true, one_arg_body, fields>, Arg1>::value);
request<one_arg_body>, Arg1>::value);
BOOST_STATIC_ASSERT(std::is_constructible<
message<true, one_arg_body, fields>, Arg1 const>::value);
request<one_arg_body>, Arg1 const>::value);
BOOST_STATIC_ASSERT(std::is_constructible<
message<true, one_arg_body, fields>, Arg1 const&>::value);
request<one_arg_body>, Arg1 const&>::value);
BOOST_STATIC_ASSERT(std::is_constructible<
message<true, one_arg_body, fields>, Arg1&&>::value);
request<one_arg_body>, Arg1&&>::value);
BOOST_STATIC_ASSERT(! std::is_constructible<
message<true, one_arg_body, fields>>::value);
request<one_arg_body>>::value);
BOOST_STATIC_ASSERT(std::is_constructible<
message<true, one_arg_body, fields>,
request<one_arg_body>,
Arg1, fields::allocator_type>::value);
BOOST_STATIC_ASSERT(std::is_constructible<
message<true, one_arg_body, fields>, std::piecewise_construct_t,
request<one_arg_body>, std::piecewise_construct_t,
std::tuple<Arg1>>::value);
BOOST_STATIC_ASSERT(std::is_constructible<
message<true, two_arg_body, fields>, std::piecewise_construct_t,
request<two_arg_body>, std::piecewise_construct_t,
std::tuple<Arg1, Arg2>>::value);
BOOST_STATIC_ASSERT(std::is_constructible<
message<true, two_arg_body, fields>, std::piecewise_construct_t,
request<two_arg_body>, std::piecewise_construct_t,
std::tuple<Arg1, Arg2>, std::tuple<fields::allocator_type>>::value);
{
Arg1 arg1;
message<true, one_arg_body, fields>{std::move(arg1)};
request<one_arg_body>{std::move(arg1)};
BEAST_EXPECT(arg1.moved);
}
{
header<true, fields> h;
header<true> h;
h.insert(field::user_agent, "test");
message<true, one_arg_body, fields> m{Arg1{}, h};
request<one_arg_body> m{Arg1{}, h};
BEAST_EXPECT(h["User-Agent"] == "test");
BEAST_EXPECT(m["User-Agent"] == "test");
}
{
header<true, fields> h;
header<true> h;
h.insert(field::user_agent, "test");
message<true, one_arg_body, fields> m{Arg1{}, std::move(h)};
request<one_arg_body> m{Arg1{}, std::move(h)};
BEAST_EXPECT(! h.exists("User-Agent"));
BEAST_EXPECT(m["User-Agent"] == "test");
}
// swap
message<true, string_body, fields> m1;
message<true, string_body, fields> m2;
request<string_body> m1;
request<string_body> m2;
m1.target("u");
m1.body = "1";
m1.insert("h", "v");
@@ -197,8 +197,8 @@ public:
void
testSwap()
{
message<false, string_body, fields> m1;
message<false, string_body, fields> m2;
response<string_body> m1;
response<string_body> m2;
m1.result(status::ok);
m1.version = 10;
m1.body = "1";

View File

@@ -336,7 +336,7 @@ public:
"GET / HTTP/1.1\r\n\r\n"};
BEAST_EXPECT(handler::count() == 0);
multi_buffer b;
message<true, dynamic_body, fields> m;
request<dynamic_body> m;
async_read(is, b, m, handler{});
BEAST_EXPECT(handler::count() > 0);
ios.stop();
@@ -355,7 +355,7 @@ public:
"GET / HTTP/1.1\r\n\r\n"};
BEAST_EXPECT(handler::count() == 0);
multi_buffer b;
message<true, dynamic_body, fields> m;
request<dynamic_body> m;
async_read(is, b, m, handler{});
BEAST_EXPECT(handler::count() > 0);
}

View File

@@ -289,7 +289,7 @@ public:
testAsyncWrite(yield_context do_yield)
{
{
message<false, string_body, fields> m;
response<string_body> m;
m.version = 10;
m.result(status::ok);
m.reason("OK");
@@ -308,7 +308,7 @@ public:
"*****");
}
{
message<false, string_body, fields> m;
response<string_body> m;
m.version = 11;
m.result(status::ok);
m.reason("OK");
@@ -341,7 +341,7 @@ public:
test::fail_counter fc(n);
test::fail_stream<
test::string_ostream> fs(fc, ios_);
message<true, fail_body, fields> m{fc};
request<fail_body> m{fc};
m.method(verb::get);
m.target("/");
m.version = 10;
@@ -372,7 +372,7 @@ public:
test::fail_counter fc(n);
test::fail_stream<
test::string_ostream> fs(fc, ios_);
message<true, fail_body, fields> m{fc};
request<fail_body> m{fc};
m.method(verb::get);
m.target("/");
m.version = 10;
@@ -405,7 +405,7 @@ public:
test::fail_counter fc(n);
test::fail_stream<
test::string_ostream> fs(fc, ios_);
message<true, fail_body, fields> m{fc};
request<fail_body> m{fc};
m.method(verb::get);
m.target("/");
m.version = 10;
@@ -438,7 +438,7 @@ public:
test::fail_counter fc(n);
test::fail_stream<
test::string_ostream> fs(fc, ios_);
message<true, fail_body, fields> m{fc};
request<fail_body> m{fc};
m.method(verb::get);
m.target("/");
m.version = 10;
@@ -466,7 +466,7 @@ public:
test::fail_counter fc(n);
test::fail_stream<
test::string_ostream> fs(fc, ios_);
message<true, fail_body, fields> m{fc};
request<fail_body> m{fc};
m.method(verb::get);
m.target("/");
m.version = 10;
@@ -495,7 +495,7 @@ public:
{
// auto content-length HTTP/1.0
{
message<true, string_body, fields> m;
request<string_body> m;
m.method(verb::get);
m.target("/");
m.version = 10;
@@ -512,7 +512,7 @@ public:
}
// no content-length HTTP/1.0
{
message<true, unsized_body, fields> m;
request<unsized_body> m;
m.method(verb::get);
m.target("/");
m.version = 10;
@@ -532,7 +532,7 @@ public:
}
// auto content-length HTTP/1.1
{
message<true, string_body, fields> m;
request<string_body> m;
m.method(verb::get);
m.target("/");
m.version = 11;
@@ -549,7 +549,7 @@ public:
}
// no content-length HTTP/1.1
{
message<true, unsized_body, fields> m;
request<unsized_body> m;
m.method(verb::get);
m.target("/");
m.version = 11;
@@ -574,7 +574,7 @@ public:
void test_std_ostream()
{
// Conversion to std::string via operator<<
message<true, string_body, fields> m;
request<string_body> m;
m.method(verb::get);
m.target("/");
m.version = 11;
@@ -604,7 +604,7 @@ public:
boost::asio::io_service ios;
test::string_ostream os{ios};
BEAST_EXPECT(handler::count() == 0);
message<true, string_body, fields> m;
request<string_body> m;
m.method(verb::get);
m.version = 11;
m.target("/");
@@ -626,7 +626,7 @@ public:
boost::asio::io_service ios;
test::string_ostream is{ios};
BEAST_EXPECT(handler::count() == 0);
message<true, string_body, fields> m;
request<string_body> m;
m.method(verb::get);
m.version = 11;
m.target("/");
@@ -708,7 +708,7 @@ public:
test::pipe p{ios_};
p.client.write_size(3);
message<false, Body, fields> m0;
response<Body> m0;
m0.version = 11;
m0.result(status::ok);
m0.reason("OK");

View File

@@ -10,6 +10,7 @@ add_executable (websocket-tests
../../extras/beast/unit_test/main.cpp
websocket_async_echo_server.hpp
websocket_sync_echo_server.hpp
doc_snippets.cpp
error.cpp
option.cpp
rfc6455.cpp

View File

@@ -0,0 +1,72 @@
//
// 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)
//
#include <beast/core.hpp>
#include <boost/asio.hpp>
#include <iostream>
#include <thread>
using namespace beast;
//[ws_snippet_1
#include <beast/websocket.hpp>
using namespace beast::websocket;
//]
namespace doc_ws_snippets {
void fxx() {
boost::asio::io_service ios;
boost::asio::io_service::work work{ios};
std::thread t{[&](){ ios.run(); }};
error_code ec;
boost::asio::ip::tcp::socket sock{ios};
{
//[ws_snippet_2
stream<boost::asio::ip::tcp::socket> ws{ios};
//]
}
{
//[ws_snippet_3
stream<boost::asio::ip::tcp::socket> ws{std::move(sock)};
//]
}
{
//[ws_snippet_4
stream<boost::asio::ip::tcp::socket&> ws{sock};
//]
//[ws_snippet_5
ws.next_layer().shutdown(boost::asio::ip::tcp::socket::shutdown_send);
//]
}
{
//[ws_snippet_6
std::string const host = "mywebapp.com";
boost::asio::ip::tcp::resolver r{ios};
stream<boost::asio::ip::tcp::socket> ws{ios};
boost::asio::connect(ws.next_layer(),
r.resolve(boost::asio::ip::tcp::resolver::query{host, "ws"}));
//]
}
{
//[ws_snippet_7
boost::asio::ip::tcp::acceptor acceptor{ios};
stream<boost::asio::ip::tcp::socket> ws{acceptor.get_io_service()};
acceptor.accept(ws.next_layer());
//]
}
} // fxx()
} // doc_ws_snippets

View File

@@ -11,6 +11,7 @@ add_executable (websocket-ssl-tests
${BEAST_INCLUDES}
${EXTRAS_INCLUDES}
../../../extras/beast/unit_test/main.cpp
doc_snippets.cpp
websocket_async_ssl_echo_server.hpp
ssl_server.cpp
)

View File

@@ -0,0 +1,58 @@
//
// 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)
//
#include <beast/core.hpp>
#include <beast/websocket.hpp>
#include <boost/asio.hpp>
#include <iostream>
#include <thread>
using namespace beast;
using namespace beast::websocket;
//[wss_snippet_1
#include <beast/websocket/ssl.hpp>
#include <boost/asio/ssl.hpp>
//]
namespace doc_wss_snippets {
void fxx() {
boost::asio::io_service ios;
boost::asio::io_service::work work{ios};
std::thread t{[&](){ ios.run(); }};
error_code ec;
boost::asio::ip::tcp::socket sock{ios};
{
//[wss_snippet_2
boost::asio::ssl::context ctx{boost::asio::ssl::context::sslv23};
stream<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> wss{ios, ctx};
//]
}
{
//[wss_snippet_3
boost::asio::ip::tcp::endpoint ep;
boost::asio::ssl::context ctx{boost::asio::ssl::context::sslv23};
stream<boost::asio::ssl::stream<boost::asio::ip::tcp::socket>> ws{ios, ctx};
// connect the underlying TCP/IP socket
ws.next_layer().next_layer().connect(ep);
// perform SSL handshake
ws.next_layer().handshake(boost::asio::ssl::stream_base::client);
// perform WebSocket handshake
ws.handshake("localhost", "/");
//]
}
} // fxx()
} // doc_wss_snippets