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