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