|
cwist
Modern C web framework with libttak runtime
|
WebSocket handshake and frame transport helpers for CWIST handlers. More...
#include <cwist/net/websocket/websocket.h>#include <cwist/net/http/http.h>#include <cwist/core/mem/alloc.h>#include <cwist/core/seq/seq.h>#include "ws_utils.h"#include <ctype.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <strings.h>#include <unistd.h>#include <arpa/inet.h>#include <errno.h>
Go to the source code of this file.
Macros | |
| #define | _GNU_SOURCE |
| #define | WS_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" |
| #define | CWIST_WS_MAX_PAYLOAD_BYTES ((uint64_t)(16u * 1024u * 1024u)) |
| #define | CWIST_WS_MAX_MESSAGE_BYTES ((size_t)(64u * 1024u * 1024u)) |
Functions | |
| bool | cwist_websocket_upgrade_response (cwist_http_request *req, cwist_http_response *res) |
| Validate the upgrade request and fill a 101 Switching Protocols response. | |
| cwist_websocket * | cwist_websocket_upgrade (cwist_http_request *req, int client_fd) |
| Upgrade an HTTP request to a WebSocket connection. | |
| cwist_ws_frame * | cwist_websocket_receive (cwist_websocket *ws) |
| Receive the next complete WebSocket message from a connected client. | |
| int | cwist_websocket_send (cwist_websocket *ws, cwist_ws_opcode_t opcode, const uint8_t *data, size_t len) |
| Send a single FIN-terminated WebSocket frame to the peer. | |
| void | cwist_websocket_frame_destroy (cwist_ws_frame *frame) |
| Release a frame and its owned payload buffer. | |
| int | cwist_websocket_send_sequenced (cwist_websocket *ws, const uint8_t *data, size_t len, uint16_t chunk_payload_size) |
| Send a large payload as sequenced binary frames. | |
| uint8_t * | cwist_websocket_receive_sequenced (cwist_websocket *ws, size_t *out_len) |
| Receive and reassemble a sequenced binary message. | |
| void | cwist_websocket_close (cwist_websocket *ws) |
| Initiate a close handshake for the WebSocket wrapper. | |
| void | cwist_websocket_destroy (cwist_websocket *ws) |
| Destroy the WebSocket wrapper without closing the underlying socket. | |
WebSocket handshake and frame transport helpers for CWIST handlers.
Definition in file websocket.c.
| #define _GNU_SOURCE |
Definition at line 2 of file websocket.c.
Definition at line 37 of file websocket.c.
Definition at line 31 of file websocket.c.
| #define WS_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" |
Definition at line 24 of file websocket.c.
| void cwist_websocket_close | ( | cwist_websocket * | ws | ) |
Initiate a close handshake for the WebSocket wrapper.
Close the WebSocket connection.
| ws | Connection to close. NULL is ignored. |
Definition at line 512 of file websocket.c.
References cap, cwist_websocket_send(), CWIST_WS_FRAME_CLOSE, and cwist_websocket::is_closed.
| void cwist_websocket_destroy | ( | cwist_websocket * | ws | ) |
Destroy the WebSocket wrapper without closing the underlying socket.
Destroy the WebSocket context.
| ws | Wrapper to release. NULL is ignored. |
Definition at line 523 of file websocket.c.
References cwist_free(), and cwist_websocket::frag_buf.
| void cwist_websocket_frame_destroy | ( | cwist_ws_frame * | frame | ) |
Release a frame and its owned payload buffer.
Destroy a frame.
| frame | Frame object to destroy. NULL is ignored. |
Definition at line 436 of file websocket.c.
References cap, and cwist_free().
Referenced by cwist_websocket_receive_sequenced().
| cwist_ws_frame * cwist_websocket_receive | ( | cwist_websocket * | ws | ) |
Receive the next complete WebSocket message from a connected client.
Receive a frame. Blocks until a frame is received or connection closed.
Receive a frame, blocking until data arrives or the socket closes.
Transparently reassembles fragmented messages (RFC 6455 section 5.4): frames with FIN=0 are buffered internally and the function blocks until the final FIN=1 frame arrives, at which point the fully-assembled payload is returned as a single frame. Control frames (CLOSE, PING, PONG) are always FIN=1 and are delivered immediately even when a fragmented data message is in progress.
Client frames are required to be masked by RFC 6455, so unmasked payloads are rejected. The returned payload is null-terminated for convenience.
| ws | WebSocket connection wrapper returned by cwist_websocket_upgrade(). |
Definition at line 217 of file websocket.c.
References cap, cwist_alloc(), cwist_free(), cwist_websocket_send(), CWIST_WS_FRAME_CLOSE, CWIST_WS_FRAME_CONTINUATION, CWIST_WS_FRAME_PING, CWIST_WS_FRAME_PONG, CWIST_WS_MAX_PAYLOAD_BYTES, cwist_websocket::fd, cwist_websocket::frag_buf, cwist_websocket::frag_cap, cwist_websocket::frag_len, cwist_websocket::frag_opcode, head, and cwist_websocket::is_closed.
Referenced by cwist_websocket_receive_sequenced().
| uint8_t * cwist_websocket_receive_sequenced | ( | cwist_websocket * | ws, |
| size_t * | out_len | ||
| ) |
Receive and reassemble a sequenced binary message.
Reads binary frames until every chunk of one sequenced message has arrived, discarding duplicates and reordering out-of-order chunks. The returned buffer is heap-allocated and must be freed with cwist_free().
| ws | WebSocket connection. |
| out_len | Receives the length of the reassembled payload. |
Definition at line 468 of file websocket.c.
References cap, cwist_alloc(), cwist_seq_assembler_create(), cwist_seq_assembler_destroy(), cwist_seq_assembler_feed(), cwist_seq_assembler_get_data(), cwist_seq_assembler_is_complete(), cwist_seq_chunk_parse(), cwist_websocket_frame_destroy(), cwist_websocket_receive(), CWIST_WS_FRAME_BINARY, CWIST_WS_FRAME_CLOSE, and cwist_websocket::is_closed.
| int cwist_websocket_send | ( | cwist_websocket * | ws, |
| cwist_ws_opcode_t | opcode, | ||
| const uint8_t * | data, | ||
| size_t | len | ||
| ) |
Send a single FIN-terminated WebSocket frame to the peer.
Send a frame.
Send a frame with the specified opcode and payload.
| ws | Active WebSocket connection wrapper. |
| opcode | WebSocket opcode describing the payload semantics. |
| data | Optional payload buffer. May be NULL when len is zero. |
| len | Number of payload bytes to transmit. |
Definition at line 398 of file websocket.c.
References cap, cwist_websocket::fd, head, and cwist_websocket::is_closed.
Referenced by cwist_websocket_close(), cwist_websocket_receive(), and cwist_websocket_send_sequenced().
| int cwist_websocket_send_sequenced | ( | cwist_websocket * | ws, |
| const uint8_t * | data, | ||
| size_t | len, | ||
| uint16_t | chunk_payload_size | ||
| ) |
Send a large payload as sequenced binary frames.
Splits data into chunks of chunk_payload_size (or smaller for the final chunk), prefixes each chunk with the CWIST sequence header, and sends every chunk as an independent binary frame. The peer can reassemble the original payload even when frames arrive out of order.
| ws | WebSocket connection. |
| data | Payload bytes. |
| len | Payload length. |
| chunk_payload_size | Maximum payload bytes per chunk (must be > 0). |
Definition at line 446 of file websocket.c.
References cap, cwist_seq_message_free(), cwist_seq_split(), cwist_websocket_send(), CWIST_WS_FRAME_BINARY, and cwist_websocket::is_closed.
| cwist_websocket * cwist_websocket_upgrade | ( | cwist_http_request * | req, |
| int | client_fd | ||
| ) |
Upgrade an HTTP request to a WebSocket connection.
Upgrade an HTTP request to WebSocket.
Upgrade a standard HTTP request to a WebSocket connection.
The function validates the required upgrade headers, computes the Sec-WebSocket-Accept response, emits the 101 Switching Protocols reply, and returns a lightweight wrapper around the already-open client socket.
| req | Parsed HTTP request that requested the upgrade. |
| client_fd | Accepted client socket descriptor. |
Definition at line 119 of file websocket.c.
References cap, cwist_alloc(), cwist_http_response_create(), cwist_http_response_destroy(), cwist_http_send_response(), cwist_websocket_upgrade_response(), CWIST_WS_FRAME_CONTINUATION, cwist_websocket::fd, cwist_websocket::frag_buf, cwist_websocket::frag_cap, cwist_websocket::frag_len, cwist_websocket::frag_opcode, cwist_websocket::is_closed, and cwist_http_request::upgraded.
| bool cwist_websocket_upgrade_response | ( | cwist_http_request * | req, |
| cwist_http_response * | res | ||
| ) |
Validate the upgrade request and fill a 101 Switching Protocols response.
Computes the Sec-WebSocket-Accept key (sha1 + base64), sets status 101 and the Upgrade/Connection/Sec-WebSocket-Accept headers on res, but does NOT send anything. Shared by the blocking cwist_websocket_upgrade() and the C1M reactor path, which sends the 101 through the coalesced HTTP writer.
| req | Parsed upgrade request to validate. |
| res | Response object to fill (must be empty). |
res carries the 101 reply. Definition at line 71 of file websocket.c.
References base64_encode(), cap, cwist_free(), cwist_http_header_add(), cwist_http_header_get(), cwist_sstring_assign(), cwist_http_request::headers, cwist_http_response::headers, sha1(), cwist_http_response::status_code, cwist_http_response::status_text, and WS_GUID.
Referenced by cwist_websocket_upgrade().