[/ 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:control Control Frames] Control frames are small (less than 128 bytes) messages entirely contained in an individual WebSocket frame. They may be sent at any time by either peer on an established connection, and can appear in between continuation frames for a message. There are three types of control frames: ping, pong, and close. A sent ping indicates a request that the sender wants to receive a pong. A pong is a response to a ping. Pongs may be sent unsolicited, at any time. One use for an unsolicited pong is to inform the remote peer that the session is still active after a long period of inactivity. A close frame indicates that the remote peer wishes to close the WebSocket connection. The connection is considered gracefully closed when each side has sent and received a close frame. During read operations, Beast automatically reads and processes control frames. Pings are replied to as soon as possible with a pong, received ping and pongs are delivered to the ping callback. The receipt of a close frame initiates the WebSocket close procedure, eventually resulting in the error code [link beast.ref.websocket__error `error::closed`] being delivered to the caller in a subsequent read operation, assuming no other error takes place. A consequence of this automatic behavior is that caller-initiated read operations can cause socket writes. However, these writes will not compete with caller-initiated write operations. For the purposes of correctness with respect to the stream invariants, caller-initiated read operations still only count as a read. This means that callers can have a simultaneously active read, write, and ping operation in progress, while the implementation also automatically handles control frames. [heading Ping and Pong Frames] Ping and pong messages are control frames which may be sent at any time by either peer on an established WebSocket connection. They are sent using the functions [link beast.ref.websocket__stream.ping `ping`] and [link beast.ref.websocket__stream.pong `pong`]. To be notified of ping and pong control frames, callers may register a "ping callback" using [link beast.ref.websocket__stream.set_option `set_option`]. The object provided with this option should be callable with the following signature: ``` void on_ping(bool is_pong, websocket::ping_data const& payload); ... ws.set_option(ping_callback{&on_ping}); ``` When a ping callback is registered, all pings and pongs received through either synchronous read functions or asynchronous read functions will invoke the ping callback, with the value of `is_pong` set to `true` if a pong was received or `false` otherwise. The payload of the ping or pong control frame is passed in the payload argument. Unlike regular completion handlers used in calls to asynchronous initiation functions, the ping callback only needs to be set once. The callback is not reset when a ping or pong is received. The same callback is used for both synchronous and asynchronous reads. The ping callback is passive; in order to receive pings and pongs, a synchronous or asynchronous stream read function must be active. [note When an asynchronous read function receives a ping or pong, the ping callback is invoked in the same manner as that used to invoke the final completion handler of the corresponding read function. ] [heading Close Frames] The WebSocket protocol defines a procedure and control message for initiating a close of the session. Handling of close initiated by the remote end of the connection is performed automatically. To manually initiate a close, use the [link beast.ref.websocket__stream.close `close`] function: ``` ws.close(); ``` When the remote peer initiates a close by sending a close frame, Beast will handle it for you by causing the next read to return `error::closed`. When this error code is delivered, it indicates to the application that the WebSocket connection has been closed cleanly, and that the TCP/IP connection has been closed. After initiating a close, it is necessary to continue reading messages until receiving the error `error::closed`. This is because the remote peer may still be sending message and control frames before it receives and responds to the close frame. [important To receive the [link beast.ref.websocket__error `error::closed`] error, a read operation is required. ] [heading Auto-fragment] To ensure timely delivery of control frames, large messages can be broken up into smaller sized frames. The automatic fragment option turns on this feature, and the write buffer size option determines the maximum size of the fragments: ``` ... ws.set_option(websocket::auto_fragment{true}); ws.set_option(websocket::write_buffer_size{16384}); ``` [endsect]