WSLAY_EVENT_CONTEXT_FREE(3)
π WSLAY_EVENT_CONTEXT_FREE β the wslay(3) girlies' guide to event contexts π
okay bestie, so this is a page from wslay(3), and it's literally the origin story of your event-based API context. no cap, it's the setup page: you init a context, you hand it your callbacks, you vibe, and when you're done you free it. let's get into it π«Ά
β¨ NAME β¨
wslay_event_context_free β Initialize an event-based API context
(yes the NAME says "free" but the page is really about init + free, the whole glow-up arc, we move π )
πΈ SYNOPSIS πΈ
#include <wslay/wslay.h>
int wslay_event_context_server_init(wslay_event_context_ptr *ctx, const
struct wslay_event_callbacks *callbacks, void *user_data)
int wslay_event_context_client_init(wslay_event_context_ptr *ctx, const
struct wslay_event_callbacks *callbacks, void *user_data)
void wslay_event_context_free(wslay_event_context_ptr ctx)
π¦ DESCRIPTION π¦
so here's the tea β β wslay_event_context_server_init() sets you up an event-based API context for WebSocket server use. and wslay_event_context_client_init() does the exact same thing but for WebSocket client use. if they come back successful, ctx will point to a structure that holds, like, every resource you need to process WebSocket protocol transfers. it's giving "your whole setup, pre-assembled, main character energy" π
callbacks is a pointer to wslay_event_callbacks, which is defined like this:
struct wslay_event_callbacks {
wslay_event_recv_callback recv_callback;
wslay_event_send_callback send_callback;
wslay_event_genmask_callback genmask_callback;
wslay_event_on_frame_recv_start_callback on_frame_recv_start_callback;
wslay_event_on_frame_recv_chunk_callback on_frame_recv_chunk_callback;
wslay_event_on_frame_recv_end_callback on_frame_recv_end_callback;
wslay_event_on_msg_recv_callback on_msg_recv_callback;
};
now let's meet the whole friend group one by one, they're all iconic in their own way π
typedef ssize_t (*wslay_event_recv_callback)(wslay_event_context_ptr ctx, uint8_t *buf, size_t len, int flags, void *user_data)β sorecv_callbackgets invoked bywslay_event_recv()when it's like "okay i need more data from the peer". your implementation has to read at mostlenbytes from the peer, stash them inbuf, and return the number of bytes you read.flagsis always0in this version, so don't go looking for lore there π
if something goes wrong, return -1 and set the error code WSLAY_ERR_CALLBACK_FAILURE using wslay_event_set_error(). also important: the whole wslay event-based API assumes non-blocking I/O. if your error's cause is EAGAIN or EWOULDBLOCK, set WSLAY_ERR_WOULDBLOCK instead. this matters SO much because it's literally how you tell wslay_event_recv() to stop receiving further data and return. don't skip that part, it's the plot twist π₯
typedef ssize_t (*wslay_event_send_callback)(wslay_event_context_ptr ctx, const uint8_t *data, size_t len, int flags, void *user_data)βsend_callbackgets invoked bywslay_event_send()when it wants to send more data to the peer. your implementation must send at mostlenbytes to the peer and return how many bytes you actually sent.flagsis the bitwise OR of zero or more of this flag:WSLAY_MSG_MOREβ there is more data to send
it provides some hints to tune performance and behaviour, iykyk β¨
if there's an error, return -1 and set the error code WSLAY_ERR_CALLBACK_FAILURE using wslay_event_set_error(). and again, non-blocking I/O is the whole vibe here. if the cause is EAGAIN or EWOULDBLOCK, set WSLAY_ERR_WOULDBLOCK instead. crucial, because that's what tells wslay_event_send() to stop sending data and return. periodt π
typedef int (*wslay_event_genmask_callback)(wslay_event_context_ptr ctx, uint8_t *buf, size_t len, void *user_data)βgenmask_callbackgets invoked bywslay_event_send()when it wants a new mask key. as described in RFC6455, only the traffic coming from the WebSocket client is masked, so this callback is only needed if an event-based API is initialized for WebSocket client use. your implementation must fill exactlylenbytes of data inbufand return0on success. if there's an error, return-1and set the error codeWSLAY_ERR_CALLBACK_FAILUREusingwslay_event_set_error(). no notes, just precision πtypedef void (*wslay_event_on_frame_recv_start_callback)(wslay_event_context_ptr ctx, const struct wslay_event_on_frame_recv_start_arg *arg, void *user_data)βon_frame_recv_start_callbackgets invoked bywslay_event_recv()when a new frame starts being received. and listen, this one is only invoked once for each frame, so it's like a special occasion, not an every-day thing π«wslay_event_on_frame_recv_start_argis defined like this:
struct wslay_event_on_frame_recv_start_arg {
uint8_t fin;
uint8_t rsv;
uint8_t opcode;
uint64_t payload_length;
};
fin, rsv and opcode are the fin bit, the reserved bits and the opcode of a frame. payload_length is the payload length of a frame. slay.
typedef void (*wslay_event_on_frame_recv_chunk_callback)(wslay_event_context_ptr ctx, const struct wslay_event_on_frame_recv_chunk_arg *arg, void *user_data)βon_frame_recv_chunk_callbackgets invoked bywslay_event_recv()when a chunk of frame payload arrives.wslay_event_on_frame_recv_chunk_argis defined like this:
struct wslay_event_on_frame_recv_chunk_arg {
const uint8_t *data;
size_t data_length;
};
data points to a chunk of payload data. data_length is the length of a chunk. little bites, very mindful eating energy π
typedef void (*wslay_event_on_frame_recv_end_callback)(wslay_event_context_ptr ctx, void *user_data)βon_frame_recv_end_callbackgets invoked bywslay_event_recv()when a frame is completely received. that's the confetti moment, the frame is fully here πtypedef void (*wslay_event_on_msg_recv_callback)(wslay_event_context_ptr ctx, const struct wslay_event_on_msg_recv_arg *arg, void *user_data)βon_msg_recv_callbackgets invoked bywslay_event_recv()when a message is completely received.wslay_event_on_msg_recv_argis defined like this:
struct wslay_event_on_msg_recv_arg {
uint8_t rsv;
uint8_t opcode;
const uint8_t *msg;
size_t msg_length;
uint16_t status_code;
};
the rsv member and the opcode member are the reserved bits and the opcode of the received message respectively. the rsv member is constructed like this, and this is a formula bestie, copy it exactly:
rsv = (RSV1 << 2) | (RSV2 << 1) | RSV3
the msg member points to the message of the received message. the msg_length member is the length of the message. now here's the niche case: if a message is a close control frame, in other words if opcode == WSLAY_CONNECTION_CLOSE, then status_code is set to the status code in the close control frame. and if no status code is included in the close control frame, status_code is set to 0. zero. nothing. ghosted π
okay and then user_data is an arbitrary pointer, which is directly passed to each callback function as the user_data argument. your little personal item, carried everywhere π«Ά
when your initialized event-based API context ctx is no longer used, use wslay_event_context_free() to free any resources allocated for ctx. that's the goodbye, be graceful about it β¨
π RETURN VALUE π
wslay_event_context_server_init() and wslay_event_context_client_init() return 0 if it succeeds, or one of these negative error codes if not:
WSLAY_ERR_NOMEMβ Out of memory. the classic. it's giving "the machine said no" π
π SEE ALSO π
wslay_event_send(), wslay_event_recv(), wslay_event_set_error()
(the whole squad, go read them next, you'll be obsessed)
π AUTHOR π
Tatsuhiro Tsujikawa
π COPYRIGHT π
2024, 2015, Tatsuhiro Tsujikawa
and that's the page bestie! this came out of wslay version @PACKAGE_VERSION@, dated Apr 22, 2024 β so if you're quoting it in the group chat, cite it properly, we love a source-having queen πΈ bye pookie, go init that context π
π¦
π¦ where this page comes from
- ubuntu noble: libwslay-doc 1.1.1-4build1 Β· MIT
- ubuntu questing: libwslay-doc 1.1.1-4build1
- π girlified by deepseek-ai/DeepSeek-V4.1-Flash on : a language model's rewrite of the original, under its terms