132 lines
5.2 KiB
Plaintext
132 lines
5.2 KiB
Plaintext
[/
|
|
Copyright (c) 2016-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)
|
|
|
|
Official repository: https://github.com/boostorg/beast
|
|
]
|
|
|
|
[section Handshaking (Servers)]
|
|
|
|
A
|
|
[link beast.ref.boost__beast__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
|
|
[@https://tools.ietf.org/html/rfc6455#section-4.2.2 ['101 Switching Protocols]]
|
|
status code. On failure, an error is returned or an exception is thrown.
|
|
Depending on the keep alive setting, the connection may remain 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:
|
|
|
|
[ws_snippet_11]
|
|
|
|
Successful WebSocket Upgrade responses generated by the implementation will
|
|
typically look like this:
|
|
|
|
[table Decorated WebSocket Upgrade HTTP Request
|
|
[[Serialized Octets][Description]]
|
|
[[
|
|
```
|
|
HTTP/1.1 101 Switching Protocols
|
|
Upgrade: websocket
|
|
Connection: upgrade
|
|
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
|
|
Server: Beast/40
|
|
```
|
|
][
|
|
The
|
|
[@https://tools.ietf.org/html/rfc6455#section-11.3.3 ['Sec-WebSocket-Accept]]
|
|
field value is generated from the request in a fashion specified by
|
|
the WebSocket protocol.
|
|
]]]
|
|
|
|
[heading Decorators]
|
|
|
|
If the caller wishes to add or modify fields, the member functions
|
|
[link beast.ref.boost__beast__websocket__stream.accept_ex `accept_ex`] and
|
|
[link beast.ref.boost__beast__websocket__stream.async_accept_ex `async_accept_ex`]
|
|
are provided which allow an additional function object, called a
|
|
['decorator], to be passed. The decorator is invoked to modify
|
|
the HTTP Upgrade request as needed. This example sets the Server
|
|
field on the response:
|
|
|
|
[ws_snippet_12]
|
|
|
|
The HTTP Upgrade response produced by the previous call looks like this:
|
|
|
|
[table Decorated WebSocket Upgrade HTTP Request
|
|
[[Serialized Octets][Description]]
|
|
[[
|
|
```
|
|
HTTP/1.1 101 Switching Protocols
|
|
Upgrade: websocket
|
|
Connection: upgrade
|
|
Sec-WebSocket-Accept: s3pPLMBiTxaQ9kYGzzhZRbK+xOo=
|
|
Server: AcmeServer
|
|
```
|
|
][
|
|
When the Upgrade request fails, the implementation will still invoke
|
|
the decorator to modify the response. In this case, the response
|
|
object will have a status code other than 101.
|
|
|
|
Undefined behavior results when the upgrade request is successful
|
|
and the decorator modifies the fields specific to perform the
|
|
WebSocket Upgrade, such as the Upgrade and Connection fields.
|
|
]]]
|
|
|
|
[heading Passing HTTP Requests]
|
|
|
|
When implementing an HTTP server that also supports WebSocket, the
|
|
server usually reads the HTTP request from the client. To detect when
|
|
the incoming HTTP request is a WebSocket Upgrade request, the function
|
|
[link beast.ref.boost__beast__websocket__is_upgrade `is_upgrade`] may be used.
|
|
|
|
Once the caller determines that the HTTP request is a WebSocket Upgrade,
|
|
additional overloads of
|
|
[link beast.ref.boost__beast__websocket__stream.accept `accept`],
|
|
[link beast.ref.boost__beast__websocket__stream.accept_ex `accept_ex`],
|
|
[link beast.ref.boost__beast__websocket__stream.async_accept `async_accept`], and
|
|
[link beast.ref.boost__beast__websocket__stream.async_accept_ex `async_accept_ex`]
|
|
are provided which receive the entire HTTP request header as an object
|
|
to perform the handshake. In this example, the request is first read
|
|
in using the HTTP algorithms, and then passed to a newly constructed
|
|
stream:
|
|
|
|
[ws_snippet_13]
|
|
|
|
[heading Buffered Handshakes]
|
|
|
|
Sometimes a server implementation wishes to read octets on the stream
|
|
in order to route the incoming request. For example, a server may read
|
|
the first 6 octets after accepting an incoming connection to determine
|
|
if a TLS protocol is being negotiated, and choose a suitable implementation
|
|
at run-time. In the case where the server wishes to accept the incoming
|
|
request as an HTTP WebSocket Upgrade request, additional overloads of
|
|
[link beast.ref.boost__beast__websocket__stream.accept `accept`],
|
|
[link beast.ref.boost__beast__websocket__stream.accept_ex `accept_ex`],
|
|
[link beast.ref.boost__beast__websocket__stream.async_accept `async_accept`], and
|
|
[link beast.ref.boost__beast__websocket__stream.async_accept_ex `async_accept_ex`]
|
|
are provided which receive the additional buffered octets and consume
|
|
them as part of the handshake.
|
|
|
|
In this example, the server reads the initial HTTP message into the
|
|
specified dynamic buffer as an octet sequence in the buffer's output
|
|
area, and later uses those octets to attempt an HTTP WebSocket Upgrade:
|
|
|
|
[ws_snippet_14]
|
|
|
|
The implementation uses a fixed-size storage area to hold buffers passed
|
|
using these functions. If an application is reaching the limit of the
|
|
internal buffer size, then the websocket stream may be instantiated with
|
|
the next layer type of
|
|
[link beast.ref.boost__beast__buffered_read_stream `buffered_read_stream`]
|
|
to wrap the underlying stream. The buffered handshake data may be first
|
|
placed into the buffered read stream, which uses a dynamically sized
|
|
buffer.
|
|
|
|
[endsect]
|