]> git.ipfire.org Git - thirdparty/openssl.git/blame - ssl/quic/quic_tserver.c
Enable QUIC test server to find out the termination reason
[thirdparty/openssl.git] / ssl / quic / quic_tserver.c
CommitLineData
51a168b8
HL
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 */
19struct 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
4e3a55fd
MC
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
51a168b8
HL
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
4e3a55fd
MC
43static 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
56QUIC_TSERVER *ossl_quic_tserver_new(const QUIC_TSERVER_ARGS *args,
57 const char *certfile, const char *keyfile)
51a168b8
HL
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
4e3a55fd
MC
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
51a168b8
HL
86 ch_args.libctx = srv->args.libctx;
87 ch_args.propq = srv->args.propq;
4e3a55fd 88 ch_args.tls = srv->tls;
51a168b8
HL
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
104err:
105 if (srv != NULL)
106 ossl_quic_channel_free(srv->ch);
107
108 OPENSSL_free(srv);
109 return NULL;
110}
111
112void 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);
4e3a55fd
MC
120 SSL_free(srv->tls);
121 SSL_CTX_free(srv->ctx);
51a168b8
HL
122 OPENSSL_free(srv);
123}
124
14e31409
MC
125/* Set mutator callbacks for test framework support */
126int 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
51a168b8
HL
135int 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
145int ossl_quic_tserver_is_connected(QUIC_TSERVER *srv)
146{
147 return ossl_quic_channel_is_active(srv->ch);
148}
149
adef87a2 150/* Returns 1 if the server is in any terminating or terminated state */
149a8e6c
MC
151int ossl_quic_tserver_is_term_any(QUIC_TSERVER *srv,
152 QUIC_TERMINATE_CAUSE *cause)
adef87a2 153{
149a8e6c
MC
154 return ossl_quic_channel_is_term_any(srv->ch, cause);
155}
156
157/* Returns 1 if the server is in a terminated state */
158int ossl_quic_tserver_is_terminated(QUIC_TSERVER *srv,
159 QUIC_TERMINATE_CAUSE *cause)
160{
161 return ossl_quic_channel_is_terminated(srv->ch, cause);
adef87a2
MC
162}
163
51a168b8
HL
164int ossl_quic_tserver_read(QUIC_TSERVER *srv,
165 unsigned char *buf,
166 size_t buf_len,
167 size_t *bytes_read)
168{
a9979965 169 int is_fin = 0;
51a168b8
HL
170
171 if (!ossl_quic_channel_is_active(srv->ch))
172 return 0;
173
a9979965
HL
174 if (srv->stream0->recv_fin_retired)
175 return 0;
176
51a168b8
HL
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;
091f532e 189
51a168b8
HL
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
a9979965
HL
207int ossl_quic_tserver_has_read_ended(QUIC_TSERVER *srv)
208{
209 return srv->stream0->recv_fin_retired;
210}
211
51a168b8
HL
212int 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}
a9979965
HL
236
237int 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}