ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
http2.h File Reference

Go to the source code of this file.

Data Structures

struct  http2_request_view_t
struct  http2_header

Typedefs

typedef struct http2_connection http2_connection_t
typedef struct http2_header http2_header_t
typedef asciichat_error_t(* http2_request_fn) (http2_connection_t *connection, const http2_request_view_t *request, void *user_data)

Functions

asciichat_error_t http2_connection_create (http2_connection_t **connection, http2_request_fn on_request, void *user_data, size_t max_request_body_length, size_t max_response_body_length)
void http2_connection_destroy (http2_connection_t **connection)
asciichat_error_t http2_connection_receive (http2_connection_t *connection, const void *data, size_t length)
asciichat_error_t http2_connection_next_output (http2_connection_t *connection, const uint8_t **data, size_t *length)
asciichat_error_t http2_connection_submit_response (http2_connection_t *connection, int32_t stream_id, unsigned status, const http_header_t *headers, size_t header_count, const void *body, size_t body_length)

Typedef Documentation

◆ http2_connection_t

Definition at line 8 of file http2.h.

◆ http2_header_t

typedef struct http2_header http2_header_t

◆ http2_request_fn

typedef asciichat_error_t(* http2_request_fn) (http2_connection_t *connection, const http2_request_view_t *request, void *user_data)

Definition at line 23 of file http2.h.

Function Documentation

◆ http2_connection_create()

asciichat_error_t http2_connection_create ( http2_connection_t ** connection,
http2_request_fn on_request,
void * user_data,
size_t max_request_body_length,
size_t max_response_body_length )

Definition at line 189 of file http2.c.

190 {
191 if (!out || !on_request || max_request_body_length == 0 || max_response_body_length == 0)
192 return SET_ERRNO(ERROR_INVALID_PARAM, "Missing HTTP/2 request callback");
193 http2_connection_t *connection = SAFE_CALLOC(1, sizeof(*connection), http2_connection_t *);
194 nghttp2_session_callbacks *callbacks = NULL;
195 nghttp2_option *options = NULL;
196 if (nghttp2_session_callbacks_new(&callbacks) != 0 || nghttp2_option_new(&options) != 0) {
197 nghttp2_session_callbacks_del(callbacks);
198 nghttp2_option_del(options);
199 SAFE_FREE(connection);
200 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Cannot initialize HTTP/2 callbacks");
201 }
202 nghttp2_session_callbacks_set_on_begin_headers_callback(callbacks, on_begin_headers);
203 nghttp2_session_callbacks_set_on_header_callback(callbacks, on_header);
204 nghttp2_session_callbacks_set_on_data_chunk_recv_callback(callbacks, on_data);
205 nghttp2_session_callbacks_set_on_frame_recv_callback(callbacks, on_frame_recv);
206 nghttp2_session_callbacks_set_on_stream_close_callback(callbacks, on_stream_close);
207 if (nghttp2_session_server_new2(&connection->session, callbacks, connection, options) != 0) {
208 nghttp2_session_callbacks_del(callbacks);
209 nghttp2_option_del(options);
210 SAFE_FREE(connection);
211 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Cannot initialize HTTP/2 session");
212 }
213 nghttp2_session_callbacks_del(callbacks);
214 nghttp2_option_del(options);
215 nghttp2_settings_entry settings = {NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS, HTTP2_MAX_CONCURRENT_STREAMS};
216 if (nghttp2_submit_settings(connection->session, NGHTTP2_FLAG_NONE, &settings, 1) != 0) {
217 nghttp2_session_del(connection->session);
218 SAFE_FREE(connection);
219 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Cannot configure HTTP/2 stream limit");
220 }
221 connection->on_request = on_request;
222 connection->user_data = user_data;
223 connection->max_body_length = max_request_body_length;
224 connection->max_response_body_length = max_response_body_length;
225 *out = connection;
226 return ASCIICHAT_OK;
227}
#define SET_ERRNO(code,...)
#define SAFE_FREE(ptr)
Definition common.h:377
#define SAFE_CALLOC(count, size, cast)
Definition common.h:275
@ ERROR_NETWORK_PROTOCOL
Definition error_codes.h:76
@ ASCIICHAT_OK
Definition error_codes.h:46
@ ERROR_INVALID_PARAM
#define HTTP2_MAX_CONCURRENT_STREAMS
Definition http2.c:9
struct http2_connection http2_connection_t
Definition http2.h:8
static bool size_t gotel_query_t * out
Definition queries.h:8
size_t max_response_body_length
Definition http2.c:36
nghttp2_session * session
Definition http2.c:32
size_t max_body_length
Definition http2.c:35
http2_request_fn on_request
Definition http2.c:33
void * user_data
Definition http2.c:34

References ASCIICHAT_OK, ERROR_INVALID_PARAM, ERROR_NETWORK_PROTOCOL, HTTP2_MAX_CONCURRENT_STREAMS, http2_connection::max_body_length, http2_connection::max_response_body_length, http2_connection::on_request, out, SAFE_CALLOC, SAFE_FREE, http2_connection::session, SET_ERRNO, and http2_connection::user_data.

◆ http2_connection_destroy()

void http2_connection_destroy ( http2_connection_t ** connection)

Definition at line 229 of file http2.c.

229 {
230 if (!connection || !*connection)
231 return;
232 nghttp2_session_del((*connection)->session);
233 SAFE_FREE(*connection);
234 *connection = NULL;
235}

References SAFE_FREE.

◆ http2_connection_next_output()

asciichat_error_t http2_connection_next_output ( http2_connection_t * connection,
const uint8_t ** data,
size_t * length )

Definition at line 245 of file http2.c.

245 {
246 if (!connection || !data || !length)
247 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid HTTP/2 output request");
248 ssize_t output_length = nghttp2_session_mem_send(connection->session, &connection->output);
249 if (output_length < 0)
250 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Cannot serialize HTTP/2 output");
251 connection->output_length = (size_t)output_length;
252 *data = connection->output;
253 *length = connection->output_length;
254 return ASCIICHAT_OK;
255}
size_t output_length
Definition http2.c:38
const uint8_t * output
Definition http2.c:37

References ASCIICHAT_OK, ERROR_INVALID_PARAM, ERROR_NETWORK_PROTOCOL, http2_connection::output, http2_connection::output_length, http2_connection::session, and SET_ERRNO.

◆ http2_connection_receive()

asciichat_error_t http2_connection_receive ( http2_connection_t * connection,
const void * data,
size_t length )

Definition at line 237 of file http2.c.

237 {
238 if (!connection || (!data && length))
239 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid HTTP/2 input");
240 if (nghttp2_session_mem_recv(connection->session, data, length) < 0)
241 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Invalid HTTP/2 frame sequence");
242 return ASCIICHAT_OK;
243}

References ASCIICHAT_OK, ERROR_INVALID_PARAM, ERROR_NETWORK_PROTOCOL, http2_connection::session, and SET_ERRNO.

◆ http2_connection_submit_response()

asciichat_error_t http2_connection_submit_response ( http2_connection_t * connection,
int32_t stream_id,
unsigned status,
const http_header_t * headers,
size_t header_count,
const void * body,
size_t body_length )

Definition at line 257 of file http2.c.

259 {
260 if (!connection || status < 100 || status > 599 || body_length > connection->max_response_body_length ||
261 (!body && body_length))
262 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid HTTP/2 response");
263 if (header_count > HTTP2_MAX_HEADERS || (header_count && !headers))
264 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid HTTP/2 response headers");
265 char *status_text = SAFE_MALLOC(4, char *);
266 if (!status_text)
267 return SET_ERRNO(ERROR_MEMORY, "Cannot allocate HTTP/2 response status");
268 safe_snprintf(status_text, 4, "%u", status);
269 response_state_t *response = SAFE_CALLOC(1, sizeof(*response), response_state_t *);
270 if (!response) {
271 SAFE_FREE(status_text);
272 return SET_ERRNO(ERROR_MEMORY, "Cannot allocate HTTP/2 response state");
273 }
274 response->length = body_length;
275 if (body_length) {
276 response->data = SAFE_MALLOC(body_length, char *);
277 if (!response->data) {
278 SAFE_FREE(response);
279 return SET_ERRNO(ERROR_MEMORY, "Cannot allocate HTTP/2 response body");
280 }
281 memcpy(response->data, body, body_length);
282 }
283 nghttp2_nv *fields = SAFE_CALLOC(header_count + 1, sizeof(*fields), nghttp2_nv *);
284 if (!fields) {
285 SAFE_FREE(status_text);
286 SAFE_FREE(response->data);
287 SAFE_FREE(response);
288 return SET_ERRNO(ERROR_MEMORY, "Cannot allocate HTTP/2 response headers");
289 }
290 fields[0] = (nghttp2_nv){(uint8_t *)":status", (uint8_t *)status_text, 7, strlen(status_text), NGHTTP2_NV_FLAG_NONE};
291 for (size_t i = 0; i < header_count; ++i) {
292 if (!headers[i].name || !headers[i].value) {
293 SAFE_FREE(fields);
294 SAFE_FREE(status_text);
295 SAFE_FREE(response->data);
296 SAFE_FREE(response);
297 return SET_ERRNO(ERROR_INVALID_PARAM, "Invalid HTTP/2 response header");
298 }
299 fields[i + 1] = (nghttp2_nv){(uint8_t *)headers[i].name, (uint8_t *)headers[i].value, strlen(headers[i].name),
300 strlen(headers[i].value), NGHTTP2_NV_FLAG_NONE};
301 }
302 nghttp2_data_provider provider = {.source = {.ptr = response}, .read_callback = read_response};
303 int result =
304 nghttp2_submit_response(connection->session, stream_id, fields, header_count + 1, body_length ? &provider : NULL);
305 SAFE_FREE(fields);
306 SAFE_FREE(status_text);
307 if (!body_length)
308 SAFE_FREE(response);
309 if (result != 0) {
310 if (body_length) {
311 SAFE_FREE(response->data);
312 SAFE_FREE(response);
313 }
314 return SET_ERRNO(ERROR_NETWORK_PROTOCOL, "Cannot submit HTTP/2 response");
315 }
316 return ASCIICHAT_OK;
317}
#define SAFE_MALLOC(size, cast)
Definition common.h:265
unsigned char uint8_t
Definition common.h:60
@ ERROR_MEMORY
Definition error_codes.h:51
int safe_snprintf(char *buffer, size_t buffer_size, const char *format,...)
Platform-safe snprintf wrapper.
#define HTTP2_MAX_HEADERS
Definition http2.c:8
char * data
Definition http2.c:26
size_t length
Definition http2.c:27

References ASCIICHAT_OK, response_state_t::data, ERROR_INVALID_PARAM, ERROR_MEMORY, ERROR_NETWORK_PROTOCOL, HTTP2_MAX_HEADERS, response_state_t::length, http2_connection::max_response_body_length, SAFE_CALLOC, SAFE_FREE, SAFE_MALLOC, safe_snprintf(), http2_connection::session, SET_ERRNO, and http_header_t::value.

Referenced by http_response_finish().