|
| 1 | +#ifndef ROQR_H |
| 2 | +#define ROQR_H |
| 3 | + |
| 4 | +#include <stddef.h> |
| 5 | +#include <stdint.h> |
| 6 | + |
| 7 | +#ifdef __cplusplus |
| 8 | +extern "C" { |
| 9 | +#endif |
| 10 | + |
| 11 | +/* Error codes. 0x00-0x07 mirror the RoQR draft Table 2 application error |
| 12 | + * codes; values >= 100 are FFI-local. */ |
| 13 | +typedef enum roqr_error { |
| 14 | + ROQR_OK = 0, |
| 15 | + ROQR_ERR_GENERAL = 1, |
| 16 | + ROQR_ERR_INTERNAL = 2, |
| 17 | + ROQR_ERR_FRAME_ENCODING = 3, |
| 18 | + ROQR_ERR_STREAM_CREATION = 4, |
| 19 | + ROQR_ERR_FRAME_CANCELLED = 5, |
| 20 | + ROQR_ERR_UNKNOWN_FLOW = 6, |
| 21 | + ROQR_ERR_EXPECTATION_UNMET = 7, |
| 22 | + ROQR_ERR_INVALID_ARG = 100, |
| 23 | + ROQR_ERR_CONNECT_FAILED = 101, |
| 24 | + ROQR_ERR_TIMEOUT = 102 |
| 25 | +} roqr_error; |
| 26 | + |
| 27 | +typedef enum roqr_delivery_mode { |
| 28 | + ROQR_DELIVERY_STREAM = 0, |
| 29 | + ROQR_DELIVERY_DATAGRAM = 1, |
| 30 | + ROQR_DELIVERY_AUTO = 2 |
| 31 | +} roqr_delivery_mode; |
| 32 | + |
| 33 | +/* One RoQR frame crossing the ABI. On the receive callback, `payload` |
| 34 | + * points into memory owned by the library and valid only for the duration |
| 35 | + * of the callback; copy it if you need it later. */ |
| 36 | +typedef struct roqr_frame { |
| 37 | + uint64_t flow_id; |
| 38 | + uint64_t timestamp; |
| 39 | + uint8_t message_type; |
| 40 | + uint64_t message_stream_id; |
| 41 | + uint64_t chunk_stream_id; |
| 42 | + const uint8_t* payload; |
| 43 | + size_t payload_len; |
| 44 | +} roqr_frame; |
| 45 | + |
| 46 | +typedef struct roqr_client roqr_client; |
| 47 | + |
| 48 | +/* Library version, "major.minor.patch". */ |
| 49 | +const char* roqr_version(void); |
| 50 | + |
| 51 | +roqr_client* roqr_client_create(void); |
| 52 | +void roqr_client_destroy(roqr_client* client); |
| 53 | + |
| 54 | +/* Receive callback: fires on the QUIC network thread. Do NOT block and do |
| 55 | + * NOT call roqr_client_destroy or roqr_client_wait_* from inside it; |
| 56 | + * roqr_client_send/close/bind_flow/retire_flow are safe to call. `frame` |
| 57 | + * and its payload are valid only for the duration of the call. */ |
| 58 | +typedef void (*roqr_message_cb)(const roqr_frame* frame, void* user_data); |
| 59 | + |
| 60 | +/* Close callback: fires on the network thread with the peer's application |
| 61 | + * error code (0 for a clean close). Same non-blocking rules apply. */ |
| 62 | +typedef void (*roqr_closed_cb)(uint64_t app_error_code, void* user_data); |
| 63 | + |
| 64 | +/* Set handlers before roqr_client_connect. */ |
| 65 | +void roqr_client_set_on_message(roqr_client* client, roqr_message_cb cb, |
| 66 | + void* user_data); |
| 67 | +void roqr_client_set_on_closed(roqr_client* client, roqr_closed_cb cb, |
| 68 | + void* user_data); |
| 69 | + |
| 70 | +roqr_error roqr_client_connect(roqr_client* client, const char* host, |
| 71 | + uint16_t port, int insecure_skip_verify); |
| 72 | +/* Returns 1 if connected within timeout_ms, 0 on timeout. */ |
| 73 | +int roqr_client_wait_connected(roqr_client* client, int timeout_ms); |
| 74 | +int roqr_client_datagrams_negotiated(roqr_client* client); |
| 75 | + |
| 76 | +/* Thread-safe. Returns ROQR_ERR_INVALID_ARG for a null client/frame or an |
| 77 | + * empty payload (RoQR requires payload length > 0). */ |
| 78 | +roqr_error roqr_client_send(roqr_client* client, const roqr_frame* frame, |
| 79 | + roqr_delivery_mode mode); |
| 80 | + |
| 81 | +void roqr_client_bind_flow(roqr_client* client, uint64_t flow_id); |
| 82 | +void roqr_client_retire_flow(roqr_client* client, uint64_t flow_id); |
| 83 | + |
| 84 | +void roqr_client_close(roqr_client* client, uint64_t app_error_code); |
| 85 | +int roqr_client_wait_closed(roqr_client* client, int timeout_ms); |
| 86 | + |
| 87 | +#ifdef __cplusplus |
| 88 | +} |
| 89 | +#endif |
| 90 | + |
| 91 | +#endif /* ROQR_H */ |
0 commit comments