Home | History | Annotate | Line # | Download | only in man7
      1 =pod
      2 
      3 =begin comment
      4 
      5 NB: Changes to the source code samples in this file should also be reflected in
      6 demos/guide/quic-server-non-block.c
      7 
      8 =end comment
      9 
     10 =head1 NAME
     11 
     12 ossl-guide-quic-server-non-block
     13 - OpenSSL Guide: Writing a simple nonblocking QUIC server
     14 
     15 =head1 SIMPLE NONBLOCKING QUIC SERVER EXAMPLE
     16 
     17 This page presents various source code samples demonstrating how to write a
     18 simple, non-concurrent, QUIC "echo" server application which accepts one client
     19 connection at a time, echoing input from the client back to the same client.
     20 Once the current client disconnects, the next client connection is accepted.
     21 
     22 The server only accepts C<http/1.0> and C<hq-interop> ALPN's and doesn't actually
     23 implement HTTP but only does a simple echo.  This is non-standard and will not
     24 be supported by real world servers.  This is for demonstration purposes only.
     25 
     26 There are various methods to test this server: B<quic-client-block.c> and
     27 B<quic-client-non-block.c> will send a basic HTTP/1.0 request, which the server
     28 will echo back.  You can also test this server by running
     29 C<openssl s_client -connect localhost:4443 -4 -quic -alpn http/1.0> and entering
     30 text that will be echoed back by the server.
     31 
     32 Both the listening socket and connected socket are "nonblocking".  However,
     33 we use select() to make the listening socket block when it cannot read/write.
     34 Rather than stopping and waiting, your application may need to go and do other
     35 tasks whilst the B<SSL> object is unable to read/write.  For example: updating a
     36 GUI or performing operations on some other connection or stream.
     37 
     38 The complete source code for this example nonblocking QUIC server is available
     39 in the B<demos/guide> directory of the OpenSSL source distribution in the file
     40 B<quic-server-non-block.c>.  It is also available online at
     41 L<https://github.com/openssl/openssl/blob/master/demos/guide/quic-server-non-block.c>.
     42 
     43 We assume that you already have OpenSSL installed on your system; that you
     44 already have some fundamental understanding of OpenSSL concepts and QUIC (see
     45 L<ossl-guide-libraries-introduction(7)> and L<ossl-guide-quic-introduction(7)>);
     46 and that you know how to write and build C code and link it against the
     47 libcrypto and libssl libraries that are provided by OpenSSL.  It also assumes
     48 that you have a basic understanding of UDP/IP and sockets.
     49 
     50 =head2 Creating the SSL_CTX and SSL objects
     51 
     52 The first step is to create an B<SSL_CTX> object for our server.  We use the
     53 L<SSL_CTX_new(3)> function for this purpose.  We pass as an argument the return
     54 value of the function L<OSSL_QUIC_server_method(3)>.  You should use this method
     55 whenever 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 
     66 Servers need a private key and certificate.  Intermediate issuer CA
     67 certificates are often required, and both the server (end-entity or EE)
     68 certificate and the issuer ("chain") certificates are most easily configured in
     69 a single "chain file".  Below we load such a chain file (the EE certificate
     70 must appear first), and then load the corresponding private key, checking that
     71 it matches the server certificate.  No checks are performed to check the
     72 integrity of the chain (CA signatures or certificate expiration dates, for
     73 example), but we do verify the consistency of the private key with the
     74 corresponding 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 
    104 Most servers, including this one, do not solicit client certificates.  We
    105 therefore do not need a "trust store" and allow the handshake to complete even
    106 when the client does not present a certificate.  Note: Even if a client did
    107 present a trusted certificate, for it to be useful, the server application
    108 would still need custom code to use the verified identity to grant nondefault
    109 access to that particular client.  Some servers grant access to all clients
    110 with certificates from a private CA, this then requires processing of
    111 certificate revocation lists to deauthorise a client.  It is often simpler and
    112 more secure to instead keep a list of authorised public keys.
    113 
    114 Though this is the default setting, we explicitly call the
    115 L<SSL_CTX_set_verify(3)> function and pass the B<SSL_VERIFY_NONE> value to it.
    116 The final argument to this function is a callback that you can optionally
    117 supply to override the default handling for certificate verification.  Most
    118 applications do not need to do this so this can safely be set to NULL to get
    119 the 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 
    135 QUIC also dictates using Application-Layer Protocol Negotiation (ALPN) to select
    136 an application protocol.  We use L<SSL_CTX_set_alpn_select_cb(3)> for this
    137 purpose.  We can pass a callback which will be called for each connection to
    138 select 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 
    143 In 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 
    165 That is all the setup that we need to do for the B<SSL_CTX>.  Next, we create a
    166 UDP 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 
    191 To run the QUIC server, we create an B<SSL_LISTENER> to listen for incoming
    192 connections.  We provide it with the bound UDP port to then explicitly begin
    193 listening 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 
    220 The server now enters a "forever" loop, handling one client connection at a
    221 time.  Before each connection, we clear the OpenSSL error stack so that any
    222 error reports are related to just the new connection.
    223 
    224     /* Pristine error stack for each new connection */
    225     ERR_clear_error();
    226 
    227 We then wait until a connection is ready for reading.
    228 It uses the select function to wait until the socket is either readable
    229 or writable, depending on what the SSL connection requires.
    230 
    231 We then accept a new connection in which the handshake will have already
    232 occurred. However, since we are in nonblocking mode, L<SSL_accept_connection(3)>
    233 will return immediately. Therefore, we use a helper function to essentially
    234 block 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 
    242 The helper function wait_for_activity uses select() to block until the file
    243 descriptor belonging to the passed SSL object is readable. As mentioned earlier,
    244 a 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 
    287 With 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 
    312 Finally, we echo the received data back to the client.  We can use
    313 L<SSL_write_ex2(3)> to pass in a special flag SSL_WRITE_FLAG_CONCLUDE that will
    314 send a FIN packet once the write has successfully finished writing all the data
    315 to 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 
    327 We then shut down the connection with L<SSL_shutdown(3)>, which may need
    328 to 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 
    339 Finally, we free the SSL connection, and the server is now ready to accept the
    340 next client connection.
    341 
    342     SSL_free(conn);
    343 
    344 =head2 Final clean up
    345 
    346 If the server somehow manages to break out of the infinite loop and
    347 be ready to exit, it would deallocate the constructed B<SSL>.
    348 
    349     SSL_free(listener);
    350 
    351 And 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 
    358 L<ossl-guide-introduction(7)>, L<ossl-guide-libraries-introduction(7)>,
    359 L<ossl-guide-libssl-introduction(7)>, L<ossl-guide-quic-introduction(7)>,
    360 L<ossl-guide-quic-client-non-block(7)>, L<ossl-guide-quic-client-block(7)>,
    361 L<ossl-guide-tls-server-block(7)>, L<ossl-guide-quic-server-block(7)>
    362 
    363 =head1 COPYRIGHT
    364 
    365 Copyright 2024-2025 The OpenSSL Project Authors. All Rights Reserved.
    366 
    367 Licensed under the Apache License 2.0 (the "License").  You may not use
    368 this file except in compliance with the License.  You can obtain a copy
    369 in the file LICENSE in the source distribution or at
    370 L<https://www.openssl.org/source/license.html>.
    371 
    372 =cut
    373