xref: /freebsd/crypto/openssl/doc/designs/quic-design/server/quic-server-api.md (revision e7be843b4a162e68651d3911f0357ed464915629)
1QUIC Server API Design
2======================
3
4Requirements
5------------
6
7Essential:
8
9- Support server mode.
10- Support multiple clients on one UDP socket/BIO.
11- Accept incoming clients and get a `SSL *` object which works just like a
12  client QCSO.
13
14Maybe:
15
16- Binding multiple BIOs (UDP sockets) to one listener?
17
18Implied:
19
20- Support connection migration and preferred addressing in the future.
21- Maximise reuse of existing APIs.
22
23Approach
24--------
25
26Two design sketches are shown below, their relative merits are evaluated, and
27one is chosen.
28
29Sketch A: `SSL_LISTENER`
30------------------------
31
32A new type `SSL_LISTENER` is introduced to the public API. This represents an
33entity which listens for incoming connections. It is **not** intended to be QUIC
34specific and provides an abstract interface which could be adapted to other
35cases in the future. For example, it could be used for TLS over TCP to make
36accepting incoming TCP connections easy.
37
38Internally, an `SSL_LISTENER` has a common header in much the same way that
39`SSL` objects now do. For example, if called using a QUIC `SSL_CTX`, the
40internal structure might be a `QUIC_LISTENER`, etc. If called using a TLS
41`SSL_CTX`, this might be a `TCP_LISTENER` doing something very ordinary. We can
42support DTLS in the future in the same way as QUIC, etc.
43
44Internally, an `SSL_LISTENER` stores any common state that needs to be held
45collectively for all connections created by that listener.
46
47`SSL_LISTENER` objects are refcounted and referenced by any connection which
48descends from them. Thus, an application may free the `SSL_LISTENER`, but
49it will be retained until it is no longer depended on by any connection.
50
51The operation of an `SSL_LISTENER` is simple: call
52`SSL_LISTENER_accept_connection`. For QUIC, this returns a new QCSO, which is
53considered a child of the listener.
54
55```c
56SSL_LISTENER *SSL_LISTENER_new(SSL_CTX *ctx, BIO *net_rbio, BIO *net_wbio);
57int SSL_LISTENER_up_ref(SSL_LISTENER *l);
58int SSL_LISTENER_free(SSL_LISTENER *l);
59
60BIO *SSL_LISTENER_get0_net_rbio(SSL_LISTENER *l);
61BIO *SSL_LISTENER_get0_net_wbio(SSL_LISTENER *l);
62int SSL_LISTENER_set1_net_rbio(SSL_LISTENER *l, BIO *net_rbio);
63int SSL_LISTENER_set1_net_wbio(SSL_LISTENER *l, BIO *net_wbio);
64
65SSL *SSL_LISTENER_accept_connection(SSL_LISTENER *l, uint64_t flags);
66size_t SSL_LISTENER_get_accept_queue_len(SSL_LISTENER *l);
67```
68
69### Discussion
70
71However, there are a number of disadvantages to introducing a new object type.
72The concept of a listener shares many of the same concepts inherent to
73supporting non-blocking network I/O which our SSL API for QUIC connections has
74been carefully designed to support:
75
76- Poll descriptors (`SSL_get_[rw]poll_descriptor`);
77- `SSL_net_(read|write)_desired`;
78- `SSL_handle_events`;
79- `SSL_get_event_timeout`;
80- BIO configuration (`SSL_set_[rw]bio`);
81- Refcounting (`SSL_up_ref`, `SSL_free`).
82
83We would need to duplicate all of these APIs. Moreover application developers
84would need to use both and the distinction between the two would become
85confusing.
86
87Sketch B: New SSL Object Type: Listener
88---------------------------------------
89
90Instead of the above, the definition of a new SSL object subtype — a Listener —
91is proposed. A QLSO (QUIC Listener SSL Object) is defined in much the same way
92that QCSOs and QSSOs are currently defined, using the common SSL structure
93header.
94
95Many existing APIs around the handling of non-blocking I/O can then be supported
96and work in exactly the same way.
97
98```c
99/*
100 * SSL_new_listener
101 * ----------------
102 *
103 * Creates a QLSO, assuming a QUIC SSL_CTX.
104 *
105 * TCP and DTLS can be supported in the future; not supported for non-QUIC
106 * SSL_CTXs for now.
107 */
108SSL *SSL_new_listener(SSL_CTX *ctx, uint64_t flags);
109
110/*
111 * A QLSO supports the following existing APIs:
112 *
113 *   - Poll descriptors (`SSL_get_[rw]poll_descriptor`)
114 *   - `SSL_net_(read|write)_desired`
115 *   - `SSL_handle_events`
116 *   - `SSL_get_event_timeout`
117 *   - BIO configuration (`SSL_set_[rw]bio`)
118 *   - Refcounting (`SSL_up_ref`, `SSL_free`)
119 */
120
121/*
122 * New API for QLSOs: SSL_accept_connection
123 * ----------------------------------------
124 *
125 * These APIs are exactly the same as  SSL_accept_stream, but made a separate
126 * function to avoid confusion. Supported on QLSOs only.
127 */
128SSL *SSL_accept_connection(SSL *ssl, uint64_t flags);
129size_t SSL_get_accept_connection_queue_len(SSL *ssl);
130
131/*
132 * New API for QLSOs: SSL_listen
133 * -----------------------------
134 *
135 * This is not usually needed as SSL_accept_connection will implicitly trigger
136 * this if it has not been called yet. It is only needed if a server wishes to
137 * ensure it has started to accept incoming connections but does not wish to
138 * actually call SSL_accept_connection yet. In this regard it is similar to
139 * listen(2).
140 */
141int SSL_listen(SSL *ssl);
142
143/*
144 * New API for QCSOs: SSL_get_peer_addr
145 * ------------------------------------
146 *
147 * An API to retrieve a L4 peer address. Supported on QCSOs only.
148 */
149int SSL_get_peer_addr(SSL *ssl, BIO_ADDR *peer_addr);
150
151/* SSL_get_local_addr may be introduced once it is relevant (migration etc.) */
152
153/* Returns 1 for QLSOs (or future TLS/DTLS listeners) only. */
154int SSL_is_listener(SSL *ssl);
155
156/* Returns the QLSO (if any) from which a QCSO or QSSO is descended. */
157SSL *SSL_get0_listener(SSL *ssl);
158
159/* SSL_is_quic returns 1 */
160```
161
162Selection of Design
163-------------------
164
165We could also consider using an `SSL_CTX` as the listener type. Since a
166`SSL_CTX` is intended to span the lifespan of multiple TLS connections there is
167a degree of logic here. However, this does not match up naturally because an
168`SSL_CTX` is not designed to hold network resources or manage network I/O. It
169does not have the facilities for polling and event handling that the `SSL`
170object API has been enhanced with. It would also be a fairly major paradigm
171shift for existing server applications and make things difficult if a server
172wanted to use different `SSL_CTX` instances to use different e.g. TLS settings
173within the same listener.
174
175Based on the merits of the above, Sketch B is chosen for adoption.
176
177Discussion of Relevant Issues
178-----------------------------
179
180### Notes on Internal Refactoring to Support Multiple Connections
181
182Currently a client connection is a QCSO
183(`QUIC_CONNECTION`) which contains a `QUIC_CHANNEL`. The `QUIC_CONNECTION`
184provides API Personality Layer (APL) implementation and wraps the APL-agnostic
185`QUIC_CHANNEL`. We currently have two APLs, the libssl API (“the” APL) and
186`QUIC_TSERVER` for internal testing use. `QUIC_XSO` is the APL object
187representing a QUIC stream and wraps our APL-agnostic channel-owned
188`QUIC_STREAM` object. There is no specific object in the `QUIC_TSERVER` APL for
189a stream as they are referenced in that API by stream ID only.
190
191`QUIC_CHANNEL` corresponds exactly to a QUIC connection. In a similar manner,
192`QUIC_STREAM` corresponds exactly to a QUIC stream. In server operation,
193multiple `QUIC_CHANNEL` instances will exist, one per accepted connection.
194
195Above we introduce the notion of a QUIC Listener SSL Object (QLSO), which
196internally will be represented by the type `QUIC_LISTENER`. This forms a new
197object in the libssl APL.
198
199With server operation, multiple connections will share a single UDP
200socket/network BIO. Certain resources currently tied 1:1 into a `QUIC_CHANNEL`
201will be broken out, such as the network BIO pointers and `QUIC_DEMUX` instance.
202A `QUIC_CHANNEL` continues to own e.g. the QRX/QTX as these are
203connection-specific.
204
205Because preserving the separation of the APL(s) and the QUIC core is desirable,
206the concept of a `QUIC_PORT` is introduced. This is the internal object tracking
207a demux and network BIOs which a `QUIC_CHANNEL` will belong to. In other words,
208the new situation is as follows:
209
210| Abbr. | libssl APL Object | QUIC Core Object |
211|-------|-------------------|------------------|
212| QLSO  | `QUIC_LISTENER`   | `QUIC_PORT`      |
213| QCSO  | `QUIC_CONNECTION` | `QUIC_CHANNEL`   |
214| QSSO  | `QUIC_XSO`        | `QUIC_STREAM`    |
215
216### Listener Flexibility
217
218A listener allows multiple connections to be received on a UDP socket. However,
219there is no intrinsic requirement in QUIC that a socket only be used for client
220use, or only for server use. Therefore, it should be possible for an application
221to create a QLSO, use it to accept connections, and also use it to initiate
222outgoing connections.
223
224This can be supported in a simple manner:
225
226```c
227SSL *SSL_new_from_listener(SSL *ssl);
228```
229
230This creates an unconnected (idle) QCSO from a QLSO. Use of
231`SSL_set1_initial_peer_addr` is mandatory in this case as peer address
232autodetection is inhibited.
233
234The created QCSO otherwise works in a completely normal fashion.
235
236### Client-Only Listeners
237
238In fact, the realisation of this hybrid capability is simply an emergent
239consequence of our internal refactor. Since a QUIC server will be split into an
240internal `QUIC_PORT` and zero or more `QUIC_CONNECTION` instances, so too will a
241client connection become simply a degenerate case where there is a `QUIC_PORT`
242and only one `QUIC_CONNECTION`. So the client case basically just becomes a
243simplified API where we spin up a `QUIC_PORT`/listener automatically to support
244a single connection.
245
246It is potentially desirable for a client to be able to use the listener
247API even if it is only initiating connections as a client and never accepting
248connections. There are several reasons why an application might want to do this:
249
250- it allows the application to centralise its I/O polling and networking arrangements;
251- it allows the application to handle the TERMINATING phase of connections in a
252  better (and more RFC-compliant) way.
253
254For the latter reason, consider how connection termination works. Once a QUIC
255Immediate Close is initiated using a `CONNECTION_CLOSE` frame, a connection
256enters the `TERMINATING` state and is expected to stay there for some period of
257time until the possibility of various contingencies (such as loss of a
258`CONNECTION_CLOSE` frame and its necessary retransmission) has been accounted
259for. However, many applications may not wish to hang around for potentially
260several seconds or longer while tearing down a QUIC connection.
261
262Allowing clients to use a listener resolves this problem, if the lifetime of the
263application exceeds the lifetime of most client connections. The listener can
264continue to hold the `QUIC_PORT` internally and respond to enquiries for
265terminating and terminated connections, even if (as far as the application is
266concerned) no client connections currently exist and all prior client
267connections have been freed using `SSL_free`. The internal `QUIC_CHANNEL` can be
268kept around by the `QUIC_PORT` until it reaches the `TERMINATED` state.
269
270A client-only listener can be created one of two ways:
271
2721. by calling `SSL_new_listener` while passing this flag:
273
274    ```
275    #define SSL_LISTENER_FLAG_NO_ACCEPT  (1U << 0)
276    ```
277
2782. by using a client `SSL_METHOD`, which implies `NO_ACCEPT`.
279
280This flag simply indicates that this listener is not to be used to accept
281incoming connections. A client can then use `SSL_new_from_listener` as usual to
282create an outgoing QCSO.
283
284### CID Length Determination
285
286Currently a client connection uses a zero-length local CID. Since we want to
287support multiple outgoing client connections on one socket these will need to
288support a non-zero-length local CID. Equally servers will need to support CIDs.
289
290By default when a QLSO is used, we will use a real, non-zero-length CID. If the
291existing QUIC client API is used (with no QLSO) we will likely spin up a
292`QUIC_PORT` internally but specially choose to use a zero-length local CID since
293we know this port will never be used for more than one connection.
294
295If an application creates a QLSO explicitly but knows it will not need to
296create more than one connection, it can pass the following flag when creating
297the listener:
298
299```c
300#define SSL_LISTENER_FLAG_SINGLE_CONN   (1U << 1)
301```
302
303Failure to do so is nonfatal and simply increases packet overheads.
304
305### Future Compatibility: TLS over TCP Support
306
307Assuming we choose to use the SSL object type as the basis of a new listener
308object type, let us consider how this API could also be used to support TLS over
309TCP, at least in a server role:
310
311```c
312/* Blocking example: */
313{
314    SSL *l, *conn;
315    BIO *tcp_listener = get_bio_sock_for_listening_tcp_socket();
316    SSL_CTX *ctx = create_ssl_ctx(TLS_server_method());
317    BIO_ADDR addr;
318
319    l = SSL_new_listener(ctx);
320    SSL_set_bio(l, tcp_listener, tcp_listener);
321
322    for (;;) {
323        /* standard SSL_CONNECTION is returned */
324        conn = SSL_accept_connection(l, 0);
325
326        spawn_thread_to_process_conn(conn, &addr);
327    }
328}
329```
330
331Essentially, when `SSL_new_listener` is given a `SSL_CTX` which is using a TLS
332method, it returns some different kind of object, say a `TCP_LISTENER`, which
333also is a kind of SSL object. `SSL_accept_connection` calls `accept(2)` via some
334BIO abstraction on the provided BIO, and constructs a new BIO on the resulting
335socket, wrapping it via standard `SSL_new` using the same `SSL_CTX`.
336
337Thus, this API should be compatible with any future adaptation to also support
338TCP.
339
340### Future Compatibility: DTLS over UDP Support
341
342The relevant concerns regarding DTLS are likely to be highly similar to QUIC,
343so this API should also be adaptable to support DTLS in the future, providing
344a unified server-side API. `SSL_new_listener` will return e.g. a
345`DTLS_LISTENER`.
346
347### Supporting Multiple Sockets
348
349There are three means that we can provide to support a server which wants to
350listen on multiple UDP sockets:
351
3521. Allow a QLSO to bind multiple BIOs;
3532. Create multiple QLSOs and use some polling mechanism to service all of them;
3543. Create some higher level object which can aggregate multiple QLSOs.
355
356(1) would require more extensive API changes and should only be done if a
357compelling reason to do so arises. (3) is a more advanced design which is
358theoretically possible in future and is discussed in the next section.
359For now, we will support only (2) (which we can support via our planned polling
360API) until a compelling need arises.
361
362### Roles and Domains: Concepts and Future Evolution
363
364A client can use QUIC using a single QCSO without ever creating a QLSO.
365Conversely a client or server can use QUIC by creating a QLSO and then one or
366more subsidiary QCSOs. This implies that, at least in terms of the publicly
367visible API, the roles of certain essential aspects of QUIC can belong to
368different publicly visible API objects.
369
370The following concepts are introduced:
371
372- **Port Leader:** A Port Leader is the APL object which caused the creation
373  of a `QUIC_PORT`, which is responsible for servicing a particular pair
374  of network BIOs. Currently maps to one UDP socket.
375
376  In the simple client API, the QCSO is the port leader.
377  In a client using a QLSO, the QLSO is the port leader.
378  In a server, the QLSO is the port leader.
379
380- **Event Leader:** An Event Leader is the APL object which handles event
381  processing. Calls to SSL_handle_events() for any subsidiary object is
382  equivalent to a call to SSL_handle_events() on the Event Leader, which handles
383  state machine processing for that object and all subsidiary objects.
384
385  The event leader is the highest-level APL object in a QUIC APL object
386  hierarchy:
387
388  In the simple client API, the QCSO is the event leader.
389  In a client using a QLSO, the QLSO is the event leader.
390  In a server, the QLSO is the event leader.
391
392- **Domain:** A QUIC domain is a set of APL objects rooted in an Event Leader.
393  In other words, requests to handle events on subsidiary objects in a domain
394  are channeled up to the Event Leader and processed there. A QUIC domain is a
395  set of logically grouped QUIC objects which share a single I/O reactor and
396  event processing context.
397
398  A domain could contain multiple QLSOs (i.e., multiple UDP sockets) in future.
399  In this case QLSOs may cease to be the most senior APL object type and there
400  may be some new hypothetical SSL_new_quic_domain() call.
401
402  However, there is no plan to implement domains at this time; for the time
403  being, this is purely conceptual and ensures our architecture can grow to
404  supporting multiple sockets and listeners in a given QUIC context if need be.
405
406  If ever implemented, a domain will be reified by a `QUIC_DOMAIN` structure as
407  part of the APL and a `QUIC_ENGINE` structure as part of the QUIC core. The
408  SSL object type will be abbreviated QDSO (QUIC Domain SSL Object).
409
410The introduction of the concept of a domain demonstrates the value of the Port
411Leader and Domain Leader concepts going forward:
412
413Example 1 — Explicitly Created Domain:
414
415```text
416QDSO (QUIC_DOMAIN/QUIC_ENGINE)              Event Leader
417    QLSO (QUIC_LISTENER/QUIC_PORT)          Port Leader
418        QCSO (QUIC_CONNECTION/QUIC_CHANNEL)
419            QSSO (QUIC_XSO/QUIC_STREAM)
420```
421
422Example 2 - Explicitly Created QLSO, Implicitly Created Domain:
423
424```text
425QLSO (QUIC_LISTENER/QUIC_PORT)              Event Leader, Port Leader
426    [QUIC_ENGINE]
427    QCSO (QUIC_CONNECTION/QUIC_CHANNEL)
428        QSSO (QUIC_XSO/QUIC_STREAM)
429```
430
431Here we see that the QLSO now has the Event Leader role, as it is the most
432senior object visible publicly as a constructed API object. Note that a
433QUIC_ENGINE will be created internally to allow the QLSO to service the Event
434Leader role, but the corresponding QUIC_DOMAIN APL object will not exist, as
435this is not API-visible.
436
437Example 3 - Explicitly Created Single Client QCSO:
438
439```text
440QCSO (QUIC_CONNECTION/QUIC_CHANNEL)         Event Leader, Port Leader
441    [QUIC_ENGINE]
442    [QUIC_PORT]
443    QSSO (QUIC_XSO/QUIC_STREAM)
444```
445
446Here we see that the QCSO now has the Port Leader role. Note that a QUIC_PORT
447will be created internally to allow the QCSO to service the Port Leader role,
448but the corresponding QUIC_LISTENER APL object will not exist, as this is not
449API-visible. Similarly a QUIC_ENGINE is spun up to handle the Event Leader role,
450as above.
451
452It should be emphasised that everything in this section is largely academic and
453intended to demonstrate potential future directions and the adaptability of the
454design to future evolution. There is no immediate plan to implement a QDSO
455object type in the APL. However it will be viable to do so if we want to support
456multiple sockets per domain someday.
457
458| Abbr. | libssl APL Object | QUIC Core Object | Seniority   | Potential Roles |
459|-------|-------------------|------------------|-------------|-----------------|
460| QDSO  | `QUIC_DOMAIN`     | `QUIC_ENGINE`    | 1 (Highest) | EL              |
461| QLSO  | `QUIC_LISTENER`   | `QUIC_PORT`      | 2           | EL PL           |
462| QCSO  | `QUIC_CONNECTION` | `QUIC_CHANNEL`   | 3           | EL PL           |
463| QSSO  | `QUIC_XSO`        | `QUIC_STREAM`    | 4           |                 |
464
465### Polling
466
467We will support polling all QUIC object types (QLSOs, QCSOs, QSSOs) using a new
468polling API. This is the subject of its own design and will be discussed in more
469detail in a separate design document.
470
471### Impact of `SSL_METHOD` selection
472
473The interaction of our various QCSO and QLSO construction APIs in the APL,
474and the choice of the `SSL_METHOD` for a `SSL_CTX`, must also be considered.
475The following interactions are chosen:
476
477```text
478SSL_new(QUIC_client_method)             → QCSO(Client)
479SSL_new(QUIC_client_thread_method)      → QCSO(Client)
480SSL_new(QUIC_server_method)             → (not supported; error)
481
482SSL_new_listener(QUIC_client_method)        → QLSO(Client)   (implicit NO_ACCEPT)
483SSL_new_listener(QUIC_client_thread_method) → QLSO(Client)   (implicit NO_ACCEPT)
484SSL_new_listener(QUIC_server_method)        → QLSO(Server + Client)
485
486SSL_new_from_listener(QUIC_client_method)           → QCSO (Client)
487SSL_new_from_listener(QUIC_client_thread_method)    → QCSO (Client)
488SSL_new_from_listener(QUIC_server_method)           → QCSO (Client)
489```
490
491Observations:
492
493- It makes no sense to try and make a single QCSO proactively as a server,
494  so this just results in an error.
495
496- A server QLSO can also make outgoing client connections.
497
498- By contrast, if a client `SSL_METHOD` is specified when creating a listener,
499  it is assumed to be uninterested in accepting connections and this implies the
500  `NO_ACCEPT` flag. In this regard the functionality of a server is a superset
501  of the functionality of a client.
502
503- `SSL_new_from_listener` always creates a client QCSO.
504
505- `SINGLE_CONN` is implied automatically only when calling `SSL_new` and not
506  using a QLSO.
507
508Usage Example
509-------------
510
511The following is a blocking example, where `SSL_accept_connection` waits until a
512new connection is available.
513
514```c
515{
516    SSL *l, *conn;
517    SSL_CTX *ctx = create_ssl_ctx(QUIC_server_method());
518    BIO *dgram_bio = get_dgram_bio();
519
520    l = SSL_new_listener(ctx);
521    SSL_set_bio(l, dgram_bio, dgram_bio);
522
523    for (;;) {
524        /* automatically starts and calls SSL_listen on first call */
525        conn = SSL_accept_connection(l, 0); /* standard QCSO is returned */
526
527        spawn_thread_to_process_conn(conn);
528    }
529}
530```
531
532In non-blocking mode, `SSL_accept_connection` will simply act in a non-blocking
533fashion and return immediately with NULL if no new incoming connection is
534available, just like `SSL_accept_stream`. The details of how polling and waiting
535for incoming stream events, and other events, will work will be discussed in the
536subsequent polling design document.
537