diff --git a/capi/include/hyper.h b/capi/include/hyper.h index cc97c84e3c..8cc7b40e89 100644 --- a/capi/include/hyper.h +++ b/capi/include/hyper.h @@ -249,6 +249,14 @@ typedef void (*hyper_userdata_drop)(void*); typedef int (*hyper_body_data_callback)(void*, struct hyper_context*, struct hyper_buf**); +typedef void (*hyper_request_on_informational_callback)(void*, struct hyper_response*); + +typedef int (*hyper_headers_foreach_callback)(void*, const uint8_t*, size_t, const uint8_t*, size_t); + +typedef size_t (*hyper_io_read_callback)(void*, struct hyper_context*, uint8_t*, size_t); + +typedef size_t (*hyper_io_write_callback)(void*, struct hyper_context*, const uint8_t*, size_t); + /* The main definition of a service. This callback will be invoked for each transaction on the connection. @@ -266,14 +274,6 @@ typedef int (*hyper_body_data_callback)(void*, struct hyper_context*, struct hyp */ typedef void (*hyper_service_callback)(void*, struct hyper_request*, struct hyper_response_channel*); -typedef void (*hyper_request_on_informational_callback)(void*, struct hyper_response*); - -typedef int (*hyper_headers_foreach_callback)(void*, const uint8_t*, size_t, const uint8_t*, size_t); - -typedef size_t (*hyper_io_read_callback)(void*, struct hyper_context*, uint8_t*, size_t); - -typedef size_t (*hyper_io_write_callback)(void*, struct hyper_context*, const uint8_t*, size_t); - #ifdef __cplusplus extern "C" { #endif // __cplusplus @@ -501,661 +501,661 @@ enum hyper_code hyper_clientconn_options_http1_allow_multiline_headers(struct hy int enabled); /* - Create a new HTTP/1 serverconn options object. + Frees a `hyper_error`. + + This should be used for any error once it is no longer needed. */ -struct hyper_http1_serverconn_options *hyper_http1_serverconn_options_new(const struct hyper_executor *exec); +void hyper_error_free(struct hyper_error *err); /* - Free a `hyper_http1_serverconn_options*`. + Get an equivalent `hyper_code` from this error. */ -void hyper_http1_serverconn_options_free(struct hyper_http1_serverconn_options *opts); +enum hyper_code hyper_error_code(const struct hyper_error *err); /* - Set whether HTTP/1 connections should support half-closures. + Print the details of this error to a buffer. - Clients can chose to shutdown their write-side while waiting for the server to respond. - Setting this to true will prevent closing the connection immediately if read detects an EOF - in the middle of a request. + The `dst_len` value must be the maximum length that the buffer can + store. - Default is `false` + The return value is number of bytes that were written to `dst`. */ -enum hyper_code hyper_http1_serverconn_options_half_close(struct hyper_http1_serverconn_options *opts, - bool enabled); +size_t hyper_error_print(const struct hyper_error *err, uint8_t *dst, size_t dst_len); /* - Enables or disables HTTP/1 keep-alive. + Construct a new HTTP request. - Default is `true`. + To avoid a memory leak, the request must eventually be consumed by + `hyper_request_free` or `hyper_clientconn_send`. */ -enum hyper_code hyper_http1_serverconn_options_keep_alive(struct hyper_http1_serverconn_options *opts, - bool enabled); +struct hyper_request *hyper_request_new(void); /* - Set whether HTTP/1 connections will write header names as title case at the socket level. + Free an HTTP request. - Default is `false`. + This should only be used if the request isn't consumed by + `hyper_clientconn_send`. */ -enum hyper_code hyper_http1_serverconn_options_title_case_headers(struct hyper_http1_serverconn_options *opts, - bool enabled); +void hyper_request_free(struct hyper_request *req); /* - Set whether to support preserving original header cases. - - Currently, this will record the original cases received, and store them in a private - extension on the Request. It will also look for and use such an extension in any provided - Response. - - Since the relevant extension is still private, there is no way to interact with the - original cases. The only effect this can have now is to forward the cases in a proxy-like - fashion. - - Default is `false`. + Set the HTTP Method of the request. */ -enum hyper_code hyper_http1_serverconn_options_preserve_header_case(struct hyper_http1_serverconn_options *opts, - bool enabled); +enum hyper_code hyper_request_set_method(struct hyper_request *req, + const uint8_t *method, + size_t method_len); /* - Set a timeout for reading client request headers. If a client does not - transmit the entire header within this time, the connection is closed. + Get the HTTP Method of the request. - Default is to have no timeout. + `method` must be a pointer to a buffer that this function will populate with the HTTP + method of the request. The `header_len` argument must be a pointer to a `size_t` which, on + call, is populated with the maximum length of the `method` buffer and, on successful + response, will be set to the actual length of the value written into the buffer. */ -enum hyper_code hyper_http1_serverconn_options_header_read_timeout(struct hyper_http1_serverconn_options *opts, - uint64_t millis); +enum hyper_code hyper_request_method(const struct hyper_request *req, + uint8_t *method, + size_t *method_len); /* - Set whether HTTP/1 connections should try to use vectored writes, or always flatten into a - single buffer. + Set the URI of the request. - Note that setting this to false may mean more copies of body data, but may also improve - performance when an IO transport doesn’t support vectored writes well, such as most TLS - implementations. + The request's URI is best described as the `request-target` from the RFCs. So in HTTP/1, + whatever is set will get sent as-is in the first line (GET $uri HTTP/1.1). It + supports the 4 defined variants, origin-form, absolute-form, authority-form, and + asterisk-form. - Setting this to true will force hyper to use queued strategy which may eliminate - unnecessary cloning on some TLS backends. + The underlying type was built to efficiently support HTTP/2 where the request-target is + split over :scheme, :authority, and :path. As such, each part can be set explicitly, or the + type can parse a single contiguous string and if a scheme is found, that slot is "set". If + the string just starts with a path, only the path portion is set. All pseudo headers that + have been parsed/set are sent when the connection type is HTTP/2. - Default is to automatically guess which mode to use, this function overrides the heuristic. + To set each slot explicitly, use `hyper_request_set_uri_parts`. */ -enum hyper_code hyper_http1_serverconn_options_writev(struct hyper_http1_serverconn_options *opts, - bool enabled); +enum hyper_code hyper_request_set_uri(struct hyper_request *req, + const uint8_t *uri, + size_t uri_len); /* - Set the maximum buffer size for the HTTP/1 connection. Must be no lower `8192`. + Set the URI of the request with separate scheme, authority, and + path/query strings. - Default is a sensible value. + Each of `scheme`, `authority`, and `path_and_query` should either be + null, to skip providing a component, or point to a UTF-8 encoded + string. If any string pointer argument is non-null, its corresponding + `len` parameter must be set to the string's length. */ -enum hyper_code hyper_http1_serverconn_options_max_buf_size(struct hyper_http1_serverconn_options *opts, - uintptr_t max_buf_size); +enum hyper_code hyper_request_set_uri_parts(struct hyper_request *req, + const uint8_t *scheme, + size_t scheme_len, + const uint8_t *authority, + size_t authority_len, + const uint8_t *path_and_query, + size_t path_and_query_len); /* - Aggregates flushes to better support pipelined responses. + Get the URI of the request split into scheme, authority and path/query strings. - Experimental, may have bugs. + Each of `scheme`, `authority` and `path_and_query` may be pointers to buffers that this + function will populate with the appropriate values from the request. If one of these + pointers is non-NULL then the associated `_len` field must be a pointer to a `size_t` + which, on call, is populated with the maximum length of the buffer and, on successful + response, will be set to the actual length of the value written into the buffer. - Default is `false`. - */ -enum hyper_code hyper_http1_serverconn_options_pipeline_flush(struct hyper_http1_serverconn_options *opts, - bool enabled); + If a buffer is passed as `NULL` then the `_len` field will be ignored and that component + will be skipped. -/* - Create a new HTTP/2 serverconn options object bound to the provided executor. + This function may fail with `HYPERE_INSUFFICIENT_SPACE` if one of the provided buffers is + not long enough to hold the value from the request. */ -struct hyper_http2_serverconn_options *hyper_http2_serverconn_options_new(const struct hyper_executor *exec); +enum hyper_code hyper_request_uri_parts(const struct hyper_request *req, + uint8_t *scheme, + size_t *scheme_len, + uint8_t *authority, + size_t *authority_len, + uint8_t *path_and_query, + size_t *path_and_query_len); /* - Free a `hyper_http2_serverconn_options*`. - */ -void hyper_http2_serverconn_options_free(struct hyper_http2_serverconn_options *opts); + Set the preferred HTTP version of the request. -/* - Sets the `SETTINGS_INITIAL_WINDOW_SIZE` option for HTTP/2 stream-level flow control. + The version value should be one of the `HYPER_HTTP_VERSION_` constants. - Passing `0` instructs hyper to use a sensible default value. + Note that this won't change the major HTTP version of the connection, + since that is determined at the handshake step. */ -enum hyper_code hyper_http2_serverconn_options_initial_stream_window_size(struct hyper_http2_serverconn_options *opts, - unsigned int window_size); +enum hyper_code hyper_request_set_version(struct hyper_request *req, int version); /* - Sets the max connection-level flow control for HTTP/2. + Get the HTTP version used by this request. - Passing `0` instructs hyper to use a sensible default value. + The returned value could be: + + - `HYPER_HTTP_VERSION_1_0` + - `HYPER_HTTP_VERSION_1_1` + - `HYPER_HTTP_VERSION_2` + - `HYPER_HTTP_VERSION_NONE` if newer (or older). */ -enum hyper_code hyper_http2_serverconn_options_initial_connection_window_size(struct hyper_http2_serverconn_options *opts, - unsigned int window_size); +int hyper_request_version(const struct hyper_request *resp); /* - Sets whether to use an adaptive flow control. - - Enabling this will override the limits set in http2_initial_stream_window_size and - http2_initial_connection_window_size. + Gets a reference to the HTTP headers of this request - Default is `false`. + This is not an owned reference, so it should not be accessed after the + `hyper_request` has been consumed. */ -enum hyper_code hyper_http2_serverconn_options_adaptive_window(struct hyper_http2_serverconn_options *opts, - bool enabled); +struct hyper_headers *hyper_request_headers(struct hyper_request *req); /* - Sets the maximum frame size to use for HTTP/2. + Set the body of the request. - Passing `0` instructs hyper to use a sensible default value. + The default is an empty body. + + This takes ownership of the `hyper_body *`, you must not use it or + free it after setting it on the request. */ -enum hyper_code hyper_http2_serverconn_options_max_frame_size(struct hyper_http2_serverconn_options *opts, - unsigned int frame_size); +enum hyper_code hyper_request_set_body(struct hyper_request *req, struct hyper_body *body); /* - Sets the `SETTINGS_MAX_CONCURRENT_STREAMS` option for HTTP2 connections. + Take ownership of the body of this request. - Default is no limit (`std::u32::MAX`). Passing `0` will use this default. + It is safe to free the request even after taking ownership of its body. */ -enum hyper_code hyper_http2_serverconn_options_max_concurrent_streams(struct hyper_http2_serverconn_options *opts, - unsigned int max_streams); +struct hyper_body *hyper_request_body(struct hyper_request *req); /* - Sets an interval for HTTP/2 Ping frames should be sent to keep a connection alive. + Set an informational (1xx) response callback. - Default is to not use keep-alive pings. Passing `0` will use this default. - */ -enum hyper_code hyper_http2_serverconn_options_keep_alive_interval(struct hyper_http2_serverconn_options *opts, - uint64_t interval_seconds); + The callback is called each time hyper receives an informational (1xx) + response for this request. -/* - Sets a timeout for receiving an acknowledgement of the keep-alive ping. + The third argument is an opaque user data pointer, which is passed to + the callback each time. - If the ping is not acknowledged within the timeout, the connection will be closed. Does - nothing if `hyper_http2_serverconn_options_keep_alive_interval` is disabled. + The callback is passed the `void *` data pointer, and a + `hyper_response *` which can be inspected as any other response. The + body of the response will always be empty. - Default is 20 seconds. + NOTE: The `hyper_response *` is just borrowed data, and will not + be valid after the callback finishes. You must copy any data you wish + to persist. */ -enum hyper_code hyper_http2_serverconn_options_keep_alive_timeout(struct hyper_http2_serverconn_options *opts, - uint64_t timeout_seconds); +enum hyper_code hyper_request_on_informational(struct hyper_request *req, + hyper_request_on_informational_callback callback, + void *data, + hyper_userdata_drop drop); /* - Set the maximum write buffer size for each HTTP/2 stream. Must be no larger than - `u32::MAX`. - - Default is a sensible value. + Construct a new HTTP 200 Ok response */ -enum hyper_code hyper_http2_serverconn_options_max_send_buf_size(struct hyper_http2_serverconn_options *opts, - uintptr_t max_buf_size); +struct hyper_response *hyper_response_new(void); /* - Enables the extended `CONNECT` protocol. + Free an HTTP response. + + This should be used for any response once it is no longer needed. */ -enum hyper_code hyper_http2_serverconn_options_enable_connect_protocol(struct hyper_http2_serverconn_options *opts); +void hyper_response_free(struct hyper_response *resp); /* - Sets the max size of received header frames. + Get the HTTP-Status code of this response. - Default is a sensible value. + It will always be within the range of 100-599. */ -enum hyper_code hyper_http2_serverconn_options_max_header_list_size(struct hyper_http2_serverconn_options *opts, - uint32_t max); +uint16_t hyper_response_status(const struct hyper_response *resp); /* - Create a service from a wrapped callback function. + Set the HTTP Status-Code of this response. */ -struct hyper_service *hyper_service_new(hyper_service_callback service_fn); +void hyper_response_set_status(struct hyper_response *resp, uint16_t status); /* - Register opaque userdata with the `hyper_service`. This userdata must be `Send` in a rust - sense (i.e. can be passed between threads) though it doesn't have to be thread-safe (it - won't be accessed from multiple thread concurrently). + Get a pointer to the reason-phrase of this response. - The service takes ownership of the userdata and will call the `drop_userdata` callback when - the service task is complete. If the `drop_userdata` callback is `NULL` then the service - will instead borrow the userdata and forget it when the associated task is completed and - thus the calling code is responsible for cleaning up the userdata through some other - mechanism. + This buffer is not null-terminated. + + This buffer is owned by the response, and should not be used after + the response has been freed. + + Use `hyper_response_reason_phrase_len()` to get the length of this + buffer. */ -void hyper_service_set_userdata(struct hyper_service *service, - void *userdata, - hyper_userdata_drop drop); +const uint8_t *hyper_response_reason_phrase(const struct hyper_response *resp); /* - Frees a hyper_service object if no longer needed + Get the length of the reason-phrase of this response. + + Use `hyper_response_reason_phrase()` to get the buffer pointer. */ -void hyper_service_free(struct hyper_service *service); +size_t hyper_response_reason_phrase_len(const struct hyper_response *resp); /* - Serve the provided `hyper_service *` as an HTTP/1 endpoint over the provided `hyper_io *` - and configured as per the `hyper_http1_serverconn_options *`. + Set the preferred HTTP version of the response. - Returns a `hyper_task*` which must be given to an executor to make progress. + The version value should be one of the `HYPER_HTTP_VERSION_` constants. - This function consumes the IO and Service objects and thus they should not be accessed - after this function is called. + Note that this won't change the major HTTP version of the connection, + since that is determined at the handshake step. */ -struct hyper_task *hyper_serve_http1_connection(struct hyper_http1_serverconn_options *serverconn_options, - struct hyper_io *io, - struct hyper_service *service); +enum hyper_code hyper_response_set_version(struct hyper_response *req, int version); /* - Serve the provided `hyper_service *` as an HTTP/2 endpoint over the provided `hyper_io *` - and configured as per the `hyper_http2_serverconn_options *`. + Get the HTTP version used by this response. - Returns a `hyper_task*` which must be given to an executor to make progress. + The returned value could be: - This function consumes the IO and Service objects and thus they should not be accessed - after this function is called. + - `HYPER_HTTP_VERSION_1_0` + - `HYPER_HTTP_VERSION_1_1` + - `HYPER_HTTP_VERSION_2` + - `HYPER_HTTP_VERSION_NONE` if newer (or older). */ -struct hyper_task *hyper_serve_http2_connection(struct hyper_http2_serverconn_options *serverconn_options, - struct hyper_io *io, - struct hyper_service *service); +int hyper_response_version(const struct hyper_response *resp); /* - Serve the provided `hyper_service *` as either an HTTP/1 or HTTP/2 (depending on what the - client requests) endpoint over the provided `hyper_io *` and configured as per the - appropriate `hyper_httpX_serverconn_options *`. - - Returns a `hyper_task*` which must be given to an executor to make progress. + Gets a reference to the HTTP headers of this response. - This function consumes the IO and Service objects and thus they should not be accessed - after this function is called. + This is not an owned reference, so it should not be accessed after the + `hyper_response` has been freed. */ -struct hyper_task *hyper_serve_httpX_connection(struct hyper_http1_serverconn_options *http1_serverconn_options, - struct hyper_http2_serverconn_options *http2_serverconn_options, - struct hyper_io *io, - struct hyper_service *service); +struct hyper_headers *hyper_response_headers(struct hyper_response *resp); /* - Sends a `hyper_response*` back to the client. This function consumes the response and the - channel. + Set the body of the response. - See [hyper_service_callback] for details. + The default is an empty body. + + This takes ownership of the `hyper_body *`, you must not use it or + free it after setting it on the request. */ -void hyper_response_channel_send(struct hyper_response_channel *channel, - struct hyper_response *response); +enum hyper_code hyper_response_set_body(struct hyper_response *rsp, struct hyper_body *body); /* - Frees a `hyper_error`. + Take ownership of the body of this response. - This should be used for any error once it is no longer needed. + It is safe to free the response even after taking ownership of its body. + + To avoid a memory leak, the body must eventually be consumed by + `hyper_body_free`, `hyper_body_foreach`, or `hyper_request_set_body`. */ -void hyper_error_free(struct hyper_error *err); +struct hyper_body *hyper_response_body(struct hyper_response *resp); /* - Get an equivalent `hyper_code` from this error. + Iterates the headers passing each name and value pair to the callback. + + The `userdata` pointer is also passed to the callback. + + The callback should return `HYPER_ITER_CONTINUE` to keep iterating, or + `HYPER_ITER_BREAK` to stop. */ -enum hyper_code hyper_error_code(const struct hyper_error *err); +void hyper_headers_foreach(const struct hyper_headers *headers, + hyper_headers_foreach_callback func, + void *userdata); /* - Print the details of this error to a buffer. + Sets the header with the provided name to the provided value. - The `dst_len` value must be the maximum length that the buffer can - store. + This overwrites any previous value set for the header. + */ +enum hyper_code hyper_headers_set(struct hyper_headers *headers, + const uint8_t *name, + size_t name_len, + const uint8_t *value, + size_t value_len); - The return value is number of bytes that were written to `dst`. +/* + Adds the provided value to the list of the provided name. + + If there were already existing values for the name, this will append the + new value to the internal list. */ -size_t hyper_error_print(const struct hyper_error *err, uint8_t *dst, size_t dst_len); +enum hyper_code hyper_headers_add(struct hyper_headers *headers, + const uint8_t *name, + size_t name_len, + const uint8_t *value, + size_t value_len); /* - Construct a new HTTP request. + Create a new IO type used to represent a transport. - To avoid a memory leak, the request must eventually be consumed by - `hyper_request_free` or `hyper_clientconn_send`. + The read and write functions of this transport should be set with + `hyper_io_set_read` and `hyper_io_set_write`. + + To avoid a memory leak, the IO handle must eventually be consumed by + `hyper_io_free` or `hyper_clientconn_handshake`. */ -struct hyper_request *hyper_request_new(void); +struct hyper_io *hyper_io_new(void); /* - Free an HTTP request. + Free an IO handle. This should only be used if the request isn't consumed by - `hyper_clientconn_send`. + `hyper_clientconn_handshake`. */ -void hyper_request_free(struct hyper_request *req); +void hyper_io_free(struct hyper_io *io); /* - Set the HTTP Method of the request. + Set the user data pointer for this IO to some value. + + This value is passed as an argument to the read and write callbacks. + + If passed, the `drop_func` will be called on the `userdata` when the + `hyper_io` is destroyed (either explicitly by `hyper_io_free` or + implicitly by an associated hyper task completing). */ -enum hyper_code hyper_request_set_method(struct hyper_request *req, - const uint8_t *method, - size_t method_len); +void hyper_io_set_userdata(struct hyper_io *io, void *data, hyper_userdata_drop drop_func); /* - Get the HTTP Method of the request. + Get the user data pointer for this IO value. - `method` must be a pointer to a buffer that this function will populate with the HTTP - method of the request. The `header_len` argument must be a pointer to a `size_t` which, on - call, is populated with the maximum length of the `method` buffer and, on successful - response, will be set to the actual length of the value written into the buffer. + The userdata is still owned by the IO so must be treated as "borrowed" + + Returns NULL if no userdata has been set. */ -enum hyper_code hyper_request_method(const struct hyper_request *req, - uint8_t *method, - size_t *method_len); +void *hyper_io_get_userdata(struct hyper_io *io); /* - Set the URI of the request. + Set the read function for this IO transport. - The request's URI is best described as the `request-target` from the RFCs. So in HTTP/1, - whatever is set will get sent as-is in the first line (GET $uri HTTP/1.1). It - supports the 4 defined variants, origin-form, absolute-form, authority-form, and - asterisk-form. + Data that is read from the transport should be put in the `buf` pointer, + up to `buf_len` bytes. The number of bytes read should be the return value. - The underlying type was built to efficiently support HTTP/2 where the request-target is - split over :scheme, :authority, and :path. As such, each part can be set explicitly, or the - type can parse a single contiguous string and if a scheme is found, that slot is "set". If - the string just starts with a path, only the path portion is set. All pseudo headers that - have been parsed/set are sent when the connection type is HTTP/2. + It is undefined behavior to try to access the bytes in the `buf` pointer, + unless you have already written them yourself. It is also undefined behavior + to return that more bytes have been written than actually set on the `buf`. - To set each slot explicitly, use `hyper_request_set_uri_parts`. + If there is no data currently available, a waker should be claimed from + the `ctx` and registered with whatever polling mechanism is used to signal + when data is available later on. The return value should be + `HYPER_IO_PENDING`. + + If there is an irrecoverable error reading data, then `HYPER_IO_ERROR` + should be the return value. */ -enum hyper_code hyper_request_set_uri(struct hyper_request *req, - const uint8_t *uri, - size_t uri_len); +void hyper_io_set_read(struct hyper_io *io, hyper_io_read_callback func); /* - Set the URI of the request with separate scheme, authority, and - path/query strings. + Set the write function for this IO transport. - Each of `scheme`, `authority`, and `path_and_query` should either be - null, to skip providing a component, or point to a UTF-8 encoded - string. If any string pointer argument is non-null, its corresponding - `len` parameter must be set to the string's length. - */ -enum hyper_code hyper_request_set_uri_parts(struct hyper_request *req, - const uint8_t *scheme, - size_t scheme_len, - const uint8_t *authority, - size_t authority_len, - const uint8_t *path_and_query, - size_t path_and_query_len); + Data from the `buf` pointer should be written to the transport, up to + `buf_len` bytes. The number of bytes written should be the return value. -/* - Get the URI of the request split into scheme, authority and path/query strings. + If no data can currently be written, the `waker` should be cloned and + registered with whatever polling mechanism is used to signal when data + is available later on. The return value should be `HYPER_IO_PENDING`. - Each of `scheme`, `authority` and `path_and_query` may be pointers to buffers that this - function will populate with the appropriate values from the request. If one of these - pointers is non-NULL then the associated `_len` field must be a pointer to a `size_t` - which, on call, is populated with the maximum length of the buffer and, on successful - response, will be set to the actual length of the value written into the buffer. + Yeet. - If a buffer is passed as `NULL` then the `_len` field will be ignored and that component - will be skipped. + If there is an irrecoverable error reading data, then `HYPER_IO_ERROR` + should be the return value. + */ +void hyper_io_set_write(struct hyper_io *io, hyper_io_write_callback func); - This function may fail with `HYPERE_INSUFFICIENT_SPACE` if one of the provided buffers is - not long enough to hold the value from the request. +/* + Create a new HTTP/1 serverconn options object. */ -enum hyper_code hyper_request_uri_parts(const struct hyper_request *req, - uint8_t *scheme, - size_t *scheme_len, - uint8_t *authority, - size_t *authority_len, - uint8_t *path_and_query, - size_t *path_and_query_len); +struct hyper_http1_serverconn_options *hyper_http1_serverconn_options_new(const struct hyper_executor *exec); /* - Set the preferred HTTP version of the request. + Free a `hyper_http1_serverconn_options*`. + */ +void hyper_http1_serverconn_options_free(struct hyper_http1_serverconn_options *opts); - The version value should be one of the `HYPER_HTTP_VERSION_` constants. +/* + Set whether HTTP/1 connections should support half-closures. - Note that this won't change the major HTTP version of the connection, - since that is determined at the handshake step. + Clients can chose to shutdown their write-side while waiting for the server to respond. + Setting this to true will prevent closing the connection immediately if read detects an EOF + in the middle of a request. + + Default is `false` */ -enum hyper_code hyper_request_set_version(struct hyper_request *req, int version); +enum hyper_code hyper_http1_serverconn_options_half_close(struct hyper_http1_serverconn_options *opts, + bool enabled); /* - Get the HTTP version used by this request. - - The returned value could be: + Enables or disables HTTP/1 keep-alive. - - `HYPER_HTTP_VERSION_1_0` - - `HYPER_HTTP_VERSION_1_1` - - `HYPER_HTTP_VERSION_2` - - `HYPER_HTTP_VERSION_NONE` if newer (or older). + Default is `true`. */ -int hyper_request_version(const struct hyper_request *resp); +enum hyper_code hyper_http1_serverconn_options_keep_alive(struct hyper_http1_serverconn_options *opts, + bool enabled); /* - Gets a reference to the HTTP headers of this request + Set whether HTTP/1 connections will write header names as title case at the socket level. - This is not an owned reference, so it should not be accessed after the - `hyper_request` has been consumed. + Default is `false`. */ -struct hyper_headers *hyper_request_headers(struct hyper_request *req); +enum hyper_code hyper_http1_serverconn_options_title_case_headers(struct hyper_http1_serverconn_options *opts, + bool enabled); /* - Set the body of the request. + Set whether to support preserving original header cases. - The default is an empty body. + Currently, this will record the original cases received, and store them in a private + extension on the Request. It will also look for and use such an extension in any provided + Response. - This takes ownership of the `hyper_body *`, you must not use it or - free it after setting it on the request. + Since the relevant extension is still private, there is no way to interact with the + original cases. The only effect this can have now is to forward the cases in a proxy-like + fashion. + + Default is `false`. */ -enum hyper_code hyper_request_set_body(struct hyper_request *req, struct hyper_body *body); +enum hyper_code hyper_http1_serverconn_options_preserve_header_case(struct hyper_http1_serverconn_options *opts, + bool enabled); /* - Take ownership of the body of this request. + Set a timeout for reading client request headers. If a client does not + transmit the entire header within this time, the connection is closed. - It is safe to free the request even after taking ownership of its body. + Default is to have no timeout. */ -struct hyper_body *hyper_request_body(struct hyper_request *req); +enum hyper_code hyper_http1_serverconn_options_header_read_timeout(struct hyper_http1_serverconn_options *opts, + uint64_t millis); /* - Set an informational (1xx) response callback. - - The callback is called each time hyper receives an informational (1xx) - response for this request. + Set whether HTTP/1 connections should try to use vectored writes, or always flatten into a + single buffer. - The third argument is an opaque user data pointer, which is passed to - the callback each time. + Note that setting this to false may mean more copies of body data, but may also improve + performance when an IO transport doesn’t support vectored writes well, such as most TLS + implementations. - The callback is passed the `void *` data pointer, and a - `hyper_response *` which can be inspected as any other response. The - body of the response will always be empty. + Setting this to true will force hyper to use queued strategy which may eliminate + unnecessary cloning on some TLS backends. - NOTE: The `hyper_response *` is just borrowed data, and will not - be valid after the callback finishes. You must copy any data you wish - to persist. + Default is to automatically guess which mode to use, this function overrides the heuristic. */ -enum hyper_code hyper_request_on_informational(struct hyper_request *req, - hyper_request_on_informational_callback callback, - void *data, - hyper_userdata_drop drop); +enum hyper_code hyper_http1_serverconn_options_writev(struct hyper_http1_serverconn_options *opts, + bool enabled); /* - Construct a new HTTP 200 Ok response + Set the maximum buffer size for the HTTP/1 connection. Must be no lower `8192`. + + Default is a sensible value. */ -struct hyper_response *hyper_response_new(void); +enum hyper_code hyper_http1_serverconn_options_max_buf_size(struct hyper_http1_serverconn_options *opts, + uintptr_t max_buf_size); /* - Free an HTTP response. + Aggregates flushes to better support pipelined responses. - This should be used for any response once it is no longer needed. + Experimental, may have bugs. + + Default is `false`. */ -void hyper_response_free(struct hyper_response *resp); +enum hyper_code hyper_http1_serverconn_options_pipeline_flush(struct hyper_http1_serverconn_options *opts, + bool enabled); /* - Get the HTTP-Status code of this response. - - It will always be within the range of 100-599. + Create a new HTTP/2 serverconn options object bound to the provided executor. */ -uint16_t hyper_response_status(const struct hyper_response *resp); +struct hyper_http2_serverconn_options *hyper_http2_serverconn_options_new(const struct hyper_executor *exec); /* - Set the HTTP Status-Code of this response. + Free a `hyper_http2_serverconn_options*`. */ -void hyper_response_set_status(struct hyper_response *resp, uint16_t status); +void hyper_http2_serverconn_options_free(struct hyper_http2_serverconn_options *opts); /* - Get a pointer to the reason-phrase of this response. - - This buffer is not null-terminated. - - This buffer is owned by the response, and should not be used after - the response has been freed. + Sets the `SETTINGS_INITIAL_WINDOW_SIZE` option for HTTP/2 stream-level flow control. - Use `hyper_response_reason_phrase_len()` to get the length of this - buffer. + Passing `0` instructs hyper to use a sensible default value. */ -const uint8_t *hyper_response_reason_phrase(const struct hyper_response *resp); +enum hyper_code hyper_http2_serverconn_options_initial_stream_window_size(struct hyper_http2_serverconn_options *opts, + unsigned int window_size); /* - Get the length of the reason-phrase of this response. + Sets the max connection-level flow control for HTTP/2. - Use `hyper_response_reason_phrase()` to get the buffer pointer. + Passing `0` instructs hyper to use a sensible default value. */ -size_t hyper_response_reason_phrase_len(const struct hyper_response *resp); +enum hyper_code hyper_http2_serverconn_options_initial_connection_window_size(struct hyper_http2_serverconn_options *opts, + unsigned int window_size); /* - Set the preferred HTTP version of the response. + Sets whether to use an adaptive flow control. - The version value should be one of the `HYPER_HTTP_VERSION_` constants. + Enabling this will override the limits set in http2_initial_stream_window_size and + http2_initial_connection_window_size. - Note that this won't change the major HTTP version of the connection, - since that is determined at the handshake step. + Default is `false`. */ -enum hyper_code hyper_response_set_version(struct hyper_response *req, int version); +enum hyper_code hyper_http2_serverconn_options_adaptive_window(struct hyper_http2_serverconn_options *opts, + bool enabled); /* - Get the HTTP version used by this response. - - The returned value could be: + Sets the maximum frame size to use for HTTP/2. - - `HYPER_HTTP_VERSION_1_0` - - `HYPER_HTTP_VERSION_1_1` - - `HYPER_HTTP_VERSION_2` - - `HYPER_HTTP_VERSION_NONE` if newer (or older). + Passing `0` instructs hyper to use a sensible default value. */ -int hyper_response_version(const struct hyper_response *resp); +enum hyper_code hyper_http2_serverconn_options_max_frame_size(struct hyper_http2_serverconn_options *opts, + unsigned int frame_size); /* - Gets a reference to the HTTP headers of this response. + Sets the `SETTINGS_MAX_CONCURRENT_STREAMS` option for HTTP2 connections. - This is not an owned reference, so it should not be accessed after the - `hyper_response` has been freed. + Default is no limit (`std::u32::MAX`). Passing `0` will use this default. */ -struct hyper_headers *hyper_response_headers(struct hyper_response *resp); +enum hyper_code hyper_http2_serverconn_options_max_concurrent_streams(struct hyper_http2_serverconn_options *opts, + unsigned int max_streams); /* - Set the body of the response. - - The default is an empty body. + Sets an interval for HTTP/2 Ping frames should be sent to keep a connection alive. - This takes ownership of the `hyper_body *`, you must not use it or - free it after setting it on the request. + Default is to not use keep-alive pings. Passing `0` will use this default. */ -enum hyper_code hyper_response_set_body(struct hyper_response *rsp, struct hyper_body *body); +enum hyper_code hyper_http2_serverconn_options_keep_alive_interval(struct hyper_http2_serverconn_options *opts, + uint64_t interval_seconds); /* - Take ownership of the body of this response. + Sets a timeout for receiving an acknowledgement of the keep-alive ping. - It is safe to free the response even after taking ownership of its body. + If the ping is not acknowledged within the timeout, the connection will be closed. Does + nothing if `hyper_http2_serverconn_options_keep_alive_interval` is disabled. - To avoid a memory leak, the body must eventually be consumed by - `hyper_body_free`, `hyper_body_foreach`, or `hyper_request_set_body`. + Default is 20 seconds. */ -struct hyper_body *hyper_response_body(struct hyper_response *resp); +enum hyper_code hyper_http2_serverconn_options_keep_alive_timeout(struct hyper_http2_serverconn_options *opts, + uint64_t timeout_seconds); /* - Iterates the headers passing each name and value pair to the callback. - - The `userdata` pointer is also passed to the callback. + Set the maximum write buffer size for each HTTP/2 stream. Must be no larger than + `u32::MAX`. - The callback should return `HYPER_ITER_CONTINUE` to keep iterating, or - `HYPER_ITER_BREAK` to stop. + Default is a sensible value. */ -void hyper_headers_foreach(const struct hyper_headers *headers, - hyper_headers_foreach_callback func, - void *userdata); +enum hyper_code hyper_http2_serverconn_options_max_send_buf_size(struct hyper_http2_serverconn_options *opts, + uintptr_t max_buf_size); /* - Sets the header with the provided name to the provided value. - - This overwrites any previous value set for the header. + Enables the extended `CONNECT` protocol. */ -enum hyper_code hyper_headers_set(struct hyper_headers *headers, - const uint8_t *name, - size_t name_len, - const uint8_t *value, - size_t value_len); +enum hyper_code hyper_http2_serverconn_options_enable_connect_protocol(struct hyper_http2_serverconn_options *opts); /* - Adds the provided value to the list of the provided name. + Sets the max size of received header frames. - If there were already existing values for the name, this will append the - new value to the internal list. + Default is a sensible value. */ -enum hyper_code hyper_headers_add(struct hyper_headers *headers, - const uint8_t *name, - size_t name_len, - const uint8_t *value, - size_t value_len); +enum hyper_code hyper_http2_serverconn_options_max_header_list_size(struct hyper_http2_serverconn_options *opts, + uint32_t max); /* - Create a new IO type used to represent a transport. - - The read and write functions of this transport should be set with - `hyper_io_set_read` and `hyper_io_set_write`. - - To avoid a memory leak, the IO handle must eventually be consumed by - `hyper_io_free` or `hyper_clientconn_handshake`. + Create a service from a wrapped callback function. */ -struct hyper_io *hyper_io_new(void); +struct hyper_service *hyper_service_new(hyper_service_callback service_fn); /* - Free an IO handle. + Register opaque userdata with the `hyper_service`. This userdata must be `Send` in a rust + sense (i.e. can be passed between threads) though it doesn't have to be thread-safe (it + won't be accessed from multiple thread concurrently). - This should only be used if the request isn't consumed by - `hyper_clientconn_handshake`. + The service takes ownership of the userdata and will call the `drop_userdata` callback when + the service task is complete. If the `drop_userdata` callback is `NULL` then the service + will instead borrow the userdata and forget it when the associated task is completed and + thus the calling code is responsible for cleaning up the userdata through some other + mechanism. */ -void hyper_io_free(struct hyper_io *io); +void hyper_service_set_userdata(struct hyper_service *service, + void *userdata, + hyper_userdata_drop drop); /* - Set the user data pointer for this IO to some value. - - This value is passed as an argument to the read and write callbacks. - - If passed, the `drop_func` will be called on the `userdata` when the - `hyper_io` is destroyed (either explicitly by `hyper_io_free` or - implicitly by an associated hyper task completing). + Frees a hyper_service object if no longer needed */ -void hyper_io_set_userdata(struct hyper_io *io, void *data, hyper_userdata_drop drop_func); +void hyper_service_free(struct hyper_service *service); /* - Get the user data pointer for this IO value. + Serve the provided `hyper_service *` as an HTTP/1 endpoint over the provided `hyper_io *` + and configured as per the `hyper_http1_serverconn_options *`. - The userdata is still owned by the IO so must be treated as "borrowed" + Returns a `hyper_task*` which must be given to an executor to make progress. - Returns NULL if no userdata has been set. + This function consumes the IO and Service objects and thus they should not be accessed + after this function is called. */ -void *hyper_io_get_userdata(struct hyper_io *io); +struct hyper_task *hyper_serve_http1_connection(struct hyper_http1_serverconn_options *serverconn_options, + struct hyper_io *io, + struct hyper_service *service); /* - Set the read function for this IO transport. - - Data that is read from the transport should be put in the `buf` pointer, - up to `buf_len` bytes. The number of bytes read should be the return value. - - It is undefined behavior to try to access the bytes in the `buf` pointer, - unless you have already written them yourself. It is also undefined behavior - to return that more bytes have been written than actually set on the `buf`. + Serve the provided `hyper_service *` as an HTTP/2 endpoint over the provided `hyper_io *` + and configured as per the `hyper_http2_serverconn_options *`. - If there is no data currently available, a waker should be claimed from - the `ctx` and registered with whatever polling mechanism is used to signal - when data is available later on. The return value should be - `HYPER_IO_PENDING`. + Returns a `hyper_task*` which must be given to an executor to make progress. - If there is an irrecoverable error reading data, then `HYPER_IO_ERROR` - should be the return value. + This function consumes the IO and Service objects and thus they should not be accessed + after this function is called. */ -void hyper_io_set_read(struct hyper_io *io, hyper_io_read_callback func); +struct hyper_task *hyper_serve_http2_connection(struct hyper_http2_serverconn_options *serverconn_options, + struct hyper_io *io, + struct hyper_service *service); /* - Set the write function for this IO transport. + Serve the provided `hyper_service *` as either an HTTP/1 or HTTP/2 (depending on what the + client requests) endpoint over the provided `hyper_io *` and configured as per the + appropriate `hyper_httpX_serverconn_options *`. - Data from the `buf` pointer should be written to the transport, up to - `buf_len` bytes. The number of bytes written should be the return value. + Returns a `hyper_task*` which must be given to an executor to make progress. - If no data can currently be written, the `waker` should be cloned and - registered with whatever polling mechanism is used to signal when data - is available later on. The return value should be `HYPER_IO_PENDING`. + This function consumes the IO and Service objects and thus they should not be accessed + after this function is called. + */ +struct hyper_task *hyper_serve_httpX_connection(struct hyper_http1_serverconn_options *http1_serverconn_options, + struct hyper_http2_serverconn_options *http2_serverconn_options, + struct hyper_io *io, + struct hyper_service *service); - Yeet. +/* + Sends a `hyper_response*` back to the client. This function consumes the response and the + channel. - If there is an irrecoverable error reading data, then `HYPER_IO_ERROR` - should be the return value. + See [hyper_service_callback] for details. */ -void hyper_io_set_write(struct hyper_io *io, hyper_io_write_callback func); +void hyper_response_channel_send(struct hyper_response_channel *channel, + struct hyper_response *response); /* Creates a new task executor.