tutorial.rst revision aedecb45
1********
2Tutorial
3********
4
5.. highlight:: c
6
7Introduction
8============
9
10The LSQUIC library provides facilities for operating a QUIC (Google QUIC
11or IETF QUIC) server or client with optional HTTP (or HTTP/3) functionality.
12To do that, it specifies an application programming interface (API) and
13exposes several basic object types to operate upon:
14
15- engine;
16- connection; and
17- stream.
18
19An engine manages connections, processes incoming packets, and schedules
20outgoing packets.  An engine operates in one of two modes: client or server.
21
22The LSQUIC library does not use sockets to receive and send packets; that is
23handled by the user-supplied callbacks.  The library also does not mandate
24the use of any particular event loop.  Instead, it has functions to help the
25user schedule events.  (Thus, using an event loop is not even strictly
26necessary.)  The various callbacks and settings are supplied to the engine
27constructor.
28
29A connection carries one or more streams, ensures reliable data delivery,
30and handles the protocol details.
31
32A stream usually corresponds to a request/response pair: a client sends
33its request over a single stream and a server sends its response back
34using the same stream.  This is the Google QUIC and HTTP/3 use case.
35Nevertheless, the library does not limit one to this scenario.  Any
36application protocol can be implemented using LSQUIC -- as long as it
37can be implemented using the QUIC transport protocol.  The library provides
38hooks for stream events: when a stream is created or closed, when it has
39data to read or when it can be written to, and so on.
40
41In the following sections, we will describe how to:
42
43- initialize the library;
44- configure and instantiate an engine object;
45- send and receive packets; and
46- work with connections and streams.
47
48Include Files
49-------------
50
51A single include file, :file:`lsquic.h`, contains all the necessary
52LSQUIC declarations:
53
54::
55
56    #include <lsquic.h>
57
58Library Initialization
59======================
60
61Before the first engine object is instantiate, the library must be
62initialized using :func:`lsquic_global_init()`:
63
64::
65
66    if (0 != lsquic_global_init(LSQUIC_GLOBAL_CLIENT|LSQUIC_GLOBAL_SERVER))
67    {
68        exit(EXIT_FAILURE);
69    }
70    /* OK, do something useful */
71
72If you plan to instantiate engines only in a single mode, client or server,
73you can omit the appropriate flag.
74
75After all engines have been destroyed and the LSQUIC library is no longer
76going to be used, the global initialization can be undone:
77
78::
79
80    lsquic_global_cleanup();
81    exit(EXIT_SUCCESS);
82
83Engine Instantiation
84====================
85
86Engine instantiation is performed by :func:`lsquic_engine_new()`:
87
88::
89
90    /* Create an engine in server mode with HTTP behavior: */
91    lsquic_engine_t *engine
92        = lsquic_engine_new(LSENG_SERVER|LSENG_HTTP, &engine_api);
93
94The engine mode is selected by using the ``LSENG_SERVER`` flag.  If
95present, the engine will be in server mode; if not, the engine will
96be in client mode.
97
98Using the ``LSENG_HTTP`` flag enables the HTTP behavior:  The library
99hides the interaction between the HTTP application layer and the QUIC
100transport layer and presents a simple, unified (between Google QUIC and
101HTTP/3) way of sending and receiving HTTP messages.  Behind the scenes,
102the library will compress and uncompress HTTP headers, add and remove
103HTTP/3 stream framing, and operate the necessary control streams.
104
105Engine Configuration
106--------------------
107
108The second argument to :func:`lsquic_engine_new()` is a pointer to
109a struct of type :type:`lsquic_engine_api`.  This structure lists
110several user-specified function pointers that the engine is to use
111to perform various functions.  Mandatory among these are:
112
113- function to set packets out, :member:`lsquic_engine_api.ea_packets_out`;
114- functions linked to connection and stream events,
115  :member:`lsquic_engine_api.ea_stream_if`;
116- function to look up certificate to use, :member:`lsquic_engine_api.ea_lookup_cert` (in server mode); and
117- function to fetch SSL context, :member:`lsquic_engine_api.ea_get_ssl_ctx` (in server mode).
118
119The minimal structure for a client will look like this:
120
121::
122
123    lsquic_engine_api engine_api = {
124        .ea_packets_out     = send_packets_out,
125        .ea_packets_out_ctx = (void *) sockfd,  /* For example */
126        .ea_stream_if       = &stream_callbacks,
127        .ea_stream_if_ctx   = &some_context,
128    };
129
130Engine Settings
131---------------
132
133Engine settings can be changed by specifying
134:member:`lsquic_engine_api.ea_settings`.  There are **many** parameters
135to tweak: supported QUIC versions, amount of memory dedicated to connections
136and streams, various timeout values, and so on.  See
137:ref:`apiref-engine-settings` for full details.  If ``ea_settings`` is set
138to ``NULL``, the engine will use the defaults, which should be OK.
139
140Sending Packets
141===============
142
143The :member:`lsquic_engine_api.ea_packets_out` is the function that gets
144called when an engine instance has packets to send.  It could look like
145this:
146
147::
148
149    /* Return number of packets sent or -1 on error */
150    static int
151    send_packets_out (void *ctx, const struct lsquic_out_spec *specs,
152                                                    unsigned n_specs)
153    {
154        struct msghdr msg;
155        int sockfd;
156        unsigned n;
157
158        memset(&msg, 0, sizeof(msg));
159        sockfd = (int) (uintptr_t) ctx;
160
161        for (n = 0; n < n_specs; ++n)
162        {
163            msg.msg_name       = (void *) specs[n].dest_sa;
164            msg.msg_namelen    = sizeof(struct sockaddr_in);
165            msg.msg_iov        = specs[n].iov;
166            msg.msg_iovlen     = specs[n].iovlen;
167            if (sendmsg(sockfd, &msg, 0) < 0)
168                break;
169        }
170
171        return (int) n;
172    }
173
174Note that the version above is very simple.  :type:`lsquic_out_spec`
175also specifies local address as well as ECN value.  These are set
176using ancillary data in a platform-dependent way.
177
178Receiving Packets
179=================
180
181The user reads packets and provides them to an engine instance using
182:func:`lsquic_engine_packet_in()`.
183
184*TODO*
185
186Running Connections
187===================
188
189A connection needs to be processed once in a while.  It needs to be
190processed when one of the following is true:
191
192- There are incoming packets;
193- A stream is both readable by the user code and the user code wants
194  to read from it;
195- A stream is both writeable by the user code and the user code wants
196  to write to it;
197- User has written to stream outside of on_write() callbacks (that is
198  allowed) and now there are packets ready to be sent;
199- A timer (pacer, retransmission, idle, etc) has expired;
200- A control frame needs to be sent out;
201- A stream needs to be serviced or created.
202
203Each of these use cases is handled by a single function,
204:func:`lsquic_engine_process_conns()`.
205
206The connections to which the conditions above apply are processed (or
207"ticked") in the least recently ticked order.  After calling this function,
208you can see when is the next time a connection needs to be processed using
209:func:`lsquic_engine_earliest_adv_tick()`.
210
211Based on this value, next event can be scheduled (in the event loop of
212your choice).
213
214::
215
216
217Stream Reading and Writing
218==========================
219
220Reading from (or writing to) a stream is best down when that stream is
221readable (or writeable).  To register an interest in an event,
222