|
cwist
Modern C web framework with libttak runtime
|
Experimental GraphQL subscriptions over the graphql-ws WebSocket subprotocol (v3.7 Phase 4). More...
#include <cwist/net/graphql/graphql_ws.h>#include <cwist/core/mem/alloc.h>#include <cwist/net/websocket/websocket_async.h>#include <pthread.h>#include <stdatomic.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include "../websocket/ws_async_internal.h"
Go to the source code of this file.
Macros | |
| #define | GQL_WS_CLOSE_BAD_REQUEST 4400 |
| #define | GQL_WS_CLOSE_UNAUTHORIZED 4401 |
| #define | GQL_WS_CLOSE_DUPLICATE_ID 4409 |
| #define | GQL_WS_CLOSE_SUBSCRIBE_BEFORE_INIT 4429 |
Typedefs | |
| typedef struct gql_sub_field | gql_sub_field_t |
| typedef struct gql_ws_op | gql_ws_op_t |
| typedef struct gql_ws_conn | gql_ws_conn_t |
| typedef struct gql_ws_flush | gql_ws_flush_t |
Experimental GraphQL subscriptions over the graphql-ws WebSocket subprotocol (v3.7 Phase 4).
Protocol (Sec-WebSocket-Protocol: graphql-transport-ws): connection_init -> connection_ack subscribe {id, payload:{query,variables,operationName}} -> one next {id, payload:{data:{field: <event>}}} per published event; error {id, payload:[...]} when the operation fails to start; complete {id} when the operation ends (client complete or socket close) ping/pong -> JSON keepalive at any time after init subscribe before connection_init closes the socket with 4429; other protocol violations close with 4400/4401/4409.
Broker model: a subscription resolver returns an event source (a set of topics). cwist_graphql_publish() is the single fan-out entry point and may be called from ANY thread: matched operations queue a serialized next message, and a reactor-posted flush node drains the queue on the owning reactor thread (only the reactor thread may touch the socket). Connection teardown is reported by the WS layer's on_close hook, which unlinks every operation of the connection from the broker and releases the protocol state; refcounting keeps the state alive until in-flight flush nodes have drained.
Definition in file graphql_ws.c.
| #define GQL_WS_CLOSE_BAD_REQUEST 4400 |
Definition at line 40 of file graphql_ws.c.
| #define GQL_WS_CLOSE_DUPLICATE_ID 4409 |
Definition at line 42 of file graphql_ws.c.
| #define GQL_WS_CLOSE_SUBSCRIBE_BEFORE_INIT 4429 |
Definition at line 43 of file graphql_ws.c.
| #define GQL_WS_CLOSE_UNAUTHORIZED 4401 |
Definition at line 41 of file graphql_ws.c.
| typedef struct gql_sub_field gql_sub_field_t |
| typedef struct gql_ws_conn gql_ws_conn_t |
| typedef struct gql_ws_flush gql_ws_flush_t |
| typedef struct gql_ws_op gql_ws_op_t |
| bool cwist_graphql_event_source_add_topic | ( | cwist_graphql_event_source_t * | src, |
| const char * | topic | ||
| ) |
Add a topic to an event source.
Idempotent: adding a topic that is already present succeeds without duplicating it. The topic string is copied, so the caller keeps ownership of topic.
| src | Event source to modify; must not be NULL. |
| topic | Topic name to add; must be a non-empty string. |
Definition at line 76 of file graphql_ws.c.
References cap, cwist_alloc_array(), cwist_free(), and cwist_strdup().
| cwist_graphql_event_source_t * cwist_graphql_event_source_create | ( | void | ) |
Create an empty event source (topic interest set).
Definition at line 60 of file graphql_ws.c.
References cwist_alloc().
| void cwist_graphql_event_source_destroy | ( | cwist_graphql_event_source_t * | src | ) |
Destroy an event source, freeing all topic strings and the set.
| src | Event source to free; NULL is a no-op. |
Definition at line 101 of file graphql_ws.c.
References cap, and cwist_free().
Publish an event to the in-process broker. The payload becomes the field value inside each delivered next message's data (null when payload is NULL). Thread-safe: may be called from any thread; matched subscriptions are queued and delivered on their connection's reactor thread.
| topic | Broker topic (non-empty string). |
| payload | Event payload (borrowed) or NULL. |
next messages queued. Definition at line 468 of file graphql_ws.c.
References cap, cwist_alloc_array(), and cwist_free().
| bool cwist_graphql_ws_add_subscription | ( | cwist_graphql_ws_t * | gws, |
| const char * | field, | ||
| cwist_graphql_subscribe_fn | subscribe_fn, | ||
| void * | ctx | ||
| ) |
Register (or replace) the resolver for a subscription root field.
If the field is already registered, its resolver and context are replaced in place; otherwise a new entry is prepended to the registry. The field name is copied.
| gws | Endpoint to register on; must not be NULL. |
| field | Subscription root field name; must be a non-empty string. |
| subscribe_fn | Resolver invoked per subscribe for field; must not be NULL. It receives the parsed arguments and variables and returns an event source (owned by the broker) or NULL to reject the operation. |
| ctx | Opaque pointer passed through to subscribe_fn. |
Definition at line 190 of file graphql_ws.c.
References cap, cwist_alloc(), cwist_free(), and cwist_strdup().
| bool cwist_graphql_ws_attach | ( | cwist_graphql_ws_t * | gws, |
| int | fd, | ||
| cwist_reactor_t * | reactor, | ||
| const uint8_t * | initial, | ||
| size_t | initial_len | ||
| ) |
Attach the graphql-ws protocol handler to a connected, upgraded fd. The fd is driven reactively by reactor (same ownership contract as cwist_websocket_async_attach): the HTTP layer must not touch the fd after a successful call.
| gws | Endpoint whose schema resolves subscriptions. |
| fd | Connected client socket (set non-blocking here). |
| reactor | Reactor that will own the connection. |
| initial | Bytes already read past the upgrade request (may be NULL). |
| initial_len | Number of valid bytes at initial. |
Definition at line 730 of file graphql_ws.c.
References cap, and cwist_websocket_async_attach_ex().
| cwist_graphql_ws_t * cwist_graphql_ws_create | ( | cwist_graphql_schema_t * | schema | ) |
Create a graphql-ws endpoint holding a subscription field registry.
| schema | GraphQL schema the endpoint answers to; not owned, must outlive the endpoint. |
schema is NULL or allocation fails. Free with cwist_graphql_ws_destroy(). Definition at line 144 of file graphql_ws.c.
References cap, and cwist_alloc().
| void cwist_graphql_ws_destroy | ( | cwist_graphql_ws_t * | gws | ) |
Destroy an endpoint and its subscription field registry.
Does not touch active connections or broker operations still referencing the endpoint's resolvers.
| gws | Endpoint to free; NULL is a no-op. |
Definition at line 162 of file graphql_ws.c.
References cap, and cwist_free().