2 * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
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
10 #include "internal/quic_tserver.h"
11 #include "internal/quic_channel.h"
12 #include "internal/quic_statm.h"
13 #include "internal/common.h"
16 * QUIC Test Server Module
17 * =======================
19 struct quic_tserver_st
{
20 QUIC_TSERVER_ARGS args
;
23 * The QUIC channel providing the core QUIC connection implementation.
27 /* SSL_CTX for creating the underlying TLS connection */
30 /* SSL for the underlying TLS connection */
33 /* Our single bidirectional application data stream. */
36 /* The current peer L4 address. AF_UNSPEC if we do not have a peer yet. */
37 BIO_ADDR cur_peer_addr
;
39 /* Are we connected to a peer? */
40 unsigned int connected
: 1;
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
)
47 unsigned char alpn
[] = { 8, 'o', 's', 's', 'l', 't', 'e', 's', 't' };
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
;
53 return SSL_TLSEXT_ERR_OK
;
56 QUIC_TSERVER
*ossl_quic_tserver_new(const QUIC_TSERVER_ARGS
*args
,
57 const char *certfile
, const char *keyfile
)
59 QUIC_TSERVER
*srv
= NULL
;
60 QUIC_CHANNEL_ARGS ch_args
= {0};
62 if (args
->net_rbio
== NULL
|| args
->net_wbio
== NULL
)
65 if ((srv
= OPENSSL_zalloc(sizeof(*srv
))) == NULL
)
70 srv
->ctx
= SSL_CTX_new_ex(srv
->args
.libctx
, srv
->args
.propq
, TLS_method());
74 if (SSL_CTX_use_certificate_file(srv
->ctx
, certfile
, SSL_FILETYPE_PEM
) <= 0)
77 if (SSL_CTX_use_PrivateKey_file(srv
->ctx
, keyfile
, SSL_FILETYPE_PEM
) <= 0)
80 SSL_CTX_set_alpn_select_cb(srv
->ctx
, alpn_select_cb
, srv
);
82 srv
->tls
= SSL_new(srv
->ctx
);
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;
91 if ((srv
->ch
= ossl_quic_channel_new(&ch_args
)) == NULL
)
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
))
98 srv
->stream0
= ossl_quic_channel_get_stream_by_id(srv
->ch
, 0);
99 if (srv
->stream0
== NULL
)
106 ossl_quic_channel_free(srv
->ch
);
112 void ossl_quic_tserver_free(QUIC_TSERVER
*srv
)
117 ossl_quic_channel_free(srv
->ch
);
118 BIO_free(srv
->args
.net_rbio
);
119 BIO_free(srv
->args
.net_wbio
);
121 SSL_CTX_free(srv
->ctx
);
125 /* Set mutator callbacks for test framework support */
126 int ossl_quic_tserver_set_plain_packet_mutator(QUIC_TSERVER
*srv
,
127 ossl_mutate_packet_cb mutatecb
,
128 ossl_finish_mutate_cb finishmutatecb
,
131 return ossl_quic_channel_set_mutator(srv
->ch
, mutatecb
, finishmutatecb
,
135 int ossl_quic_tserver_set_handshake_mutator(QUIC_TSERVER
*srv
,
136 ossl_statem_mutate_handshake_cb mutate_handshake_cb
,
137 ossl_statem_finish_mutate_handshake_cb finish_mutate_handshake_cb
,
140 return ossl_statem_set_mutator(ossl_quic_channel_get0_ssl(srv
->ch
),
142 finish_mutate_handshake_cb
,
146 int ossl_quic_tserver_tick(QUIC_TSERVER
*srv
)
148 ossl_quic_reactor_tick(ossl_quic_channel_get_reactor(srv
->ch
));
150 if (ossl_quic_channel_is_active(srv
->ch
))
156 int ossl_quic_tserver_is_connected(QUIC_TSERVER
*srv
)
158 return ossl_quic_channel_is_active(srv
->ch
);
161 /* Returns 1 if the server is in any terminating or terminated state */
162 int ossl_quic_tserver_is_term_any(QUIC_TSERVER
*srv
,
163 QUIC_TERMINATE_CAUSE
*cause
)
165 return ossl_quic_channel_is_term_any(srv
->ch
, cause
);
168 /* Returns 1 if the server is in a terminated state */
169 int ossl_quic_tserver_is_terminated(QUIC_TSERVER
*srv
,
170 QUIC_TERMINATE_CAUSE
*cause
)
172 return ossl_quic_channel_is_terminated(srv
->ch
, cause
);
175 int ossl_quic_tserver_read(QUIC_TSERVER
*srv
,
182 if (!ossl_quic_channel_is_active(srv
->ch
))
185 if (srv
->stream0
->recv_fin_retired
)
188 if (!ossl_quic_rstream_read(srv
->stream0
->rstream
, buf
, buf_len
,
189 bytes_read
, &is_fin
))
192 if (*bytes_read
> 0) {
194 * We have read at least one byte from the stream. Inform stream-level
195 * RXFC of the retirement of controlled bytes. Update the active stream
196 * status (the RXFC may now want to emit a frame granting more credit to
199 OSSL_RTT_INFO rtt_info
;
201 ossl_statm_get_rtt_info(ossl_quic_channel_get_statm(srv
->ch
), &rtt_info
);
203 if (!ossl_quic_rxfc_on_retire(&srv
->stream0
->rxfc
, *bytes_read
,
204 rtt_info
.smoothed_rtt
))
209 srv
->stream0
->recv_fin_retired
= 1;
212 ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv
->ch
),
218 int ossl_quic_tserver_has_read_ended(QUIC_TSERVER
*srv
)
220 return srv
->stream0
->recv_fin_retired
;
223 int ossl_quic_tserver_write(QUIC_TSERVER
*srv
,
224 const unsigned char *buf
,
226 size_t *bytes_written
)
228 if (!ossl_quic_channel_is_active(srv
->ch
))
231 if (!ossl_quic_sstream_append(srv
->stream0
->sstream
,
232 buf
, buf_len
, bytes_written
))
235 if (*bytes_written
> 0)
237 * We have appended at least one byte to the stream. Potentially mark
238 * the stream as active, depending on FC.
240 ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv
->ch
),
244 ossl_quic_tserver_tick(srv
);
248 int ossl_quic_tserver_conclude(QUIC_TSERVER
*srv
)
250 if (!ossl_quic_channel_is_active(srv
->ch
))
253 if (!ossl_quic_sstream_get_final_size(srv
->stream0
->sstream
, NULL
)) {
254 ossl_quic_sstream_fin(srv
->stream0
->sstream
);
255 ossl_quic_stream_map_update_state(ossl_quic_channel_get_qsm(srv
->ch
),
259 ossl_quic_tserver_tick(srv
);