|
Csilk 0.2.1
A lightweight, high-performance C HTTP web framework
|
WebSocket handshake, frame encoding, and frame parsing implementation. More...
#include <stdint.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <uv.h>#include "csilk/core/internal.h"#include "csilk/csilk.h"#include "../core/context_internal.h"
Macros | |
| #define | WS_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" |
| WebSocket magic GUID string per RFC 6455 Section 4.2.2. | |
Functions | |
| void | csilk_ws_handshake (csilk_ctx_t *c) |
| Perform the WebSocket upgrade handshake per RFC 6455. | |
| static void | on_ws_write (uv_write_t *req, int status) |
| libuv write completion callback for WebSocket frame sends. | |
| void | csilk_ws_send (csilk_ctx_t *c, const uint8_t *payload, size_t len, int opcode) |
| Send a WebSocket data frame (text or binary opcode) per RFC 6455 §5.2. | |
| static void | on_close_write (uv_write_t *req, int status) |
| libuv write completion callback for WebSocket close frames. | |
| void | csilk_ws_close (csilk_ctx_t *c, uint16_t status_code, const char *reason) |
| Send a WebSocket close frame per RFC 6455 §5.5.1. | |
| void | csilk_ws_parse_frame (csilk_ctx_t *c, const uint8_t *buf, size_t nread) |
| Parse and dispatch an incoming WebSocket frame per RFC 6455 §5.2. | |
WebSocket handshake, frame encoding, and frame parsing implementation.
Architecture: The WebSocket implementation follows RFC 6455. The handshake (csilk_ws_handshake) performs the HTTP upgrade using SHA-1 + Base64 on the Sec-WebSocket-Key. Frame encoding (csilk_ws_send) constructs a raw WebSocket frame buffer per §5.2 and writes it via libuv. Frame parsing (csilk_ws_parse_frame) reads a complete frame from a buffer, unmasks client-to-server payloads, and dispatches by opcode. Close frames (csilk_ws_close) are encoded with optional status code + reason and sent asynchronously; the underlying TCP handle is closed after receiving the peer's close frame.
Wire format (RFC 6455 §5.2, 1 byte = 8 bits): Byte 0: [FIN=1][RSV=000][opcode=xxxx] Byte 1: [MASK=1][payload len=xxxxxxx] Bytes 2+ : Extended payload length (2 or 8 bytes, if len==126 or 127) Bytes 2/4/10+: Masking key (4 bytes, if MASK==1) Remaining: Payload data (XOR-decoded with masking key if MASK==1)
| #define WS_GUID "258EAFA5-E914-47DA-95CA-C5AB0DC85B11" |
WebSocket magic GUID string per RFC 6455 Section 4.2.2.
Appended to the client's Sec-WebSocket-Key before SHA-1 hashing to produce the Sec-WebSocket-Accept response header.
| void csilk_ws_close | ( | csilk_ctx_t * | c, |
| uint16_t | status_code, | ||
| const char * | reason | ||
| ) |
Send a WebSocket close frame per RFC 6455 §5.5.1.
Send a WebSocket close frame.
Constructs and sends a close frame with an optional status code and reason string. The payload is limited to 125 bytes (close frame + reason). After sending, the connection is NOT immediately closed — the peer is expected to respond with its own close frame.
| c | The request context. |
| status_code | WebSocket close status code (e.g., 1000 for normal, 1001 for "going away"). Pass 0 to omit the status code. |
| reason | Human-readable reason string (may be NULL). |
| void csilk_ws_handshake | ( | csilk_ctx_t * | c | ) |
Perform the WebSocket upgrade handshake per RFC 6455.
Perform the WebSocket upgrade handshake (HTTP Upgrade request).
Validates the presence of the Sec-WebSocket-Key header, computes the expected Sec-WebSocket-Accept response by concatenating the key with the WebSocket GUID ("258EAFA5-E914-47DA-95CA-C5AB0DC85B11"), SHA-1 hashing the result, and Base64-encoding the digest. Sets the Upgrade, Connection, and Sec-WebSocket-Accept response headers, sets status to 101 Switching Protocols, and marks the context as a WebSocket connection.
| c | The request context. |
| void csilk_ws_parse_frame | ( | csilk_ctx_t * | c, |
| const uint8_t * | buf, | ||
| size_t | nread | ||
| ) |
Parse and dispatch an incoming WebSocket frame per RFC 6455 §5.2.
Parse an incoming WebSocket frame from the raw TCP stream.
Parses the frame header (FIN, opcode, mask, payload length), extracts the payload, applies client-to-server masking if present, and dispatches based on opcode:
| c | The request context. |
| buf | Raw frame data received from the socket. |
| nread | Number of bytes available in buf. |
| void csilk_ws_send | ( | csilk_ctx_t * | c, |
| const uint8_t * | payload, | ||
| size_t | len, | ||
| int | opcode | ||
| ) |
Send a WebSocket data frame (text or binary opcode) per RFC 6455 §5.2.
Send a WebSocket data frame.
Constructs a WebSocket frame with the FIN bit set (final fragment), the specified opcode (0x01 for text, 0x02 for binary), and no masking (server-to-client frames are unmasked per RFC 6455). Supports payload lengths up to 2^64-1 using 7-bit, 16-bit, or 64-bit extended length fields as appropriate.
| c | The request context (must have _internal_client set). |
| payload | Frame payload data. |
| len | Payload length in bytes. |
| opcode | WebSocket opcode (0x01 for text, 0x02 for binary). |
|
static |
libuv write completion callback for WebSocket close frames.
Frees the frame buffer and write request. Logs an error if the write failed.
| req | The completed write request (freed by this callback). |
| status | UV status code (negative indicates error, logged to stderr). |
|
static |
libuv write completion callback for WebSocket frame sends.
Frees the frame buffer and the write request structure. Errors are silently ignored.
| req | The completed write request (freed by this callback). |
| status | UV status code (ignored). |