Repository navigation
WebSocket
Headers: <cwist/net/websocket/websocket.h> (blocking API),
<cwist/net/websocket/websocket_async.h> (reactor API), <cwist/app.h>
CWIST has two WebSocket APIs:
Blocking (cwist_app_ws) |
Reactor (cwist_app_ws_async) |
|
|---|---|---|
| Handler shape | one function that owns the connection and loops on receive
|
a callback per complete message |
| Server modes | reactor and classic pool | reactor only; in classic mode such a route answers 501
|
| Cost per connection | a thread while the handler runs | a reactor slot |
| Use for | simple request/response protocols | many concurrent connections (chat, live updates) |
static void echo(cwist_websocket *ws) {
cwist_ws_frame *f;
while ((f = cwist_websocket_receive(ws)) != NULL) {
if (f->opcode == CWIST_WS_FRAME_TEXT || f->opcode == CWIST_WS_FRAME_BINARY)
cwist_websocket_send(ws, f->opcode, f->payload, f->payload_len);
bool closing = f->opcode == CWIST_WS_FRAME_CLOSE;
cwist_websocket_frame_destroy(f);
if (closing) break;
}
}
cwist_app_ws(app, "/echo", echo);The framework performs the handshake and passes the upgraded connection to the handler; the connection closes when the handler returns.
| Function | Description |
|---|---|
cwist_ws_frame *cwist_websocket_receive(cwist_websocket *ws) |
Block until a complete message arrives; fragmented messages (RFC 6455 section 5.4) are reassembled. NULL on close or error. Free the frame with cwist_websocket_frame_destroy(). |
int cwist_websocket_send(cwist_websocket *ws, cwist_ws_opcode_t opcode, const uint8_t *data, size_t len) |
Send one frame. 0 or -1. |
int cwist_websocket_send_sequenced(cwist_websocket *ws, const uint8_t *data, size_t len, uint16_t chunk_payload_size) |
Split a large payload into binary frames with a sequence header (Sequenced Messages). |
uint8_t *cwist_websocket_receive_sequenced(cwist_websocket *ws, size_t *out_len) |
Receive and reassemble such a message (duplicates dropped, reordering handled). Free with cwist_free(). |
void cwist_websocket_close(cwist_websocket *ws) |
Send a close frame. |
cwist_websocket *cwist_websocket_upgrade(cwist_http_request *req, int client_fd) / void cwist_websocket_destroy(cwist_websocket *ws)
|
Upgrade a request yourself (outside cwist_app_ws) and free the context. |
bool cwist_websocket_upgrade_response(cwist_http_request *req, cwist_http_response *res) |
Validate an upgrade request and fill a 101 response without sending it. |
Opcodes: CWIST_WS_FRAME_CONTINUATION, _TEXT, _BINARY, _CLOSE,
_PING, _PONG. A frame has fin, opcode, payload and payload_len.
static void on_message(cwist_websocket_async *ws, cwist_ws_frame *frame, void *user_data) {
(void)user_data;
if (frame->opcode == CWIST_WS_FRAME_TEXT)
cwist_websocket_async_send(ws, CWIST_WS_FRAME_TEXT, frame->payload, frame->payload_len);
cwist_websocket_frame_destroy(frame); /* the callback must free the frame */
}
cwist_app_ws_async(app, "/live", on_message, NULL);| Function | Description |
|---|---|
void cwist_app_ws_async(cwist_app *app, const char *path, cwist_ws_on_message_t on_message, void *user_data) |
Register a reactor-driven route; on_message(ws, frame, user_data) runs on the reactor thread for every complete message. |
int cwist_websocket_async_send(cwist_websocket_async *ws, cwist_ws_opcode_t opcode, const uint8_t *data, size_t len) |
Send one frame without blocking; an unsent remainder is parked on a one-shot write slot. 0 or -1. |
void cwist_websocket_async_close(cwist_websocket_async *ws) |
Queue a close frame and schedule cleanup; safe inside the callback. |
Callbacks run on the reactor thread, so they must not block. Idle reactor
WebSocket connections close after CWIST_WS_ASYNC_IDLE_TIMEOUT_SEC (default
300; 0 disables).
The graphql-transport-ws protocol runs on the reactor WebSocket transport;
see GraphQL.
CWIST wiki, written against the dev branch of c4punks/CWIST. Pages marked "Source:" are generated from files under docs/; fix those in the repository. Questions: Discord.
Getting started
- Installation
- Quick Start
- Linking
- Server Modes
- Configuration and Environment
- Project CLI
- Tutorial / Korean
- Examples and Tutorials
Guides
Core
- API Reference
- Application
- Routing
- Middleware
- Requests and Responses
- Async Handlers
- Streaming Responses
- Error Handling
- Graceful Shutdown
- Multiport
Protocols
- HTTPS and TLS
- HTTP/2
- HTTP/3 and QUIC
- WebTransport
- WebSocket
- Server-Sent Events
- gRPC Server
- gRPC Client
- Protobuf and Codegen
- GraphQL
- WebRTC DataChannels
- HTTP Clients
Web features
- Static Files and Assets
- Big Dumb Reply Cache
- Compression
- Cookies
- Sessions and Flash
- Query Maps
- Multipart Uploads
- HTML Components
- Templates
- JSON
- Validation
- OpenAPI
Security
Data
Runtime
- Memory Management
- Full GC
- Async GC Ownership
- SString
- Reactor and I/O
- Metrics and Health
- Logging
- Testing
Platforms
Performance notes
- Benchmark Methodology
- C1M File Limits
- Reactor Fairness
- Cooperative Queuing
- Classic Pool Starvation
- Reactor Wakeup
- wrk Dual Histogram
- FIXED Endpoint Cache
- ADR-0001
- Durable Queue Gate
- Mux References
Project