WebSockets¶
Real-time messaging over the RFC 6455 WebSocket protocol: the server-side opening handshake (with a real SHA-1, not a stub) and text-frame encode/decode, all on top of an already-connected socket.
The functions take an abs_socket — the same handle Server() uses (a Winsock SOCKET on Windows, an int on POSIX). They are standalone, so they layer onto any listening endpoint you have already accepted.
API¶
| Function | Description |
|---|---|
bool ws_accept(abs_socket fd, const char *request_str) |
Performs the server-side handshake: extracts the Sec-WebSocket-Key, sends the 101 Switching Protocols response, returns whether it succeeded. |
var ws_compute_accept(const char *key) |
The Sec-WebSocket-Accept value for a client key: base64(SHA1(key + magic GUID)). |
void ws_send(abs_socket fd, const char *msg) |
Sends msg as a single unmasked text frame. |
var ws_recv(abs_socket fd) |
Receives one frame, unmasking it if the client masked it (RFC 6455 requires clients to mask), and returns the payload as an ABS_STR. None when the connection closes. |
size_t ws_encode_frame(char *out, size_t cap, const char *msg) |
Encodes msg into a server frame at out; returns the frame length (0 if cap is too small). Exposed so the wire format can be exercised without a socket. |
long ws_decode_frame(const char *buf, size_t buf_len, char *out, size_t out_cap) |
Decodes one frame (masked or unmasked) into out; returns the payload length, or -1 for a malformed/truncated frame. |
Handshake¶
var app = Server(0); /* listen (abs_server.c) */
intptr_t client_fd = accept(app->val.server.socket_fd, NULL, NULL);
char request[2048] = { 0 };
recv(client_fd, request, sizeof(request) - 1, 0);
if (ws_accept(client_fd, request)) {
ws_send(client_fd, "hello browser");
var reply = ws_recv(client_fd);
print(reply);
}
The RFC 6455 worked example checks out:
Framing helpers¶
ws_encode_frame / ws_decode_frame round-trip without any network:
char frame[32];
char out[32];
size_t n = ws_encode_frame(frame, sizeof(frame), "Hello"); /* 81 05 48 65 6c 6c 6f */
long len = ws_decode_frame(frame, n, out, sizeof(out)); /* 5, out == "Hello" */
ws_decode_frame also handles masked client frames: it reads the 4-byte mask and XORs it off.
Notes¶
- Text frames only (opcode
0x1), unmasked server-to-client per RFC 6455 §5.3. Fragmentation, ping/pong, close frames, and extensions are out of scope — this is a minimal real-time channel, not a full browser-grade stack. - Payload lengths use the 7-bit / 16-bit / 64-bit encodings; received frames are capped at 16 MiB.
ws_recvloops to read partialrecv()results and returnsABS_ERRORfor oversized frames,Noneon disconnect.- Windows links
ws2_32automatically; POSIX needs no extra flags. - See
tests/test_ws.cfor the handshake and framing vectors, andexamples/crypto_demo.cfor a wire-format simulation.
Back to README.