forked from boostorg/beast
These classes are renamed: * streambuf to multi_buffer * basic_streambuf to basic_multi_buffer
655 lines
28 KiB
Plaintext
655 lines
28 KiB
Plaintext
[/
|
|
Copyright (c) 2013-2017 Vinnie Falco (vinnie dot falco at gmail dot com)
|
|
|
|
Distributed under the Boost Software License, Version 1.0. (See accompanying
|
|
file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
|
|
]
|
|
|
|
[section:design Design Choices]
|
|
|
|
[block '''
|
|
<informaltable frame="all"><tgroup cols="1"><colspec colname="a"/><tbody><row><entry valign="top"><simplelist>
|
|
<member><link linkend="beast.design.http">HTTP FAQ</link></member>
|
|
<member><link linkend="beast.design.websocket">WebSocket FAQ</link></member>
|
|
<member><link linkend="beast.design.websocketpp">Comparison to Zaphoyd Studios WebSocket++</link></member>
|
|
</simplelist></entry></row></tbody></tgroup></informaltable>
|
|
''']
|
|
|
|
The implementations are driven by business needs of cryptocurrency server
|
|
applications (e.g. [@https://ripple.com Ripple]) written in C++. These
|
|
needs were not met by existing solutions so Beast was written from scratch
|
|
as a solution. Beast's design philosophy avoids flaws exhibited by other
|
|
libraries:
|
|
|
|
* Don't try to do too much.
|
|
|
|
* Don't sacrifice performance.
|
|
|
|
* Mimic Boost.Asio; familiarity breeds confidence.
|
|
|
|
* Role-symmetric interfaces; client and server the same (or close to it).
|
|
|
|
* Leave important decisions to the user, such as allocating memory or
|
|
managing flow control.
|
|
|
|
Beast uses the __DynamicBuffer__ concept presented in the Networking TS
|
|
(__N4588__), 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 sequence interfaces to
|
|
be optimal for interacting with Asio, and for other tasks such as incremental
|
|
parsing of data in buffers (for example, parsing websocket frames stored
|
|
in a [link beast.ref.static_streambuf `static_streambuf`]).
|
|
|
|
During the development of Beast the authors have studied other software
|
|
packages and in particular the comments left during the Boost Review process
|
|
of other packages offering similar functionality. In this section and the
|
|
FAQs that follow we attempt to answer those questions that are also applicable
|
|
to Beast.
|
|
|
|
[variablelist
|
|
[[
|
|
"I would also like to see instances of this library being used
|
|
in production. That would give some evidence that the design
|
|
works in practice."
|
|
][
|
|
Beast.HTTP and Beast.WebSocket are production ready and currently
|
|
running on public servers receiving traffic and handling millions of
|
|
dollars worth of financial transactions daily. The servers run [*rippled],
|
|
open source software ([@https://github.com/ripple/rippled repository])
|
|
implementing the
|
|
[@https://ripple.com/files/ripple_consensus_whitepaper.pdf [*Ripple Consensus Protocol]],
|
|
technology provided by [@http://ripple.com Ripple].
|
|
]]
|
|
|
|
]
|
|
|
|
|
|
|
|
[section:http HTTP FAQ]
|
|
|
|
For HTTP we model the message to maximize flexibility of implementation
|
|
strategies while allowing familiar verbs such as [*`read`] and [*`write`].
|
|
The HTTP interface is further driven by the needs of the WebSocket module,
|
|
as a WebSocket session requires a HTTP Upgrade handshake exchange at the
|
|
start. Other design goals:
|
|
|
|
* Keep it simple.
|
|
|
|
* Stay low level; don't invent a whole web server or client.
|
|
|
|
* Allow for customizations, if the user needs it.
|
|
|
|
[variablelist
|
|
|
|
[[
|
|
"Some more advanced examples, e.g. including TLS with client/server
|
|
certificates would help."
|
|
][
|
|
The HTTP interface doesn't try to reinvent the wheel, it just uses
|
|
the `boost::asio::ip::tcp::socket` or `boost::asio::ssl::stream` that
|
|
you set up beforehand. Callers use the interfaces already existing
|
|
on those objects to make outgoing connections, accept incoming connections,
|
|
or establish TLS sessions with certificates. We find the available Asio
|
|
examples for performing these tasks sufficient.
|
|
]]
|
|
|
|
[[
|
|
"A built-in router?"
|
|
][
|
|
We presume this means a facility to match expressions against the URI
|
|
in HTTP requests, and dispatch them to calling code. The authors feel
|
|
that this is a responsibility of higher level code. Beast.HTTP does
|
|
not try to offer a web server.
|
|
]]
|
|
|
|
[[
|
|
"Cookies? Forms/File Uploads?"
|
|
][
|
|
Cookies, or managing these types of HTTP headers in general, is the
|
|
responsibility of higher levels. Beast.HTTP just tries to get complete
|
|
messages to and from the calling code. It deals in the HTTP headers just
|
|
enough to process the message body and leaves the rest to callers. However,
|
|
for forms and file uploads the symmetric interface of the message class
|
|
allows HTTP requests to include arbitrary body types including those needed
|
|
to upload a file or fill out a form.
|
|
]]
|
|
|
|
[[
|
|
"...supporting TLS (is this a feature? If not this would be a show-stopper),
|
|
etc."
|
|
][
|
|
Beast.HTTP does not provide direct facilities for implementing TLS
|
|
connections; however, the interfaces already existing on the
|
|
`boost::asio::ssl::stream` are available and can be used to establish
|
|
secure connections. Then, functions like `http::read` or `http::async_write`
|
|
can work with those encrypted connections with no problem.
|
|
]]
|
|
|
|
[[
|
|
"There should also be more examples of how to integrate the http service
|
|
with getting files from the file system, generating responses CGI-style"
|
|
][
|
|
The design goal for the library is to not try to invent a web server.
|
|
We feel that there is a strong need for a basic implementation that
|
|
models the HTTP message and provides functions to send and receive them
|
|
over Asio. Such an implementation should serve as a building block upon
|
|
which higher abstractions such as the aforementioned HTTP service or
|
|
cgi-gateway can be built.
|
|
|
|
One of the example programs implements a simple HTTP server that
|
|
delivers files from the filesystem.
|
|
]]
|
|
|
|
[[
|
|
"You should send a 100-continue to ask for the rest of the body if required."
|
|
][
|
|
The Beast interface needs to support this functionality (by allowing this
|
|
special case of partial message parsing and serialization). Specifically,
|
|
it should let callers read the request up to just before the body,
|
|
and let callers write the request up to just before the body. However,
|
|
making use of this behavior should be up to callers (since Beast is low
|
|
level).
|
|
]]
|
|
|
|
[[
|
|
"What about HTTP/2?"
|
|
][
|
|
Many reviewers feel that HTTP/2 support is an essential feature of
|
|
a HTTP library. The authors agree that HTTP/2 is important but also
|
|
feel that the most sensible implementation is one that does not re-use
|
|
the same network reading and writing interface for 2 as that for 1.0
|
|
and 1.1.
|
|
|
|
The Beast.HTTP message model is suitable for HTTP/2 and can be re-used.
|
|
The IETF HTTP Working Group adopted message compatiblity with HTTP/1.x
|
|
as an explicit goal. A parser can simply emit full headers after
|
|
decoding the compressed HTTP/2 headers. The stream ID is not logically
|
|
part of the message but rather message metadata and should be
|
|
communicated out-of-band (see below). HTTP/2 sessions begin with a
|
|
traditional HTTP/1.1 Upgrade similar in fashion to the WebSocket
|
|
upgrade. An HTTP/2 implementation can use existing Beast.HTTP primitives
|
|
to perform this handshake.
|
|
|
|
Free functions for HTTP/2 sessions are not possible because of the
|
|
requirement to maintain per-session state. For example, to decode the
|
|
compressed headers. Or to remember and respect the remote peer's window
|
|
settings. The authors propose that a HTTP/2 implementation be written
|
|
as a separate class template, similar to the `websocket::stream` but with
|
|
additional interfaces to support version 2 features. We feel that
|
|
Beast.HTTP offers enough useful functionality to justify inclusion,
|
|
so that developers can take advantage of it right away instead of
|
|
waiting.
|
|
]]
|
|
|
|
]
|
|
|
|
[endsect]
|
|
|
|
|
|
|
|
[section:websocket WebSocket FAQ]
|
|
|
|
[variablelist
|
|
|
|
[[
|
|
What about message compression?
|
|
][
|
|
Beast WebSocket supports the permessage-deflate extension described in
|
|
[@https://tools.ietf.org/html/draft-ietf-hybi-permessage-compression-00 draft-ietf-hybi-permessage-compression-00].
|
|
The library comes with a header-only, C++11 port of ZLib's "deflate" codec
|
|
used in the implementation of the permessage-deflate extension.
|
|
]]
|
|
|
|
[[
|
|
Where is the TLS/SSL interface?
|
|
][
|
|
The `websocket::stream` wraps the socket or stream that you provide
|
|
(for example, a `boost::asio::ip::tcp::socket` or a
|
|
`boost::asio::ssl::stream`). You establish your TLS connection using the
|
|
interface on `ssl::stream` like shown in all of the Asio examples, then
|
|
construct your `websocket::stream` around it. It works perfectly fine;
|
|
Beast.WebSocket doesn't try to reinvent the wheel or put a fresh coat of
|
|
interface paint on the `ssl::stream`.
|
|
|
|
The WebSocket implementation [*does] provide support for shutting down
|
|
the TLS connection through the use of the ADL compile-time virtual functions
|
|
[link beast.ref.websocket__teardown `teardown`] and
|
|
[link beast.ref.websocket__async_teardown `async_teardown`]. These will
|
|
properly close the connection as per rfc6455 and overloads are available
|
|
for TLS streams. Callers may provide their own overloads of these functions
|
|
for user-defined next layer types.
|
|
]]
|
|
|
|
]
|
|
|
|
[endsect]
|
|
|
|
|
|
|
|
[section:websocketpp Comparison to Zaphoyd Studios WebSocket++]
|
|
|
|
[variablelist
|
|
|
|
[[
|
|
How does this compare to [@https://www.zaphoyd.com/websocketpp websocketpp],
|
|
an alternate header-only WebSocket implementation?
|
|
][
|
|
[variablelist
|
|
|
|
[[1. Synchronous Interface][
|
|
|
|
Beast offers full support for WebSockets using a synchronous interface. It
|
|
uses the same style of interfaces found in Boost.Asio: versions that throw
|
|
exceptions, or versions that return the error code in a reference parameter:
|
|
|
|
[table
|
|
[
|
|
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L774 Beast]]
|
|
[websocketpp]
|
|
][
|
|
[```
|
|
template<class DynamicBuffer>
|
|
void
|
|
read(opcode& op, DynamicBuffer& dynabuf)
|
|
```]
|
|
[
|
|
/<not available>/
|
|
]
|
|
]]]]
|
|
|
|
[[2. Connection Model][
|
|
|
|
websocketpp supports multiple transports by utilizing a trait, the `config::transport_type`
|
|
([@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/asio/connection.hpp#L60 asio transport example])
|
|
To get an idea of the complexity involved with implementing a transport,
|
|
compare the asio transport to the
|
|
[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/iostream/connection.hpp#L59 `iostream` transport]
|
|
(a layer that allows websocket communication over a `std::iostream`).
|
|
|
|
In contrast, Beast abstracts the transport by defining just one [*`NextLayer`]
|
|
template argument The type requirements for [*`NextLayer`] are
|
|
already familiar to users as they are documented in Asio:
|
|
__AsyncReadStream__, __AsyncWriteStream__, __SyncReadStream__, __SyncWriteStream__.
|
|
|
|
The type requirements for instantiating `beast::websocket::stream` versus
|
|
`websocketpp::connection` with user defined types are vastly reduced
|
|
(18 functions versus 2). Note that websocketpp connections are passed by
|
|
`shared_ptr`. Beast does not use `shared_ptr` anywhere in its public interface.
|
|
A `beast::websocket::stream` is constructible and movable in a manner identical
|
|
to a `boost::asio::ip::tcp::socket`. Callers can put such objects in a
|
|
`shared_ptr` if they want to, but there is no requirement to do so.
|
|
|
|
[table
|
|
[
|
|
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp Beast]]
|
|
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L234 websocketpp]]
|
|
][
|
|
[```
|
|
template<class NextLayer>
|
|
class stream
|
|
{
|
|
NextLayer next_layer_;
|
|
...
|
|
}
|
|
```]
|
|
[```
|
|
template <typename config>
|
|
class connection
|
|
: public config::transport_type::transport_con_type
|
|
, public config::connection_base
|
|
{
|
|
public:
|
|
typedef lib::shared_ptr<type> ptr;
|
|
...
|
|
}
|
|
```]
|
|
]]]]
|
|
|
|
[[3. Client and Server Role][
|
|
|
|
websocketpp provides multi-role support through a hierarchy of
|
|
different classes. A `beast::websocket::stream` is role-agnostic, it
|
|
offers member functions to perform both client and server handshakes
|
|
in the same class. The same types are used for client and server
|
|
streams.
|
|
|
|
[table
|
|
[
|
|
[Beast]
|
|
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/roles/server_endpoint.hpp#L39 websocketpp],
|
|
[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/roles/client_endpoint.hpp#L42 also]]
|
|
][
|
|
[
|
|
/<not needed>/
|
|
]
|
|
[```
|
|
template <typename config>
|
|
class client : public endpoint<connection<config>,config>;
|
|
template <typename config>
|
|
class server : public endpoint<connection<config>,config>;
|
|
```]
|
|
]]]]
|
|
|
|
[[4. Thread Safety][
|
|
|
|
websocketpp uses mutexes to protect shared data from concurrent
|
|
access. In contrast, Beast does not use mutexes anywhere in its
|
|
implementation. Instead, it follows the Asio pattern. Calls to
|
|
asynchronous initiation functions use the same method to invoke
|
|
intermediate handlers as the method used to invoke the final handler,
|
|
through the __asio_handler_invoke__ mechanism.
|
|
|
|
The only requirement in Beast is that calls to asynchronous initiation
|
|
functions are made from the same implicit or explicit strand. For
|
|
example, if the `io_service` associated with a `beast::websocket::stream`
|
|
is single threaded, this counts as an implicit strand and no performance
|
|
costs associated with mutexes are incurred.
|
|
|
|
[table
|
|
[
|
|
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/impl/read_frame_op.ipp#L118 Beast]]
|
|
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/iostream/connection.hpp#L706 websocketpp]]
|
|
][
|
|
[```
|
|
template <class Function>
|
|
friend
|
|
void asio_handler_invoke(Function&& f, read_frame_op* op)
|
|
{
|
|
return boost_asio_handler_invoke_helpers::invoke(f, op->d_->h);
|
|
}
|
|
```]
|
|
[```
|
|
mutex_type m_read_mutex;
|
|
```]
|
|
]]]]
|
|
|
|
[[5. Callback Model][
|
|
|
|
websocketpp requires a one-time call to set the handler for each event
|
|
in its interface (for example, upon message receipt). The handler is
|
|
represented by a `std::function` equivalent. Its important to recognize
|
|
that the websocketpp interface performs type-erasure on this handler.
|
|
|
|
In comparison, Beast handlers are specified in a manner identical to
|
|
Boost.Asio. They are function objects which can be copied or moved but
|
|
most importantly they are not type erased. The compiler can see
|
|
through the type directly to the implementation, permitting
|
|
optimization. Furthermore, Beast follows the Asio rules for treatment
|
|
of handlers. It respects any allocation, continuation, or invocation
|
|
customizations associated with the handler through the use of argument
|
|
dependent lookup overloads of functions such as `asio_handler_allocate`.
|
|
|
|
The Beast completion handler is provided at the call site. For each
|
|
call to an asynchronous initiation function, it is guaranteed that
|
|
there will be exactly one final call to the handler. This functions
|
|
exactly the same way as the asynchronous initiation functions found in
|
|
Boost.Asio, allowing the composition of higher level abstractions.
|
|
|
|
[table
|
|
[
|
|
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L834 Beast]]
|
|
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L281 websocketpp],
|
|
[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L473 also]]
|
|
][
|
|
[```
|
|
template<class DynamicBuffer, class ReadHandler>
|
|
typename async_completion<ReadHandler, void(error_code)>::result_type
|
|
async_read(opcode& op, DynamicBuffer& dynabuf, ReadHandler&& handler);
|
|
```]
|
|
[```
|
|
typedef lib::function<void(connection_hdl,message_ptr)> message_handler;
|
|
void set_message_handler(message_handler h);
|
|
```]
|
|
]]]]
|
|
|
|
[[6. Extensible Asynchronous Model][
|
|
|
|
Beast fully supports the
|
|
[@http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n3896.pdf Extensible Asynchronous Model]
|
|
developed by Christopher Kohlhoff, author of Boost.Asio (see Section 8).
|
|
|
|
Beast websocket asynchronous interfaces may be used seamlessly with
|
|
`std::future` stackful/stackless coroutines, or user defined customizations.
|
|
|
|
[table
|
|
[
|
|
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/impl/stream.ipp#L378 Beast]]
|
|
[websocketpp]
|
|
][
|
|
[```
|
|
beast::async_completion<ReadHandler, void(error_code)> completion(handler);
|
|
read_op<DynamicBuffer, decltype(completion.handler)>{
|
|
completion.handler, *this, op, buffer};
|
|
return completion.result.get();
|
|
```]
|
|
[
|
|
/<not available>/
|
|
]
|
|
]]]]
|
|
|
|
[[7. Message Buffering][
|
|
|
|
websocketpp defines a message buffer, passed in arguments by
|
|
`shared_ptr`, and an associated message manager which permits
|
|
aggregation and reuse of memory. The implementation of
|
|
`websocketpp::message` uses a `std::string` to hold the payload. If an
|
|
incoming message is broken up into multiple frames, the string may be
|
|
reallocated for each continuation frame. The `std::string` always uses
|
|
the standard allocator, it is not possible to customize the choice of
|
|
allocator.
|
|
|
|
Beast allows callers to specify the object for receiving the message
|
|
or frame data, which is of any type meeting the requirements of
|
|
__DynamicBuffer__ (modeled after `boost::asio::streambuf`).
|
|
|
|
Beast comes with the class __basic_multi_buffer__, an efficient
|
|
implementation of the __DynamicBuffer__ concept which makes use of multiple
|
|
allocated octet arrays. If an incoming message is broken up into
|
|
multiple pieces, no reallocation occurs. Instead, new allocations are
|
|
appended to the sequence when existing allocations are filled. Beast
|
|
does not impose any particular memory management model on callers. The
|
|
__basic_multi_buffer__ provided by beast supports standard allocators through
|
|
a template argument. Use the __DynamicBuffer__ that comes with beast,
|
|
customize the allocator if you desire, or provide your own type that
|
|
meets the requirements.
|
|
|
|
[table
|
|
[
|
|
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L774 Beast]]
|
|
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/message_buffer/message.hpp#L78 websocketpp]]
|
|
][
|
|
[```
|
|
template<class DynamicBuffer>
|
|
read(opcode& op, DynamicBuffer& dynabuf);
|
|
```]
|
|
[```
|
|
template <template<class> class con_msg_manager>
|
|
class message {
|
|
public:
|
|
typedef lib::shared_ptr<message> ptr;
|
|
...
|
|
std::string m_payload;
|
|
...
|
|
};
|
|
```]
|
|
]]]]
|
|
|
|
[[8. Sending Messages][
|
|
|
|
When sending a message, websocketpp requires that the payload is
|
|
packaged in a `websocketpp::message` object using `std::string` as the
|
|
storage, or it requires a copy of the caller provided buffer by
|
|
constructing a new message object. Messages are placed onto an
|
|
outgoing queue. An asynchronous write operation runs in the background
|
|
to clear the queue. No user facing handler can be registered to be
|
|
notified when messages or frames have completed sending.
|
|
|
|
Beast doesn't allocate or make copies of buffers when sending data. The
|
|
caller's buffers are sent in-place. You can use any object meeting the
|
|
requirements of
|
|
[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/ConstBufferSequence.html ConstBufferSequence],
|
|
permitting efficient scatter-gather I/O.
|
|
|
|
The [*ConstBufferSequence] interface allows callers to send data from
|
|
memory-mapped regions (not possible in websocketpp). Callers can also
|
|
use the same buffers to send data to multiple streams, for example
|
|
broadcasting common subscription data to many clients at once. For
|
|
each call to `async_write` the completion handler is called once when
|
|
the data finishes sending, in a manner identical to `boost::asio::async_write`.
|
|
|
|
[table
|
|
[
|
|
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L1048 Beast]]
|
|
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L672 websocketpp]]
|
|
][
|
|
[```
|
|
template<class ConstBufferSequence>
|
|
void
|
|
write(ConstBufferSequence const& buffers);
|
|
```]
|
|
[```
|
|
lib::error_code send(std::string const & payload,
|
|
frame::opcode::value op = frame::opcode::text);
|
|
...
|
|
lib::error_code send(message_ptr msg);
|
|
```]
|
|
]]]]
|
|
|
|
[[9. Streaming Messages][
|
|
|
|
websocketpp requires that the entire message fit into memory, and that
|
|
the size is known ahead of time.
|
|
|
|
Beast allows callers to compose messages in individual frames. This is
|
|
useful when the size of the data is not known ahead of time or if it
|
|
is not desired to buffer the entire message in memory at once before
|
|
sending it. For example, sending periodic output of a database query
|
|
running on a coroutine. Or sending the contents of a file in pieces,
|
|
without bringing it all into memory.
|
|
|
|
[table
|
|
[
|
|
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L1151 Beast]]
|
|
[websocketpp]
|
|
][
|
|
[```
|
|
template<class ConstBufferSequence>
|
|
void
|
|
write_frame(bool fin,
|
|
ConstBufferSequence const& buffers);
|
|
```]
|
|
[
|
|
/<not available>/
|
|
]
|
|
]]]]
|
|
|
|
[[10. Flow Control][
|
|
|
|
The websocketpp read implementation continuously reads asynchronously
|
|
from the network and buffers message data. To prevent unbounded growth
|
|
and leverage TCP/IP's flow control mechanism, callers can periodically
|
|
turn this 'read pump' off and back on.
|
|
|
|
In contrast a `beast::websocket::stream` does not independently begin
|
|
background activity, nor does it buffer messages. It receives data only
|
|
when there is a call to an asynchronous initiation function (for
|
|
example `beast::websocket::stream::async_read`) with an associated handler.
|
|
Applications do not need to implement explicit logic to regulate the
|
|
flow of data. Instead, they follow the traditional model of issuing a
|
|
read, receiving a read completion, processing the message, then
|
|
issuing a new read and repeating the process.
|
|
|
|
[table
|
|
[
|
|
[Beast]
|
|
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/connection.hpp#L728 websocketpp]]
|
|
][
|
|
[
|
|
/<implicit>/
|
|
]
|
|
[```
|
|
lib::error_code pause_reading();
|
|
lib::error_code resume_reading();
|
|
```]
|
|
]]]]
|
|
|
|
[[11. Connection Establishment][
|
|
|
|
websocketpp offers the `endpoint` class which can handle binding and
|
|
listening to a port, and spawning connection objects.
|
|
|
|
Beast does not reinvent the wheel here, callers use the interfaces
|
|
already in `boost::asio` for receiving incoming connections resolving
|
|
host names, or establishing outgoing connections. After the socket (or
|
|
`boost::asio::ssl::stream`) is connected, the `beast::websocket::stream`
|
|
is constructed around it and the WebSocket handshake can be performed.
|
|
|
|
Beast users are free to implement their own "connection manager", but
|
|
there is no requirement to do so.
|
|
|
|
[table
|
|
[
|
|
[[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/async_connect.html Beast],
|
|
[@http://www.boost.org/doc/libs/1_60_0/doc/html/boost_asio/reference/basic_socket_acceptor/async_accept.html also]]
|
|
[[@https://github.com/zaphoyd/websocketpp/blob/378437aecdcb1dfe62096ffd5d944bf1f640ccc3/websocketpp/transport/asio/endpoint.hpp#L52 websocketpp]]
|
|
][
|
|
[```
|
|
#include <boost/asio.hpp>
|
|
```]
|
|
[```
|
|
template <typename config>
|
|
class endpoint : public config::socket_type;
|
|
```]
|
|
]]]]
|
|
|
|
[[12. WebSocket Handshaking][
|
|
|
|
Callers invoke `beast::websocket::accept` to perform the WebSocket
|
|
handshake, but there is no requirement to use this function. Advanced
|
|
users can perform the WebSocket handshake themselves. Beast WebSocket
|
|
provides the tools for composing the request or response, and the
|
|
Beast HTTP interface provides the container and algorithms for sending
|
|
and receiving HTTP/1 messages including the necessary HTTP Upgrade
|
|
request for establishing the WebSocket session.
|
|
|
|
Beast allows the caller to pass the incoming HTTP Upgrade request for
|
|
the cases where the caller has already received an HTTP message.
|
|
This flexibility permits novel and robust implementations. For example,
|
|
a listening socket that can handshake in multiple protocols on the
|
|
same port.
|
|
|
|
Sometimes callers want to read some bytes on the socket before reading
|
|
the WebSocket HTTP Upgrade request. Beast allows these already-received
|
|
bytes to be supplied to an overload of the accepting function to permit
|
|
sophisticated features. For example, a listening socket that can
|
|
accept both regular WebSocket and Secure WebSocket (SSL) connections.
|
|
|
|
[table
|
|
[
|
|
[[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L501 Beast],
|
|
[@https://github.com/vinniefalco/Beast/blob/6c8b4b2f8dde72b01507e4ac7fde4ffea57ebc99/include/beast/websocket/stream.hpp#L401 also]]
|
|
[websocketpp]
|
|
][
|
|
[```
|
|
template<class ConstBufferSequence>
|
|
void
|
|
accept(ConstBufferSequence const& buffers);
|
|
|
|
template<class Body, class Headers>
|
|
void
|
|
accept(http::request_v1<Body, Headers> const& request);
|
|
```]
|
|
[
|
|
/<not available>/
|
|
]
|
|
]]]]
|
|
|
|
]
|
|
]]
|
|
|
|
]
|
|
|
|
[endsect]
|
|
|
|
[endsect]
|