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