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-client-block.c
7
8=end comment
9
10=head1 NAME
11
12ossl-guide-quic-client-block
13- OpenSSL Guide: Writing a simple blocking QUIC client
14
15=head1 SIMPLE BLOCKING QUIC CLIENT EXAMPLE
16
17This page will present various source code samples demonstrating how to write
18a simple blocking QUIC client application which connects to a server, sends an
19HTTP/1.0 request to it, and reads back the response. Note that HTTP/1.0 over
20QUIC is non-standard and will not be supported by real world servers. This is
21for demonstration purposes only.
22
23We assume that you already have OpenSSL installed on your system; that you
24already have some fundamental understanding of OpenSSL concepts, TLS and QUIC
25(see L<ossl-guide-libraries-introduction(7)>, L<ossl-guide-tls-introduction(7)>
26and L<ossl-guide-quic-introduction(7)>); and that you know how to
27write and build C code and link it against the libcrypto and libssl libraries
28that are provided by OpenSSL. It also assumes that you have a basic
29understanding of UDP/IP and sockets. The example code that we build in this
30tutorial will amend the blocking TLS client example that is covered in
31L<ossl-guide-tls-client-block(7)>. Only the differences between that client and
32this one will be discussed so we also assume that you have run through and
33understand that tutorial.
34
35For this tutorial our client will be using a single QUIC stream. A subsequent
36tutorial will discuss how to write a multi-stream client (see
37L<ossl-guide-quic-multi-stream(7)>).
38
39The complete source code for this example blocking QUIC client is available in
40the C<demos/guide> directory of the OpenSSL source distribution in the file
41C<quic-client-block.c>. It is also available online at
42L<https://github.com/openssl/openssl/blob/master/demos/guide/quic-client-block.c>.
43
44=head2 Creating the SSL_CTX and SSL objects
45
46In the TLS tutorial (L<ossl-guide-tls-client-block(7)>) we created an B<SSL_CTX>
47object for our client and used it to create an B<SSL> object to represent the
48TLS connection. A QUIC connection works in exactly the same way. We first create
49an B<SSL_CTX> object and then use it to create an B<SSL> object to represent the
50QUIC connection.
51
52As in the TLS example the first step is to create an B<SSL_CTX> object for our
53client. This is done in the same way as before except that we use a different
54"method". OpenSSL offers two different QUIC client methods, i.e.
55L<OSSL_QUIC_client_method(3)> and L<OSSL_QUIC_client_thread_method(3)>.
56
57The first one is the equivalent of L<TLS_client_method(3)> but for the QUIC
58protocol. The second one is the same, but it will additionally create a
59background thread for handling time based events (known as "thread assisted
60mode", see L<ossl-guide-quic-introduction(7)>). For this tutorial we will be
61using L<OSSL_QUIC_client_method(3)> because we will not be leaving the QUIC
62connection idle in our application and so thread assisted mode is not needed.
63
64    /*
65     * Create an SSL_CTX which we can use to create SSL objects from. We
66     * want an SSL_CTX for creating clients so we use OSSL_QUIC_client_method()
67     * here.
68     */
69    ctx = SSL_CTX_new(OSSL_QUIC_client_method());
70    if (ctx == NULL) {
71        printf("Failed to create the SSL_CTX\n");
72        goto end;
73    }
74
75The other setup steps that we applied to the B<SSL_CTX> for TLS also apply to
76QUIC except for restricting the TLS versions that we are willing to accept. The
77QUIC protocol implementation in OpenSSL currently only supports TLSv1.3. There
78is no need to call L<SSL_CTX_set_min_proto_version(3)> or
79L<SSL_CTX_set_max_proto_version(3)> in an OpenSSL QUIC application, and any such
80call will be ignored.
81
82Once the B<SSL_CTX> is created, the B<SSL> object is constructed in exactly the
83same way as for the TLS application.
84
85=head2 Creating the socket and BIO
86
87A major difference between TLS and QUIC is the underlying transport protocol.
88TLS uses TCP while QUIC uses UDP. The way that the QUIC socket is created in our
89example code is much the same as for TLS. We use the L<BIO_lookup_ex(3)> and
90L<BIO_socket(3)> helper functions as we did in the previous tutorial except that
91we pass B<SOCK_DGRAM> as an argument to indicate UDP (instead of B<SOCK_STREAM>
92for TCP).
93
94    /*
95     * Lookup IP address info for the server.
96     */
97    if (!BIO_lookup_ex(hostname, port, BIO_LOOKUP_CLIENT, family, SOCK_DGRAM, 0,
98                       &res))
99        return NULL;
100
101    /*
102     * Loop through all the possible addresses for the server and find one
103     * we can connect to.
104     */
105    for (ai = res; ai != NULL; ai = BIO_ADDRINFO_next(ai)) {
106        /*
107         * Create a TCP socket. We could equally use non-OpenSSL calls such
108         * as "socket" here for this and the subsequent connect and close
109         * functions. But for portability reasons and also so that we get
110         * errors on the OpenSSL stack in the event of a failure we use
111         * OpenSSL's versions of these functions.
112         */
113        sock = BIO_socket(BIO_ADDRINFO_family(ai), SOCK_DGRAM, 0, 0);
114        if (sock == -1)
115            continue;
116
117        /* Connect the socket to the server's address */
118        if (!BIO_connect(sock, BIO_ADDRINFO_address(ai), 0)) {
119            BIO_closesocket(sock);
120            sock = -1;
121            continue;
122        }
123
124        /* Set to nonblocking mode */
125        if (!BIO_socket_nbio(sock, 1)) {
126            BIO_closesocket(sock);
127            sock = -1;
128            continue;
129        }
130
131        break;
132    }
133
134    if (sock != -1) {
135        *peer_addr = BIO_ADDR_dup(BIO_ADDRINFO_address(ai));
136        if (*peer_addr == NULL) {
137            BIO_closesocket(sock);
138            return NULL;
139        }
140    }
141
142    /* Free the address information resources we allocated earlier */
143    BIO_ADDRINFO_free(res);
144
145You may notice a couple of other differences between this code and the version
146that we used for TLS.
147
148Firstly, we set the socket into nonblocking mode. This must always be done for
149an OpenSSL QUIC application. This may be surprising considering that we are
150trying to write a blocking client. Despite this the B<SSL> object will still
151have blocking behaviour. See L<ossl-guide-quic-introduction(7)> for further
152information on this.
153
154Secondly, we take note of the IP address of the peer that we are connecting to.
155We store that information away. We will need it later.
156
157See L<BIO_lookup_ex(3)>, L<BIO_socket(3)>, L<BIO_connect(3)>,
158L<BIO_closesocket(3)>, L<BIO_ADDRINFO_next(3)>, L<BIO_ADDRINFO_address(3)>,
159L<BIO_ADDRINFO_free(3)> and L<BIO_ADDR_dup(3)> for further information on the
160functions used here. In the above example code the B<hostname> and B<port>
161variables are strings, e.g. "www.example.com" and "443".
162
163As for our TLS client, once the socket has been created and connected we need to
164associate it with a BIO object:
165
166    BIO *bio;
167
168    /* Create a BIO to wrap the socket */
169    bio = BIO_new(BIO_s_datagram());
170    if (bio == NULL) {
171        BIO_closesocket(sock);
172        return NULL;
173    }
174
175    /*
176     * Associate the newly created BIO with the underlying socket. By
177     * passing BIO_CLOSE here the socket will be automatically closed when
178     * the BIO is freed. Alternatively you can use BIO_NOCLOSE, in which
179     * case you must close the socket explicitly when it is no longer
180     * needed.
181     */
182    BIO_set_fd(bio, sock, BIO_CLOSE);
183
184Note the use of L<BIO_s_datagram(3)> here as opposed to L<BIO_s_socket(3)> that
185we used for our TLS client. This is again due to the fact that QUIC uses UDP
186instead of TCP for its transport layer. See L<BIO_new(3)>, L<BIO_s_datagram(3)>
187and L<BIO_set_fd(3)> for further information on these functions.
188
189=head2 Setting the server's hostname
190
191As in the TLS tutorial we need to set the server's hostname both for SNI (Server
192Name Indication) and for certificate validation purposes. The steps for this are
193identical to the TLS tutorial and won't be repeated here.
194
195=head2 Setting the ALPN
196
197ALPN (Application-Layer Protocol Negotiation) is a feature of TLS that enables
198the application to negotiate which protocol will be used over the connection.
199For example, if you intend to use HTTP/3 over the connection then the ALPN value
200for that is "h3" (see
201L<https://www.iana.org/assignments/tls-extensiontype-values/tls-extensiontype-values.xml#alpn-protocol-ids>).
202OpenSSL provides the ability for a client to specify the ALPN to use via the
203L<SSL_set_alpn_protos(3)> function. This is optional for a TLS client and so our
204simple client that we developed in L<ossl-guide-tls-client-block(7)> did not use
205it. However QUIC mandates that the TLS handshake used in establishing a QUIC
206connection must use ALPN.
207
208    unsigned char alpn[] = { 8, 'h', 't', 't', 'p', '/', '1', '.', '0' };
209
210    /* SSL_set_alpn_protos returns 0 for success! */
211    if (SSL_set_alpn_protos(ssl, alpn, sizeof(alpn)) != 0) {
212        printf("Failed to set the ALPN for the connection\n");
213        goto end;
214    }
215
216The ALPN is specified using a length prefixed array of unsigned chars (it is not
217a NUL terminated string). Our original TLS blocking client demo was using
218HTTP/1.0. We will use the same for this example. Unlike most OpenSSL functions
219L<SSL_set_alpn_protos(3)> returns zero for success and nonzero for failure.
220
221=head2 Setting the peer address
222
223An OpenSSL QUIC application must specify the target address of the server that
224is being connected to. In L</Creating the socket and BIO> above we saved that
225address away for future use. Now we need to use it via the
226L<SSL_set1_initial_peer_addr(3)> function.
227
228    /* Set the IP address of the remote peer */
229    if (!SSL_set1_initial_peer_addr(ssl, peer_addr)) {
230        printf("Failed to set the initial peer address\n");
231        goto end;
232    }
233
234Note that we will need to free the B<peer_addr> value that we allocated via
235L<BIO_ADDR_dup(3)> earlier:
236
237    BIO_ADDR_free(peer_addr);
238
239=head2 The handshake and application data transfer
240
241Once initial setup of the B<SSL> object is complete then we perform the
242handshake via L<SSL_connect(3)> in exactly the same way as we did for the TLS
243client, so we won't repeat it here.
244
245We can also perform data transfer using a default QUIC stream that is
246automatically associated with the B<SSL> object for us. We can transmit data
247using L<SSL_write_ex(3)>, and receive data using L<SSL_read_ex(3)> in the same
248way as for TLS. The main difference is that we have to account for failures
249slightly differently. With QUIC the stream can be reset by the peer (which is
250fatal for that stream), but the underlying connection itself may still be
251healthy.
252
253    /*
254     * Get up to sizeof(buf) bytes of the response. We keep reading until the
255     * server closes the connection.
256     */
257    while (SSL_read_ex(ssl, buf, sizeof(buf), &readbytes)) {
258        /*
259        * OpenSSL does not guarantee that the returned data is a string or
260        * that it is NUL terminated so we use fwrite() to write the exact
261        * number of bytes that we read. The data could be non-printable or
262        * have NUL characters in the middle of it. For this simple example
263        * we're going to print it to stdout anyway.
264        */
265        fwrite(buf, 1, readbytes, stdout);
266    }
267    /* In case the response didn't finish with a newline we add one now */
268    printf("\n");
269
270    /*
271     * Check whether we finished the while loop above normally or as the
272     * result of an error. The 0 argument to SSL_get_error() is the return
273     * code we received from the SSL_read_ex() call. It must be 0 in order
274     * to get here. Normal completion is indicated by SSL_ERROR_ZERO_RETURN. In
275     * QUIC terms this means that the peer has sent FIN on the stream to
276     * indicate that no further data will be sent.
277     */
278    switch (SSL_get_error(ssl, 0)) {
279    case SSL_ERROR_ZERO_RETURN:
280        /* Normal completion of the stream */
281        break;
282
283    case SSL_ERROR_SSL:
284        /*
285         * Some stream fatal error occurred. This could be because of a stream
286         * reset - or some failure occurred on the underlying connection.
287         */
288        switch (SSL_get_stream_read_state(ssl)) {
289        case SSL_STREAM_STATE_RESET_REMOTE:
290            printf("Stream reset occurred\n");
291            /* The stream has been reset but the connection is still healthy. */
292            break;
293
294        case SSL_STREAM_STATE_CONN_CLOSED:
295            printf("Connection closed\n");
296            /* Connection is already closed. Skip SSL_shutdown() */
297            goto end;
298
299        default:
300            printf("Unknown stream failure\n");
301            break;
302        }
303        break;
304
305    default:
306        /* Some other unexpected error occurred */
307        printf ("Failed reading remaining data\n");
308        break;
309    }
310
311In the above code example you can see that B<SSL_ERROR_SSL> indicates a stream
312fatal error. We can use L<SSL_get_stream_read_state(3)> to determine whether the
313stream has been reset, or if some other fatal error has occurred.
314
315=head2 Shutting down the connection
316
317In the TLS tutorial we knew that the server had finished sending data because
318L<SSL_read_ex(3)> returned 0, and L<SSL_get_error(3)> returned
319B<SSL_ERROR_ZERO_RETURN>. The same is true with QUIC except that
320B<SSL_ERROR_ZERO_RETURN> should be interpreted slightly differently. With TLS
321we knew that this meant that the server had sent a "close_notify" alert. No
322more data will be sent from the server on that connection.
323
324With QUIC it means that the server has indicated "FIN" on the stream, meaning
325that it will no longer send any more data on that stream. However this only
326gives us information about the stream itself and does not tell us anything about
327the underlying connection. More data could still be sent from the server on some
328other stream. Additionally, although the server will not send any more data to
329the client, it does not prevent the client from sending more data to the server.
330
331In this tutorial, once we have finished reading data from the server on the one
332stream that we are using, we will close the connection down. As before we do
333this via the L<SSL_shutdown(3)> function. This example for QUIC is very similar
334to the TLS version. However the L<SSL_shutdown(3)> function will need to be
335called more than once:
336
337    /*
338     * Repeatedly call SSL_shutdown() until the connection is fully
339     * closed.
340     */
341    do {
342        ret = SSL_shutdown(ssl);
343        if (ret < 0) {
344            printf("Error shutting down: %d\n", ret);
345            goto end;
346        }
347    } while (ret != 1);
348
349The shutdown process is in two stages. In the first stage we wait until all the
350data we have buffered for sending on any stream has been successfully sent and
351acknowledged by the peer, and then we send a CONNECTION_CLOSE to the peer to
352indicate that the connection is no longer usable. This immediately closes the
353connection and no more data can be sent or received. L<SSL_shutdown(3)> returns
3540 once the first stage has been completed.
355
356In the second stage the connection enters a "closing" state. Application data
357cannot be sent or received in this state, but late arriving packets coming from
358the peer will be handled appropriately. Once this stage has completed
359successfully L<SSL_shutdown(3)> will return 1 to indicate success.
360
361=head1 FURTHER READING
362
363See L<ossl-guide-quic-multi-stream(7)> to read a tutorial on how to modify the
364client developed on this page to support multiple streams.
365
366=head1 SEE ALSO
367
368L<ossl-guide-introduction(7)>, L<ossl-guide-libraries-introduction(7)>,
369L<ossl-guide-libssl-introduction(7)>, L<ossl-guide-tls-introduction(7)>,
370L<ossl-guide-tls-client-block(7)>, L<ossl-guide-quic-introduction(7)>
371
372=head1 COPYRIGHT
373
374Copyright 2023 The OpenSSL Project Authors. All Rights Reserved.
375
376Licensed under the Apache License 2.0 (the "License").  You may not use
377this file except in compliance with the License.  You can obtain a copy
378in the file LICENSE in the source distribution or at
379L<https://www.openssl.org/source/license.html>.
380
381=cut
382