]> git.ipfire.org Git - thirdparty/openssl.git/blob - ssl/quic/quic_tserver.c
Enable QUIC test server to find out the termination reason
[thirdparty/openssl.git] / ssl / quic / quic_tserver.c
1 /*
2 * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the Apache License 2.0 (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10 #include "internal/quic_tserver.h"
11 #include "internal/quic_channel.h"
12 #include "internal/quic_statm.h"
13 #include "internal/common.h"
14
15 /*
16 * QUIC Test Server Module
17 * =======================
18 */
19 struct quic_tserver_st {
20 QUIC_TSERVER_ARGS args;
21
22 /*
23 * The QUIC channel providing the core QUIC connection implementation.
24 */
25 QUIC_CHANNEL *ch;
26
27 /* SSL_CTX for creating the underlying TLS connection */
28 SSL_CTX *ctx;
29
30 /* SSL for the underlying TLS connection */
31 SSL *tls;
32
33 /* Our single bidirectional application data stream. */
34 QUIC_STREAM *stream0;
35
36 /* The current peer L4 address. AF_UNSPEC if we do not have a peer yet. */
37 BIO_ADDR cur_peer_addr;
38
39 /* Are we connected to a peer? */
40 unsigned int connected : 1;
41 };
42
43 static int alpn_select_cb(SSL *ssl, const unsigned char **out,
44 unsigned char *outlen, const unsigned char *in,
45 unsigned int inlen, void *arg)
46 {
47 unsigned char alpn[] = { 8, 'o', 's', 's', 'l', 't', 'e', 's', 't' };
48
49 if (SSL_select_next_proto((unsigned char **)out, outlen, alpn, sizeof(alpn),
50 in, inlen) != OPENSSL_NPN_NEGOTIATED)
51 return SSL_TLSEXT_ERR_ALERT_FATAL;
52
53 return SSL_TLSEXT_ERR_OK;
54 }
55
56 QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args,
57 const char *certfile, const char *keyfile)
58 {
59 QUIC_TSERVER *srv = NULL;
60 QUIC_CHANNEL_ARGS ch_args = {0};
61
62 if (args->net_rbio == NULL || args->net_wbio == NULL)
63 goto err;
64
65 if ((srv = OPENSSL_zalloc(sizeof(*srv))) == NULL)
66 goto err;
67
68 srv->args = *args;
69
70 srv->ctx = SSL_CTX_new_ex(srv->args.libctx, srv->args.propq, TLS_method());
71 if (srv->ctx == NULL)
72 goto err;
73
74 if (SSL_CTX_use_certificate_file(srv->ctx, certfile, SSL_FILETYPE_PEM) <= 0)
75 goto err;
76
77 if (SSL_CTX_use_PrivateKey_file(srv->ctx, keyfile, SSL_FILETYPE_PEM) <= 0)
78 goto err;
79
80 SSL_CTX_set_alpn_select_cb(srv->ctx, alpn_select_cb, srv);
81
82 srv->tls = SSL_new(srv->ctx);
83 if (srv->tls == NULL)
84 goto err;
85
86 ch_args.libctx = srv->args.libctx;
87 ch_args.propq = srv->args.propq;
88 ch_args.tls = srv->tls;
89 ch_args.is_server = 1;
90
91 if ((srv->ch = ossl_quic_channel_new(&ch_args)) == NULL)
92 goto err;
93
94 if (!ossl_quic_channel_set_net_rbio(srv->ch, srv->args.net_rbio)
95 || !ossl_quic_channel_set_net_wbio(srv->ch, srv->args.net_wbio))
96 goto err;
97
98 srv->stream0 = ossl_quic_channel_get_stream_by_id(srv->ch, 0);
99 if (srv->stream0 == NULL)
100 goto err;
101
102 return srv;
103
104 err:
105 if (srv != NULL)
106 ossl_quic_channel_free(srv->ch);
107
108 OPENSSL_free(srv);
109 return NULL;
110 }
111
112 void ossl_quic_tserver_free(QUIC_TSERVER *srv)
113 {
114 if (srv == NULL)
115 return;
116
117 ossl_quic_channel_free(srv->ch);
118 BIO_free(srv->args.net_rbio);
119 BIO_free(srv->args.net_wbio);
120 SSL_free(srv->tls);
121 SSL_CTX_free(srv->ctx);
122 OPENSSL_free(srv);
123 }
124
125 /* Set mutator callbacks for test framework support */
126 int ossl_quic_tserver_set_mutator(QUIC_TSERVER *srv,
127 ossl_mutate_packet_cb mutatecb,
128 ossl_finish_mutate_cb finishmutatecb,
129 void *mutatearg)
130 {
131 return ossl_quic_channel_set_mutator(srv->ch, mutatecb, finishmutatecb,
132 mutatearg);
133 }
134
135 int ossl_quic_tserver_tick(QUIC_TSERVER *srv)
136 {
137 ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(srv->ch));
138
139 if (ossl_quic_channel_is_active(srv->ch))
140 srv->connected = 1;
141
142 return 1;
143 }
144
145 int ossl_quic_tserver_is_connected(QUIC_TSERVER *srv)
146 {
147 return ossl_quic_channel_is_active(srv->ch);
148 }
149
150 /* Returns 1 if the server is in any terminating or terminated state */
151 int ossl_quic_tserver_is_term_any(QUIC_TSERVER *srv,
152 QUIC_TERMINATE_CAUSE *cause)
153 {
154 return ossl_quic_channel_is_term_any(srv->ch, cause);
155 }
156
157 /* Returns 1 if the server is in a terminated state */
158 int ossl_quic_tserver_is_terminated(QUIC_TSERVER *srv,
159 QUIC_TERMINATE_CAUSE *cause)
160 {
161 return ossl_quic_channel_is_terminated(srv->ch, cause);
162 }
163
164 int ossl_quic_tserver_read(QUIC_TSERVER *srv,
165 unsigned char *buf,
166 size_t buf_len,
167 size_t *bytes_read)
168 {
169 int is_fin = 0;
170
171 if (!ossl_quic_channel_is_active(srv->ch))
172 return 0;
173
174 if (srv->stream0->recv_fin_retired)
175 return 0;
176
177 if (!ossl_quic_rstream_read(srv->stream0->rstream, buf, buf_len,
178 bytes_read, &is_fin))
179 return 0;
180
181 if (*bytes_read > 0) {
182 /*
183 * We have read at least one byte from the stream. Inform stream-level
184 * RXFC of the retirement of controlled bytes. Update the active stream
185 * status (the RXFC may now want to emit a frame granting more credit to
186 * the peer).
187 */
188 OSSL_RTT_INFO rtt_info;
189
190 ossl_statm_get_rtt_info(ossl_quic_channel_get_statm(srv->ch), &rtt_info);
191
192 if (!ossl_quic_rxfc_on_retire(&srv->stream0->rxfc, *bytes_read,
193 rtt_info.smoothed_rtt))
194 return 0;
195 }
196
197 if (is_fin)
198 srv->stream0->recv_fin_retired = 1;
199
200 if (*bytes_read > 0)
201 ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv->ch),
202 srv->stream0);
203
204 return 1;
205 }
206
207 int ossl_quic_tserver_has_read_ended(QUIC_TSERVER *srv)
208 {
209 return srv->stream0->recv_fin_retired;
210 }
211
212 int ossl_quic_tserver_write(QUIC_TSERVER *srv,
213 const unsigned char *buf,
214 size_t buf_len,
215 size_t *bytes_written)
216 {
217 if (!ossl_quic_channel_is_active(srv->ch))
218 return 0;
219
220 if (!ossl_quic_sstream_append(srv->stream0->sstream,
221 buf, buf_len, bytes_written))
222 return 0;
223
224 if (*bytes_written > 0)
225 /*
226 * We have appended at least one byte to the stream. Potentially mark
227 * the stream as active, depending on FC.
228 */
229 ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv->ch),
230 srv->stream0);
231
232 /* Try and send. */
233 ossl_quic_tserver_tick(srv);
234 return 1;
235 }
236
237 int ossl_quic_tserver_conclude(QUIC_TSERVER *srv)
238 {
239 if (!ossl_quic_channel_is_active(srv->ch))
240 return 0;
241
242 if (!ossl_quic_sstream_get_final_size(srv->stream0->sstream, NULL)) {
243 ossl_quic_sstream_fin(srv->stream0->sstream);
244 ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv->ch),
245 srv->stream0);
246 }
247
248 ossl_quic_tserver_tick(srv);
249 return 1;
250 }