diff options
Diffstat (limited to '')
-rw-r--r-- | doc/source/programmers-guide.rst | 207 |
1 files changed, 207 insertions, 0 deletions
diff --git a/doc/source/programmers-guide.rst b/doc/source/programmers-guide.rst new file mode 100644 index 0000000..d47d19c --- /dev/null +++ b/doc/source/programmers-guide.rst @@ -0,0 +1,207 @@ +The nghttp3 programmers' guide +============================== + +This document describes a basic usage of nghttp3 library and common +pitfalls which programmers might encounter. + +Assumptions +----------- + +nghttp3 is a thin HTTP/3 layer over an underlying QUIC stack. It +relies on an underlying QUIC stack for flow control and connection +management. Although nghttp3 is QUIC stack agnostic, it expects some +particular interfaces from QUIC stack. We will describe them below. + +QPACK operations are done behind the scenes. Application can use +:type:`nghttp3_settings` to change the behaviour of QPACK +encoder/decoder. + +We define some keywords to avoid ambiguity in this document: + +* HTTP payload: HTTP request/response body +* HTTP stream data: Series of HTTP header fields, HTTP payload, and + HTTP trailer fields, serialized into HTTP/3 wire format, which is + passed to or received from QUIC stack. + +Initialization +-------------- + +The :type:`nghttp3_conn` is a basic building block of nghttp3 library. +It is created per HTTP/3 connection. If an endpoint is a client, use +`nghttp3_conn_client_new` to initialize it as client. If it is a +server, use `nghttp3_conn_server_new` to initialize it as server. + +Those initialization functions take :type:`nghttp3_callbacks`. All +callbacks are optional, but setting no callback functions makes +nghttp3 library useless for the most cases. We list callbacks which +effectively required to do HTTP/3 transaction below: + +* :member:`acked_stream_data <nghttp3_callbacks.acked_stream_data>`: + Application has to retain HTTP payload (HTTP request/response body) + until they are no longer used by :type:`nghttp3_conn`. This + callback functions tells the largest offset of HTTP payload + acknowledged by a remote endpoint, and no longer used. +* :member:`stream_close <nghttp3_callbacks.stream_close>`: It is + called when a stream is closed. It is useful to free resources + allocated for a stream. +* :member:`recv_data <nghttp3_callbacks.recv_data>`: It is called when + HTTP payload (HTTP request/response body) is received. +* :member:`deferred_consume <nghttp3_callbacks.deferred_consume>`: It + is called when :type:`nghttp3_conn` consumed HTTP stream data which + had been blocked for synchronization between streams. Application + has to tell QUIC stack the number of bytes consumed which affects + flow control. We will discuss more about this callback later when + explaining `nghttp3_conn_read_stream`. +* :member:`recv_header <nghttp3_callbacks.recv_header>`: It is called + when an HTTP header field is received. +* :member:`send_stop_sending <nghttp3_callbacks.send_stop_sending>`: + It is called when QUIC STOP_SENDING frame must be sent for a + particular stream. Sending STOP_SENDING frame means that + :type:`nghttp3_conn` no longer reads an incoming data for a + particular stream. Application has to tell QUIC stack to send + STOP_SENDING frame. +* :member:`reset_stream <nghttp3_callbacks.reset_stream>`: It is + called when QUIC RESET_STREAM frame must be sent for a particular + stream. Sending RESET_STREAM frame means that :type:`nghttp3_conn` + stops sending any HTTP stream data to a particular stream. + Application has to tell QUIC stack to send RESET_STREAM frame. + +The initialization functions also takes :type:`nghttp3_settings` which +is a set of options to tweak HTTP3/ connection settings. +`nghttp3_settings_default` fills the default values. + +The *user_data* parameter to the initialization function is an opaque +pointer and it is passed to callback functions. + +Binding control streams +----------------------- + +HTTP/3 requires at least 3 local unidirectional streams for a control +stream and QPACK encoder/decoder streams. + +Use the following functions to bind those streams to their purposes: + +* `nghttp3_conn_bind_control_stream`: Bind a given stream ID to a HTTP + control stream. +* `nghttp3_conn_bind_qpack_streams`: Bind given 2 stream IDs to QPACK + encoder and decoder streams. + +Reading HTTP stream data +------------------------ + +`nghttp3_conn_read_stream` reads HTTP stream data from a particular +stream. It returns the number of bytes "consumed". "Consumed" means +that the those bytes are completely processed and QUIC stack can +increase the flow control credit of both stream and connection by that +amount. + +The HTTP payload notified by :member:`nghttp3_callbacks.recv_data` is +not included in the return value. This is because the consumption of +those data is done by application and nghttp3 library does not know +when that happens. + +Some HTTP stream data might be consumed later because of +synchronization between streams. In this case, those bytes are +notified by :member:`nghttp3_callbacks.deferred_consume`. + +In every case, the number of consumed HTTP stream data must be +notified to QUIC stack so that it can extend flow control limits. + +Writing HTTP stream data +------------------------ + +`nghttp3_conn_writev_stream` writes HTTP stream data to a particular +stream. The order of streams to produce HTTP stream data is +determined by the nghttp3 library. In general, the control streams +have higher priority. The regular HTTP streams are ordered by +header-based HTTP priority (see +https://tools.ietf.org/html/draft-ietf-httpbis-priority-03). + +When HTTP stream data is generated, its stream ID is assigned to +*\*pstream_id*. The pointer to HTTP stream data is assigned to *vec*, +and the function returns the number of *vec* it filled. If the +generated data is the final part of the stream, *\*pfin* gets nonzero +value. If no HTTP stream data is generated, the function returns 0 +and *\*pstream_id* gets -1. + +The function might return 0 and *\*pstream_id* has proper stream ID +and *\*pfin* set to nonzero. In this case, no data is written, but it +signals the end of the stream. Even though no data is written, QUIC +stack should be notified of the end of the stream. + +The produced HTTP stream data is passed to QUIC stack. Then call +`nghttp3_conn_add_write_offset` with the number of bytes accepted by +QUIC stack. This must be done even when the written data is 0 bytes +with fin (refer to the previous paragraph for this corner case). + +If QUIC stack indicates that a stream is blocked by stream level flow +control limit, call `nghttp3_conn_block_stream`. It makes the library +not to generate HTTP stream data for the stream. Call +`nghttp3_conn_unblock_stream` when stream level flow control limit is +increased. + +If QUIC stack indicates that the write side of stream is closed, call +`nghttp3_conn_shutdown_stream_write` instead of +`nghttp3_conn_block_stream` so that the stream never be scheduled in +the future. + +Creating HTTP request or response +--------------------------------- + +In order to create HTTP request, client application calls +`nghttp3_conn_submit_request`. :type:`nghttp3_data_reader` is used to +send HTTP payload (HTTP request body). + +Similarly, server application calls `nghttp3_conn_submit_response` to +create HTTP response. :type:`nghttp3_data_reader` is also used to +send HTTP payload (HTTP response body). + +In both cases, if :type:`nghttp3_data_reader` is not provided, no HTTP +payload is generated. + +The :member:`nghttp3_data_reader.read_data` is a callback function to +generate HTTP payload. Application must retain the data passed to the +library until those data are acknowledged by +:member:`nghttp3_callbacks.acked_stream_data`. When no data is +available but will become available in the future, application returns +:macro:`NGHTTP3_ERR_WOULDBLOCK` from this callback. Then the callback +is not called for the particular stream until +`nghttp3_conn_resume_stream` is called. + +Reading HTTP request or response +-------------------------------- + +The :member:`nghttp3_callbacks.recv_header` is called when an HTTP +header field is received. + +The :member:`nghttp3_callbacks.recv_data` is called when HTTP payload +is received. + +Acknowledgement of HTTP stream data +----------------------------------- + +QUIC stack must provide an interface to notify the amount of data +acknowledged by a remote endpoint. `nghttp3_conn_add_ack_offset` must +be called with the largest offset of acknowledged HTTP stream data. + +Handling QUIC stream events +--------------------------- + +If underlying QUIC stream is closed, call `nghttp3_conn_close_stream`. + +If underlying QUIC stream is reset by a remote endpoint (that is when +RESET_STREAM is received) or no longer read by a local endpoint (that +is when STOP_SENDING is sent), call +`nghttp3_conn_shutdown_stream_read`. + +Closing HTTP/3 connection gracefully +------------------------------------ + +`nghttp3_conn_submit_shutdown_notice` creates a message to a remote +endpoint that HTTP/3 connection is going down. The receiving endpoint +should stop sending HTTP request after reading this signal. After a +couple of RTTs, call `nghttp3_conn_submit_shutdown` to start graceful +shutdown. After calling this function, the local endpoint starts +rejecting new incoming streams. The existing streams are processed +normally. When all those streams are completely processed, the +connection can be closed. |