xref: /freebsd/crypto/openssl/doc/man7/ossl-guide-quic-server-non-block.pod (revision e7be843b4a162e68651d3911f0357ed464915629)
1=pod
2
3=begin comment
4
5NB: Changes to the source code samples in this file should also be reflected in
6demos/guide/quic-server-non-block.c
7
8=end comment
9
10=head1 NAME
11
12ossl-guide-quic-server-non-block
13- OpenSSL Guide: Writing a simple nonblocking QUIC server
14
15=head1 SIMPLE NONBLOCKING QUIC SERVER EXAMPLE
16
17This page presents various source code samples demonstrating how to write a
18simple, non-concurrent, QUIC "echo" server application which accepts one client
19connection at a time, echoing input from the client back to the same client.
20Once the current client disconnects, the next client connection is accepted.
21
22The server only accepts C<http/1.0> and C<hq-interop> ALPN's and doesn't actually
23implement HTTP but only does a simple echo.  This is non-standard and will not
24be supported by real world servers.  This is for demonstration purposes only.
25
26There are various methods to test this server: B<quic-client-block.c> and
27B<quic-client-non-block.c> will send a basic HTTP/1.0 request, which the server
28will echo back.  You can also test this server by running
29C<openssl s_client -connect localhost:4443 -4 -quic -alpn http/1.0> and entering
30text that will be echoed back by the server.
31
32Both the listening socket and connected socket are "nonblocking".  However,
33we use select() to make the listening socket block when it cannot read/write.
34Rather than stopping and waiting, your application may need to go and do other
35tasks whilst the B<SSL> object is unable to read/write.  For example: updating a
36GUI or performing operations on some other connection or stream.
37
38The complete source code for this example nonblocking QUIC server is available
39in the B<demos/guide> directory of the OpenSSL source distribution in the file
40B<quic-server-non-block.c>.  It is also available online at
41L<https://github.com/openssl/openssl/blob/master/demos/guide/quic-server-non-block.c>.
42
43We assume that you already have OpenSSL installed on your system; that you
44already have some fundamental understanding of OpenSSL concepts and QUIC (see
45L<ossl-guide-libraries-introduction(7)> and L<ossl-guide-quic-introduction(7)>);
46and that you know how to write and build C code and link it against the
47libcrypto and libssl libraries that are provided by OpenSSL.  It also assumes
48that you have a basic understanding of UDP/IP and sockets.
49
50=head2 Creating the SSL_CTX and SSL objects
51
52The first step is to create an B<SSL_CTX> object for our server.  We use the
53L<SSL_CTX_new(3)> function for this purpose.  We pass as an argument the return
54value of the function L<OSSL_QUIC_server_method(3)>.  You should use this method
55whenever you are writing a QUIC server.
56
57    /*
58     * An SSL_CTX holds shared configuration information for multiple
59     * subsequent per-client SSL connections. We specifically load a QUIC
60     * server method here.
61     */
62    ctx = SSL_CTX_new(OSSL_QUIC_server_method());
63    if (ctx == NULL)
64        goto err;
65
66Servers need a private key and certificate.  Intermediate issuer CA
67certificates are often required, and both the server (end-entity or EE)
68certificate and the issuer ("chain") certificates are most easily configured in
69a single "chain file".  Below we load such a chain file (the EE certificate
70must appear first), and then load the corresponding private key, checking that
71it matches the server certificate.  No checks are performed to check the
72integrity of the chain (CA signatures or certificate expiration dates, for
73example), but we do verify the consistency of the private key with the
74corresponding certificate.
75
76    /*
77     * Load the server's certificate *chain* file (PEM format), which includes
78     * not only the leaf (end-entity) server certificate, but also any
79     * intermediate issuer-CA certificates.  The leaf certificate must be the
80     * first certificate in the file.
81     *
82     * In advanced use-cases this can be called multiple times, once per public
83     * key algorithm for which the server has a corresponding certificate.
84     * However, the corresponding private key (see below) must be loaded first,
85     * *before* moving on to the next chain file.
86     */
87    if (SSL_CTX_use_certificate_chain_file(ctx, cert_path) <= 0) {
88        fprintf(stderr, "couldn't load certificate file: %s\n", cert_path);
89        goto err;
90    }
91
92    /*
93     * Load the corresponding private key, this also checks that the private
94     * key matches the just loaded end-entity certificate.  It does not check
95     * whether the certificate chain is valid, the certificates could be
96     * expired, or may otherwise fail to form a chain that a client can
97     * validate.
98     */
99    if (SSL_CTX_use_PrivateKey_file(ctx, key_path, SSL_FILETYPE_PEM) <= 0) {
100        fprintf(stderr, "couldn't load key file: %s\n", key_path);
101        goto err;
102    }
103
104Most servers, including this one, do not solicit client certificates.  We
105therefore do not need a "trust store" and allow the handshake to complete even
106when the client does not present a certificate.  Note: Even if a client did
107present a trusted certificate, for it to be useful, the server application
108would still need custom code to use the verified identity to grant nondefault
109access to that particular client.  Some servers grant access to all clients
110with certificates from a private CA, this then requires processing of
111certificate revocation lists to deauthorise a client.  It is often simpler and
112more secure to instead keep a list of authorised public keys.
113
114Though this is the default setting, we explicitly call the
115L<SSL_CTX_set_verify(3)> function and pass the B<SSL_VERIFY_NONE> value to it.
116The final argument to this function is a callback that you can optionally
117supply to override the default handling for certificate verification.  Most
118applications do not need to do this so this can safely be set to NULL to get
119the default handling.
120
121    /*
122     * Clients rarely employ certificate-based authentication, and so we don't
123     * require "mutual" TLS authentication (indeed there's no way to know
124     * whether or how the client authenticated the server, so the term "mutual"
125     * is potentially misleading).
126     *
127     * Since we're not soliciting or processing client certificates, we don't
128     * need to configure a trusted-certificate store, so no call to
129     * SSL_CTX_set_default_verify_paths() is needed.  The server's own
130     * certificate chain is assumed valid.
131     */
132    SSL_CTX_set_verify(ctx, SSL_VERIFY_NONE, NULL);
133
134
135QUIC also dictates using Application-Layer Protocol Negotiation (ALPN) to select
136an application protocol.  We use L<SSL_CTX_set_alpn_select_cb(3)> for this
137purpose.  We can pass a callback which will be called for each connection to
138select an ALPN the server considers acceptable.
139
140    /* Setup ALPN negotiation callback to decide which ALPN is accepted. */
141    SSL_CTX_set_alpn_select_cb(ctx, select_alpn, NULL);
142
143In this case, we only accept "http/1.0" and "hq-interop".
144
145    /*
146    * ALPN strings for TLS handshake. Only 'http/1.0' and 'hq-interop'
147    * are accepted.
148    */
149    static const unsigned char alpn_ossltest[] = {
150        8,  'h', 't', 't', 'p', '/', '1', '.', '0',
151        10, 'h', 'q', '-', 'i', 'n', 't', 'e', 'r', 'o', 'p',
152    };
153
154    static int select_alpn(SSL *ssl, const unsigned char **out,
155                           unsigned char *out_len, const unsigned char *in,
156                           unsigned int in_len, void *arg)
157    {
158        if (SSL_select_next_proto((unsigned char **)out, out_len, alpn_ossltest,
159                                  sizeof(alpn_ossltest), in,
160                                  in_len) == OPENSSL_NPN_NEGOTIATED)
161            return SSL_TLSEXT_ERR_OK;
162        return SSL_TLSEXT_ERR_ALERT_FATAL;
163    }
164
165That is all the setup that we need to do for the B<SSL_CTX>.  Next, we create a
166UDP socket and bind to it on localhost.
167
168    /* Retrieve the file descriptor for a new UDP socket */
169    if ((fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0) {
170        fprintf(stderr, "cannot create socket");
171        return -1;
172    }
173
174    sa.sin_family = AF_INET;
175    sa.sin_port = htons(port);
176
177    /* Bind to the new UDP socket on localhost */
178    if (bind(fd, (const struct sockaddr *)&sa, sizeof(sa)) < 0) {
179        fprintf(stderr, "cannot bind to %u\n", port);
180        BIO_closesocket(fd);
181        return -1;
182    }
183
184    /* Set port to nonblocking mode */
185    if (BIO_socket_nbio(fd, 1) <= 0) {
186        fprintf(stderr, "Unable to set port to nonblocking mode");
187        BIO_closesocket(fd);
188        return -1;
189    }
190
191To run the QUIC server, we create an B<SSL_LISTENER> to listen for incoming
192connections.  We provide it with the bound UDP port to then explicitly begin
193listening for new connections.
194
195    /* Create a new QUIC listener */
196    if ((listener = SSL_new_listener(ctx, 0)) == NULL)
197        goto err;
198
199    /* Provide the listener with our UDP socket. */
200    if (!SSL_set_fd(listener, fd))
201        goto err;
202
203    /* Set the listener mode to nonblocking, which is inherited by
204     * child objects.
205     */
206    if (!SSL_set_blocking_mode(listener, 0))
207        goto err;
208
209    /*
210     * Begin listening. Note that is not usually needed as SSL_accept_connection
211     * will implicitly start listening. It is only needed if a server wishes to
212     * ensure it has started to accept incoming connections but does not wish to
213     * actually call SSL_accept_connection yet.
214     */
215    if (!SSL_listen(listener))
216        goto err;
217
218=head2 Server loop
219
220The server now enters a "forever" loop, handling one client connection at a
221time.  Before each connection, we clear the OpenSSL error stack so that any
222error reports are related to just the new connection.
223
224    /* Pristine error stack for each new connection */
225    ERR_clear_error();
226
227We then wait until a connection is ready for reading.
228It uses the select function to wait until the socket is either readable
229or writable, depending on what the SSL connection requires.
230
231We then accept a new connection in which the handshake will have already
232occurred. However, since we are in nonblocking mode, L<SSL_accept_connection(3)>
233will return immediately. Therefore, we use a helper function to essentially
234block until a connection is established.
235
236    printf("Waiting for connection\n");
237    while ((conn = SSL_accept_connection(listener, 0)) == NULL) {
238        wait_for_activity(listener);
239    }
240    printf("Accepted new connection\n");
241
242The helper function wait_for_activity uses select() to block until the file
243descriptor belonging to the passed SSL object is readable. As mentioned earlier,
244a more real-world application would likely use this time to perform other tasks.
245
246    /* Initialize the fd_set structure */
247    FD_ZERO(&read_fd);
248    FD_ZERO(&write_fd);
249
250    /*
251     * Determine if we would like to write to the socket, read from it, or both.
252     */
253    if (SSL_net_write_desired(ssl))
254        FD_SET(sock, &write_fd);
255    if (SSL_net_read_desired(ssl))
256        FD_SET(sock, &read_fd);
257
258    /*
259     * Find out when OpenSSL would next like to be called, regardless of
260     * whether the state of the underlying socket has changed or not.
261     */
262    if (SSL_get_event_timeout(ssl, &tv, &isinfinite) && !isinfinite)
263        tvp = &tv;
264
265    /*
266     * Wait until the socket is writeable or readable. We use select here
267     * for the sake of simplicity and portability, but you could equally use
268     * poll/epoll or similar functions
269     *
270     * NOTE: For the purposes of this demonstration code this effectively
271     * makes this demo block until it has something more useful to do. In a
272     * real application you probably want to go and do other work here (e.g.
273     * update a GUI, or service other connections).
274     *
275     * Let's say for example that you want to update the progress counter on
276     * a GUI every 100ms. One way to do that would be to use the timeout in
277     * the last parameter to "select" below. If the tvp value is greater
278     * than 100ms then use 100ms instead. Then, when select returns, you
279     * check if it did so because of activity on the file descriptors or
280     * because of the timeout. If the 100ms GUI timeout has expired but the
281     * tvp timeout has not then go and update the GUI and then restart the
282     * "select" (with updated timeouts).
283     */
284
285    select(sock + 1, &read_fd, &write_fd, NULL, tvp);
286
287With the handshake complete, the server reads all the client input.
288
289    /* Read from client until the client sends a end of stream packet */
290    while (!eof) {
291        ret = SSL_read_ex(conn, buf + total_read, sizeof(buf) - total_read,
292                          &nread);
293        total_read += nread;
294        if (total_read >= 8192) {
295            fprintf(stderr, "Could not fit all data into buffer\n");
296            goto err;
297        }
298        switch (handle_io_failure(conn, ret)) {
299        case 1:
300            continue; /* Retry */
301        case 0:
302            /* Reached end of stream */
303            if (!SSL_has_pending(conn))
304                eof = 1;
305            break;
306        default:
307            fprintf(stderr, "Failed reading remaining data\n");
308            goto err;
309        }
310    }
311
312Finally, we echo the received data back to the client.  We can use
313L<SSL_write_ex2(3)> to pass in a special flag SSL_WRITE_FLAG_CONCLUDE that will
314send a FIN packet once the write has successfully finished writing all the data
315to the peer.
316
317    /* Echo client input */
318    while (!SSL_write_ex2(conn, buf,
319                          total_read,
320                          SSL_WRITE_FLAG_CONCLUDE, &total_written)) {
321        if (handle_io_failure(conn, 0) == 1)
322            continue;
323        fprintf(stderr, "Failed to write data\n");
324        goto err;
325    }
326
327We then shut down the connection with L<SSL_shutdown(3)>, which may need
328to be called multiple times to ensure the connection is shutdown completely.
329
330    /*
331     * Shut down the connection. We may need to call this multiple times
332     * to ensure the connection is shutdown completely.
333     */
334    while ((ret = SSL_shutdown(conn)) != 1) {
335        if (ret < 0 && handle_io_failure(conn, ret) == 1)
336            continue; /* Retry */
337    }
338
339Finally, we free the SSL connection, and the server is now ready to accept the
340next client connection.
341
342    SSL_free(conn);
343
344=head2 Final clean up
345
346If the server somehow manages to break out of the infinite loop and
347be ready to exit, it would deallocate the constructed B<SSL>.
348
349    SSL_free(listener);
350
351And in the main function, it would deallocate the constructed B<SSL_CTX>.
352
353    SSL_CTX_free(ctx);
354    BIO_closesocket(fd);
355
356=head1 SEE ALSO
357
358L<ossl-guide-introduction(7)>, L<ossl-guide-libraries-introduction(7)>,
359L<ossl-guide-libssl-introduction(7)>, L<ossl-guide-quic-introduction(7)>,
360L<ossl-guide-quic-client-non-block(7)>, L<ossl-guide-quic-client-block(7)>,
361L<ossl-guide-tls-server-block(7)>, L<ossl-guide-quic-server-block(7)>
362
363=head1 COPYRIGHT
364
365Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved.
366
367Licensed under the Apache License 2.0 (the "License").  You may not use
368this file except in compliance with the License.  You can obtain a copy
369in the file LICENSE in the source distribution or at
370L<https://www.openssl.org/source/license.html>.
371
372=cut
373