xref: /freebsd/crypto/openssl/test/quic_tserver_test.c (revision e7be843b4a162e68651d3911f0357ed464915629)
1*e7be843bSPierre Pronchery /*
2*e7be843bSPierre Pronchery  * Copyright 2022-2025 The OpenSSL Project Authors. All Rights Reserved.
3*e7be843bSPierre Pronchery  *
4*e7be843bSPierre Pronchery  * Licensed under the Apache License 2.0 (the "License").  You may not use
5*e7be843bSPierre Pronchery  * this file except in compliance with the License.  You can obtain a copy
6*e7be843bSPierre Pronchery  * in the file LICENSE in the source distribution or at
7*e7be843bSPierre Pronchery  * https://www.openssl.org/source/license.html
8*e7be843bSPierre Pronchery  */
9*e7be843bSPierre Pronchery #include <openssl/ssl.h>
10*e7be843bSPierre Pronchery #include <openssl/quic.h>
11*e7be843bSPierre Pronchery #include <openssl/bio.h>
12*e7be843bSPierre Pronchery #include "internal/common.h"
13*e7be843bSPierre Pronchery #include "internal/sockets.h"
14*e7be843bSPierre Pronchery #include "internal/quic_tserver.h"
15*e7be843bSPierre Pronchery #include "internal/quic_thread_assist.h"
16*e7be843bSPierre Pronchery #include "internal/quic_ssl.h"
17*e7be843bSPierre Pronchery #include "internal/time.h"
18*e7be843bSPierre Pronchery #include "testutil.h"
19*e7be843bSPierre Pronchery 
20*e7be843bSPierre Pronchery static const char msg1[] = "The quick brown fox jumped over the lazy dogs.";
21*e7be843bSPierre Pronchery static char msg2[1024], msg3[1024];
22*e7be843bSPierre Pronchery static OSSL_TIME fake_time;
23*e7be843bSPierre Pronchery static CRYPTO_RWLOCK *fake_time_lock;
24*e7be843bSPierre Pronchery 
25*e7be843bSPierre Pronchery static const char *certfile, *keyfile;
26*e7be843bSPierre Pronchery 
is_want(SSL * s,int ret)27*e7be843bSPierre Pronchery static int is_want(SSL *s, int ret)
28*e7be843bSPierre Pronchery {
29*e7be843bSPierre Pronchery     int ec = SSL_get_error(s, ret);
30*e7be843bSPierre Pronchery 
31*e7be843bSPierre Pronchery     return ec == SSL_ERROR_WANT_READ || ec == SSL_ERROR_WANT_WRITE;
32*e7be843bSPierre Pronchery }
33*e7be843bSPierre Pronchery 
34*e7be843bSPierre Pronchery static unsigned char scratch_buf[2048];
35*e7be843bSPierre Pronchery 
fake_now(void * arg)36*e7be843bSPierre Pronchery static OSSL_TIME fake_now(void *arg)
37*e7be843bSPierre Pronchery {
38*e7be843bSPierre Pronchery     OSSL_TIME t;
39*e7be843bSPierre Pronchery 
40*e7be843bSPierre Pronchery     if (!CRYPTO_THREAD_read_lock(fake_time_lock))
41*e7be843bSPierre Pronchery         return ossl_time_zero();
42*e7be843bSPierre Pronchery 
43*e7be843bSPierre Pronchery     t = fake_time;
44*e7be843bSPierre Pronchery 
45*e7be843bSPierre Pronchery     CRYPTO_THREAD_unlock(fake_time_lock);
46*e7be843bSPierre Pronchery     return t;
47*e7be843bSPierre Pronchery }
48*e7be843bSPierre Pronchery 
real_now(void * arg)49*e7be843bSPierre Pronchery static OSSL_TIME real_now(void *arg)
50*e7be843bSPierre Pronchery {
51*e7be843bSPierre Pronchery     return ossl_time_now();
52*e7be843bSPierre Pronchery }
53*e7be843bSPierre Pronchery 
do_test(int use_thread_assist,int use_fake_time,int use_inject)54*e7be843bSPierre Pronchery static int do_test(int use_thread_assist, int use_fake_time, int use_inject)
55*e7be843bSPierre Pronchery {
56*e7be843bSPierre Pronchery     int testresult = 0, ret;
57*e7be843bSPierre Pronchery     int s_fd = -1, c_fd = -1;
58*e7be843bSPierre Pronchery     BIO *s_net_bio = NULL, *s_net_bio_own = NULL;
59*e7be843bSPierre Pronchery     BIO *c_net_bio = NULL, *c_net_bio_own = NULL;
60*e7be843bSPierre Pronchery     BIO *c_pair_own = NULL, *s_pair_own = NULL;
61*e7be843bSPierre Pronchery     QUIC_TSERVER_ARGS tserver_args = {0};
62*e7be843bSPierre Pronchery     QUIC_TSERVER *tserver = NULL;
63*e7be843bSPierre Pronchery     BIO_ADDR *s_addr_ = NULL;
64*e7be843bSPierre Pronchery     struct in_addr ina = {0};
65*e7be843bSPierre Pronchery     union BIO_sock_info_u s_info = {0};
66*e7be843bSPierre Pronchery     SSL_CTX *c_ctx = NULL;
67*e7be843bSPierre Pronchery     SSL *c_ssl = NULL;
68*e7be843bSPierre Pronchery     int c_connected = 0, c_write_done = 0, c_begin_read = 0, s_read_done = 0;
69*e7be843bSPierre Pronchery     int c_wait_eos = 0, c_done_eos = 0;
70*e7be843bSPierre Pronchery     int c_start_idle_test = 0, c_done_idle_test = 0;
71*e7be843bSPierre Pronchery     size_t l = 0, s_total_read = 0, s_total_written = 0, c_total_read = 0;
72*e7be843bSPierre Pronchery     size_t idle_units_done = 0;
73*e7be843bSPierre Pronchery     int s_begin_write = 0;
74*e7be843bSPierre Pronchery     OSSL_TIME start_time;
75*e7be843bSPierre Pronchery     unsigned char alpn[] = { 8, 'o', 's', 's', 'l', 't', 'e', 's', 't' };
76*e7be843bSPierre Pronchery     size_t limit_ms = 10000;
77*e7be843bSPierre Pronchery 
78*e7be843bSPierre Pronchery #if defined(OPENSSL_NO_QUIC_THREAD_ASSIST)
79*e7be843bSPierre Pronchery     if (use_thread_assist) {
80*e7be843bSPierre Pronchery         TEST_skip("thread assisted mode not enabled");
81*e7be843bSPierre Pronchery         return 1;
82*e7be843bSPierre Pronchery     }
83*e7be843bSPierre Pronchery #endif
84*e7be843bSPierre Pronchery 
85*e7be843bSPierre Pronchery     ina.s_addr = htonl(0x7f000001UL);
86*e7be843bSPierre Pronchery 
87*e7be843bSPierre Pronchery     /* Setup test server. */
88*e7be843bSPierre Pronchery     s_fd = BIO_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, 0);
89*e7be843bSPierre Pronchery     if (!TEST_int_ge(s_fd, 0))
90*e7be843bSPierre Pronchery         goto err;
91*e7be843bSPierre Pronchery 
92*e7be843bSPierre Pronchery     if (!TEST_true(BIO_socket_nbio(s_fd, 1)))
93*e7be843bSPierre Pronchery         goto err;
94*e7be843bSPierre Pronchery 
95*e7be843bSPierre Pronchery     if (!TEST_ptr(s_addr_ = BIO_ADDR_new()))
96*e7be843bSPierre Pronchery         goto err;
97*e7be843bSPierre Pronchery 
98*e7be843bSPierre Pronchery     if (!TEST_true(BIO_ADDR_rawmake(s_addr_, AF_INET, &ina, sizeof(ina), 0)))
99*e7be843bSPierre Pronchery         goto err;
100*e7be843bSPierre Pronchery 
101*e7be843bSPierre Pronchery     if (!TEST_true(BIO_bind(s_fd, s_addr_, 0)))
102*e7be843bSPierre Pronchery         goto err;
103*e7be843bSPierre Pronchery 
104*e7be843bSPierre Pronchery     s_info.addr = s_addr_;
105*e7be843bSPierre Pronchery     if (!TEST_true(BIO_sock_info(s_fd, BIO_SOCK_INFO_ADDRESS, &s_info)))
106*e7be843bSPierre Pronchery         goto err;
107*e7be843bSPierre Pronchery 
108*e7be843bSPierre Pronchery     if (!TEST_int_gt(BIO_ADDR_rawport(s_addr_), 0))
109*e7be843bSPierre Pronchery         goto err;
110*e7be843bSPierre Pronchery 
111*e7be843bSPierre Pronchery     if (!TEST_ptr(s_net_bio = s_net_bio_own = BIO_new_dgram(s_fd, 0)))
112*e7be843bSPierre Pronchery         goto err;
113*e7be843bSPierre Pronchery 
114*e7be843bSPierre Pronchery     if (!BIO_up_ref(s_net_bio))
115*e7be843bSPierre Pronchery         goto err;
116*e7be843bSPierre Pronchery 
117*e7be843bSPierre Pronchery     fake_time = ossl_ms2time(1000);
118*e7be843bSPierre Pronchery 
119*e7be843bSPierre Pronchery     tserver_args.net_rbio = s_net_bio;
120*e7be843bSPierre Pronchery     tserver_args.net_wbio = s_net_bio;
121*e7be843bSPierre Pronchery     tserver_args.alpn = NULL;
122*e7be843bSPierre Pronchery     tserver_args.ctx = NULL;
123*e7be843bSPierre Pronchery     if (use_fake_time)
124*e7be843bSPierre Pronchery         tserver_args.now_cb = fake_now;
125*e7be843bSPierre Pronchery 
126*e7be843bSPierre Pronchery     if (!TEST_ptr(tserver = ossl_quic_tserver_new(&tserver_args, certfile,
127*e7be843bSPierre Pronchery                                                   keyfile))) {
128*e7be843bSPierre Pronchery         BIO_free(s_net_bio);
129*e7be843bSPierre Pronchery         goto err;
130*e7be843bSPierre Pronchery     }
131*e7be843bSPierre Pronchery 
132*e7be843bSPierre Pronchery     s_net_bio_own = NULL;
133*e7be843bSPierre Pronchery 
134*e7be843bSPierre Pronchery     if (use_inject) {
135*e7be843bSPierre Pronchery         /*
136*e7be843bSPierre Pronchery          * In inject mode we create a dgram pair to feed to the QUIC client on
137*e7be843bSPierre Pronchery          * the read side. We don't feed anything to this, it is just a
138*e7be843bSPierre Pronchery          * placeholder to give the client something which never returns any
139*e7be843bSPierre Pronchery          * datagrams.
140*e7be843bSPierre Pronchery          */
141*e7be843bSPierre Pronchery         if (!TEST_true(BIO_new_bio_dgram_pair(&c_pair_own, 5000,
142*e7be843bSPierre Pronchery                                               &s_pair_own, 5000)))
143*e7be843bSPierre Pronchery             goto err;
144*e7be843bSPierre Pronchery     }
145*e7be843bSPierre Pronchery 
146*e7be843bSPierre Pronchery     /* Setup test client. */
147*e7be843bSPierre Pronchery     c_fd = BIO_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, 0);
148*e7be843bSPierre Pronchery     if (!TEST_int_ge(c_fd, 0))
149*e7be843bSPierre Pronchery         goto err;
150*e7be843bSPierre Pronchery 
151*e7be843bSPierre Pronchery     if (!TEST_true(BIO_socket_nbio(c_fd, 1)))
152*e7be843bSPierre Pronchery         goto err;
153*e7be843bSPierre Pronchery 
154*e7be843bSPierre Pronchery     if (!TEST_ptr(c_net_bio = c_net_bio_own = BIO_new_dgram(c_fd, 0)))
155*e7be843bSPierre Pronchery         goto err;
156*e7be843bSPierre Pronchery 
157*e7be843bSPierre Pronchery     if (!BIO_dgram_set_peer(c_net_bio, s_addr_))
158*e7be843bSPierre Pronchery         goto err;
159*e7be843bSPierre Pronchery 
160*e7be843bSPierre Pronchery     if (!TEST_ptr(c_ctx = SSL_CTX_new(use_thread_assist
161*e7be843bSPierre Pronchery                                       ? OSSL_QUIC_client_thread_method()
162*e7be843bSPierre Pronchery                                       : OSSL_QUIC_client_method())))
163*e7be843bSPierre Pronchery         goto err;
164*e7be843bSPierre Pronchery 
165*e7be843bSPierre Pronchery     if (!TEST_ptr(c_ssl = SSL_new(c_ctx)))
166*e7be843bSPierre Pronchery         goto err;
167*e7be843bSPierre Pronchery 
168*e7be843bSPierre Pronchery     if (use_fake_time)
169*e7be843bSPierre Pronchery         if (!TEST_true(ossl_quic_set_override_now_cb(c_ssl, fake_now, NULL)))
170*e7be843bSPierre Pronchery             goto err;
171*e7be843bSPierre Pronchery 
172*e7be843bSPierre Pronchery     /* 0 is a success for SSL_set_alpn_protos() */
173*e7be843bSPierre Pronchery     if (!TEST_false(SSL_set_alpn_protos(c_ssl, alpn, sizeof(alpn))))
174*e7be843bSPierre Pronchery         goto err;
175*e7be843bSPierre Pronchery 
176*e7be843bSPierre Pronchery     /* Takes ownership of our reference to the BIO. */
177*e7be843bSPierre Pronchery     if (use_inject) {
178*e7be843bSPierre Pronchery         SSL_set0_rbio(c_ssl, c_pair_own);
179*e7be843bSPierre Pronchery         c_pair_own = NULL;
180*e7be843bSPierre Pronchery     } else {
181*e7be843bSPierre Pronchery         SSL_set0_rbio(c_ssl, c_net_bio);
182*e7be843bSPierre Pronchery 
183*e7be843bSPierre Pronchery         /* Get another reference to be transferred in the SSL_set0_wbio call. */
184*e7be843bSPierre Pronchery         if (!TEST_true(BIO_up_ref(c_net_bio))) {
185*e7be843bSPierre Pronchery             c_net_bio_own = NULL; /* SSL_free will free the first reference. */
186*e7be843bSPierre Pronchery             goto err;
187*e7be843bSPierre Pronchery         }
188*e7be843bSPierre Pronchery     }
189*e7be843bSPierre Pronchery 
190*e7be843bSPierre Pronchery     SSL_set0_wbio(c_ssl, c_net_bio);
191*e7be843bSPierre Pronchery     c_net_bio_own = NULL;
192*e7be843bSPierre Pronchery 
193*e7be843bSPierre Pronchery     if (!TEST_true(SSL_set_blocking_mode(c_ssl, 0)))
194*e7be843bSPierre Pronchery         goto err;
195*e7be843bSPierre Pronchery 
196*e7be843bSPierre Pronchery     /*
197*e7be843bSPierre Pronchery      * We use real time for the timeout not fake time. Otherwise with fake time
198*e7be843bSPierre Pronchery      * we could hit a hang if we never increment the fake time
199*e7be843bSPierre Pronchery      */
200*e7be843bSPierre Pronchery     start_time = real_now(NULL);
201*e7be843bSPierre Pronchery 
202*e7be843bSPierre Pronchery     for (;;) {
203*e7be843bSPierre Pronchery         if (ossl_time_compare(ossl_time_subtract(real_now(NULL), start_time),
204*e7be843bSPierre Pronchery                               ossl_ms2time(limit_ms)) >= 0) {
205*e7be843bSPierre Pronchery             TEST_error("timeout while attempting QUIC server test");
206*e7be843bSPierre Pronchery             goto err;
207*e7be843bSPierre Pronchery         }
208*e7be843bSPierre Pronchery 
209*e7be843bSPierre Pronchery         if (!c_start_idle_test) {
210*e7be843bSPierre Pronchery             ret = SSL_connect(c_ssl);
211*e7be843bSPierre Pronchery             if (!TEST_true(ret == 1 || is_want(c_ssl, ret)))
212*e7be843bSPierre Pronchery                 goto err;
213*e7be843bSPierre Pronchery 
214*e7be843bSPierre Pronchery             if (ret == 1) {
215*e7be843bSPierre Pronchery                 c_connected = 1;
216*e7be843bSPierre Pronchery             } else {
217*e7be843bSPierre Pronchery                 /*
218*e7be843bSPierre Pronchery                  * keep timer ticking to keep handshake running.
219*e7be843bSPierre Pronchery                  * The timer is important for calculation of ping deadline.
220*e7be843bSPierre Pronchery                  * If things stall for whatever reason we at least send
221*e7be843bSPierre Pronchery                  * ACK eliciting ping to let peer know we are here ready
222*e7be843bSPierre Pronchery                  * to hear back.
223*e7be843bSPierre Pronchery                  */
224*e7be843bSPierre Pronchery                 if (!TEST_true(CRYPTO_THREAD_write_lock(fake_time_lock)))
225*e7be843bSPierre Pronchery                     goto err;
226*e7be843bSPierre Pronchery                 fake_time = ossl_time_add(fake_time, ossl_ms2time(100));
227*e7be843bSPierre Pronchery                 CRYPTO_THREAD_unlock(fake_time_lock);
228*e7be843bSPierre Pronchery             }
229*e7be843bSPierre Pronchery         }
230*e7be843bSPierre Pronchery 
231*e7be843bSPierre Pronchery         if (c_connected && !c_write_done) {
232*e7be843bSPierre Pronchery             if (!TEST_int_eq(SSL_write(c_ssl, msg1, sizeof(msg1) - 1),
233*e7be843bSPierre Pronchery                              (int)sizeof(msg1) - 1))
234*e7be843bSPierre Pronchery                 goto err;
235*e7be843bSPierre Pronchery 
236*e7be843bSPierre Pronchery             if (!TEST_true(SSL_stream_conclude(c_ssl, 0)))
237*e7be843bSPierre Pronchery                 goto err;
238*e7be843bSPierre Pronchery 
239*e7be843bSPierre Pronchery             c_write_done = 1;
240*e7be843bSPierre Pronchery         }
241*e7be843bSPierre Pronchery 
242*e7be843bSPierre Pronchery         if (c_connected && c_write_done && !s_read_done) {
243*e7be843bSPierre Pronchery             if (!ossl_quic_tserver_read(tserver, 0,
244*e7be843bSPierre Pronchery                                         (unsigned char *)msg2 + s_total_read,
245*e7be843bSPierre Pronchery                                         sizeof(msg2) - s_total_read, &l)) {
246*e7be843bSPierre Pronchery                 if (!TEST_true(ossl_quic_tserver_has_read_ended(tserver, 0)))
247*e7be843bSPierre Pronchery                     goto err;
248*e7be843bSPierre Pronchery 
249*e7be843bSPierre Pronchery                 if (!TEST_mem_eq(msg1, sizeof(msg1) - 1, msg2, s_total_read))
250*e7be843bSPierre Pronchery                     goto err;
251*e7be843bSPierre Pronchery 
252*e7be843bSPierre Pronchery                 s_begin_write = 1;
253*e7be843bSPierre Pronchery                 s_read_done   = 1;
254*e7be843bSPierre Pronchery             } else {
255*e7be843bSPierre Pronchery                 s_total_read += l;
256*e7be843bSPierre Pronchery                 if (!TEST_size_t_le(s_total_read, sizeof(msg1) - 1))
257*e7be843bSPierre Pronchery                     goto err;
258*e7be843bSPierre Pronchery             }
259*e7be843bSPierre Pronchery         }
260*e7be843bSPierre Pronchery 
261*e7be843bSPierre Pronchery         if (s_begin_write && s_total_written < sizeof(msg1) - 1) {
262*e7be843bSPierre Pronchery             if (!TEST_true(ossl_quic_tserver_write(tserver, 0,
263*e7be843bSPierre Pronchery                                                    (unsigned char *)msg2 + s_total_written,
264*e7be843bSPierre Pronchery                                                    sizeof(msg1) - 1 - s_total_written, &l)))
265*e7be843bSPierre Pronchery                 goto err;
266*e7be843bSPierre Pronchery 
267*e7be843bSPierre Pronchery             s_total_written += l;
268*e7be843bSPierre Pronchery 
269*e7be843bSPierre Pronchery             if (s_total_written == sizeof(msg1) - 1) {
270*e7be843bSPierre Pronchery                 ossl_quic_tserver_conclude(tserver, 0);
271*e7be843bSPierre Pronchery                 c_begin_read = 1;
272*e7be843bSPierre Pronchery             }
273*e7be843bSPierre Pronchery         }
274*e7be843bSPierre Pronchery 
275*e7be843bSPierre Pronchery         if (c_begin_read && c_total_read < sizeof(msg1) - 1) {
276*e7be843bSPierre Pronchery             ret = SSL_read_ex(c_ssl, msg3 + c_total_read,
277*e7be843bSPierre Pronchery                               sizeof(msg1) - 1 - c_total_read, &l);
278*e7be843bSPierre Pronchery             if (!TEST_true(ret == 1 || is_want(c_ssl, ret)))
279*e7be843bSPierre Pronchery                 goto err;
280*e7be843bSPierre Pronchery 
281*e7be843bSPierre Pronchery             c_total_read += l;
282*e7be843bSPierre Pronchery 
283*e7be843bSPierre Pronchery             if (c_total_read == sizeof(msg1) - 1) {
284*e7be843bSPierre Pronchery                 if (!TEST_mem_eq(msg1, sizeof(msg1) - 1,
285*e7be843bSPierre Pronchery                                  msg3, c_total_read))
286*e7be843bSPierre Pronchery                     goto err;
287*e7be843bSPierre Pronchery 
288*e7be843bSPierre Pronchery                 c_wait_eos = 1;
289*e7be843bSPierre Pronchery             }
290*e7be843bSPierre Pronchery         }
291*e7be843bSPierre Pronchery 
292*e7be843bSPierre Pronchery         if (c_wait_eos && !c_done_eos) {
293*e7be843bSPierre Pronchery             unsigned char c;
294*e7be843bSPierre Pronchery 
295*e7be843bSPierre Pronchery             ret = SSL_read_ex(c_ssl, &c, sizeof(c), &l);
296*e7be843bSPierre Pronchery             if (!TEST_false(ret))
297*e7be843bSPierre Pronchery                 goto err;
298*e7be843bSPierre Pronchery 
299*e7be843bSPierre Pronchery             /*
300*e7be843bSPierre Pronchery              * Allow the implementation to take as long as it wants to finally
301*e7be843bSPierre Pronchery              * notice EOS. Account for varied timings in OS networking stacks.
302*e7be843bSPierre Pronchery              */
303*e7be843bSPierre Pronchery             if (SSL_get_error(c_ssl, ret) != SSL_ERROR_WANT_READ) {
304*e7be843bSPierre Pronchery                 if (!TEST_int_eq(SSL_get_error(c_ssl, ret),
305*e7be843bSPierre Pronchery                                  SSL_ERROR_ZERO_RETURN))
306*e7be843bSPierre Pronchery                     goto err;
307*e7be843bSPierre Pronchery 
308*e7be843bSPierre Pronchery                 c_done_eos = 1;
309*e7be843bSPierre Pronchery                 if (use_thread_assist && use_fake_time) {
310*e7be843bSPierre Pronchery                     if (!TEST_true(ossl_quic_tserver_is_connected(tserver)))
311*e7be843bSPierre Pronchery                         goto err;
312*e7be843bSPierre Pronchery                     c_start_idle_test = 1;
313*e7be843bSPierre Pronchery                     limit_ms = 120000; /* extend time limit */
314*e7be843bSPierre Pronchery                 } else {
315*e7be843bSPierre Pronchery                     /* DONE */
316*e7be843bSPierre Pronchery                     break;
317*e7be843bSPierre Pronchery                 }
318*e7be843bSPierre Pronchery             }
319*e7be843bSPierre Pronchery         }
320*e7be843bSPierre Pronchery 
321*e7be843bSPierre Pronchery         if (c_start_idle_test && !c_done_idle_test) {
322*e7be843bSPierre Pronchery             /* This is more than our default idle timeout of 30s. */
323*e7be843bSPierre Pronchery             if (idle_units_done < 600) {
324*e7be843bSPierre Pronchery                 struct timeval tv;
325*e7be843bSPierre Pronchery                 int isinf;
326*e7be843bSPierre Pronchery 
327*e7be843bSPierre Pronchery                 if (!TEST_true(CRYPTO_THREAD_write_lock(fake_time_lock)))
328*e7be843bSPierre Pronchery                     goto err;
329*e7be843bSPierre Pronchery                 fake_time = ossl_time_add(fake_time, ossl_ms2time(100));
330*e7be843bSPierre Pronchery                 CRYPTO_THREAD_unlock(fake_time_lock);
331*e7be843bSPierre Pronchery 
332*e7be843bSPierre Pronchery                 ++idle_units_done;
333*e7be843bSPierre Pronchery                 ossl_quic_conn_force_assist_thread_wake(c_ssl);
334*e7be843bSPierre Pronchery 
335*e7be843bSPierre Pronchery                 /*
336*e7be843bSPierre Pronchery                  * If the event timeout has expired then give the assistance
337*e7be843bSPierre Pronchery                  * thread a chance to catch up
338*e7be843bSPierre Pronchery                  */
339*e7be843bSPierre Pronchery                 if (!TEST_true(SSL_get_event_timeout(c_ssl, &tv, &isinf)))
340*e7be843bSPierre Pronchery                     goto err;
341*e7be843bSPierre Pronchery                 if (!isinf && ossl_time_compare(ossl_time_zero(),
342*e7be843bSPierre Pronchery                                                 ossl_time_from_timeval(tv)) >= 0)
343*e7be843bSPierre Pronchery                     OSSL_sleep(100); /* Ensure CPU scheduling for test purposes */
344*e7be843bSPierre Pronchery             } else {
345*e7be843bSPierre Pronchery                 c_done_idle_test = 1;
346*e7be843bSPierre Pronchery             }
347*e7be843bSPierre Pronchery         }
348*e7be843bSPierre Pronchery 
349*e7be843bSPierre Pronchery         if (c_done_idle_test) {
350*e7be843bSPierre Pronchery             /*
351*e7be843bSPierre Pronchery              * If we have finished the fake idling duration, the connection
352*e7be843bSPierre Pronchery              * should still be healthy in TA mode.
353*e7be843bSPierre Pronchery              */
354*e7be843bSPierre Pronchery             if (!TEST_true(ossl_quic_tserver_is_connected(tserver)))
355*e7be843bSPierre Pronchery                 goto err;
356*e7be843bSPierre Pronchery 
357*e7be843bSPierre Pronchery             /* DONE */
358*e7be843bSPierre Pronchery             break;
359*e7be843bSPierre Pronchery         }
360*e7be843bSPierre Pronchery 
361*e7be843bSPierre Pronchery         /*
362*e7be843bSPierre Pronchery          * This is inefficient because we spin until things work without
363*e7be843bSPierre Pronchery          * blocking but this is just a test.
364*e7be843bSPierre Pronchery          */
365*e7be843bSPierre Pronchery         if (!c_start_idle_test || c_done_idle_test) {
366*e7be843bSPierre Pronchery             /* Inhibit manual ticking during idle test to test TA mode. */
367*e7be843bSPierre Pronchery             SSL_handle_events(c_ssl);
368*e7be843bSPierre Pronchery         }
369*e7be843bSPierre Pronchery 
370*e7be843bSPierre Pronchery         ossl_quic_tserver_tick(tserver);
371*e7be843bSPierre Pronchery 
372*e7be843bSPierre Pronchery         if (use_inject) {
373*e7be843bSPierre Pronchery             BIO_MSG rmsg = {0};
374*e7be843bSPierre Pronchery             size_t msgs_processed = 0;
375*e7be843bSPierre Pronchery 
376*e7be843bSPierre Pronchery             for (;;) {
377*e7be843bSPierre Pronchery                 /*
378*e7be843bSPierre Pronchery                  * Manually spoonfeed received datagrams from the real BIO_dgram
379*e7be843bSPierre Pronchery                  * into QUIC via the injection interface, thereby testing the
380*e7be843bSPierre Pronchery                  * injection interface.
381*e7be843bSPierre Pronchery                  */
382*e7be843bSPierre Pronchery                 rmsg.data       = scratch_buf;
383*e7be843bSPierre Pronchery                 rmsg.data_len   = sizeof(scratch_buf);
384*e7be843bSPierre Pronchery 
385*e7be843bSPierre Pronchery                 if (!BIO_recvmmsg(c_net_bio, &rmsg, sizeof(rmsg), 1, 0, &msgs_processed)
386*e7be843bSPierre Pronchery                     || msgs_processed == 0 || rmsg.data_len == 0)
387*e7be843bSPierre Pronchery                     break;
388*e7be843bSPierre Pronchery 
389*e7be843bSPierre Pronchery                 if (!TEST_true(SSL_inject_net_dgram(c_ssl, rmsg.data, rmsg.data_len,
390*e7be843bSPierre Pronchery                                                     NULL, NULL)))
391*e7be843bSPierre Pronchery                     goto err;
392*e7be843bSPierre Pronchery             }
393*e7be843bSPierre Pronchery         }
394*e7be843bSPierre Pronchery     }
395*e7be843bSPierre Pronchery 
396*e7be843bSPierre Pronchery     testresult = 1;
397*e7be843bSPierre Pronchery err:
398*e7be843bSPierre Pronchery     SSL_free(c_ssl);
399*e7be843bSPierre Pronchery     SSL_CTX_free(c_ctx);
400*e7be843bSPierre Pronchery     ossl_quic_tserver_free(tserver);
401*e7be843bSPierre Pronchery     BIO_ADDR_free(s_addr_);
402*e7be843bSPierre Pronchery     BIO_free(s_net_bio_own);
403*e7be843bSPierre Pronchery     BIO_free(c_net_bio_own);
404*e7be843bSPierre Pronchery     BIO_free(c_pair_own);
405*e7be843bSPierre Pronchery     BIO_free(s_pair_own);
406*e7be843bSPierre Pronchery     if (s_fd >= 0)
407*e7be843bSPierre Pronchery         BIO_closesocket(s_fd);
408*e7be843bSPierre Pronchery     if (c_fd >= 0)
409*e7be843bSPierre Pronchery         BIO_closesocket(c_fd);
410*e7be843bSPierre Pronchery     return testresult;
411*e7be843bSPierre Pronchery }
412*e7be843bSPierre Pronchery 
test_tserver(int idx)413*e7be843bSPierre Pronchery static int test_tserver(int idx)
414*e7be843bSPierre Pronchery {
415*e7be843bSPierre Pronchery     int thread_assisted, use_fake_time, use_inject;
416*e7be843bSPierre Pronchery 
417*e7be843bSPierre Pronchery     thread_assisted = idx % 2;
418*e7be843bSPierre Pronchery     idx /= 2;
419*e7be843bSPierre Pronchery 
420*e7be843bSPierre Pronchery     use_inject = idx % 2;
421*e7be843bSPierre Pronchery     idx /= 2;
422*e7be843bSPierre Pronchery 
423*e7be843bSPierre Pronchery     use_fake_time = idx % 2;
424*e7be843bSPierre Pronchery 
425*e7be843bSPierre Pronchery     if (use_fake_time && !thread_assisted)
426*e7be843bSPierre Pronchery         return 1;
427*e7be843bSPierre Pronchery 
428*e7be843bSPierre Pronchery     return do_test(thread_assisted, use_fake_time, use_inject);
429*e7be843bSPierre Pronchery }
430*e7be843bSPierre Pronchery 
431*e7be843bSPierre Pronchery OPT_TEST_DECLARE_USAGE("certfile privkeyfile\n")
432*e7be843bSPierre Pronchery 
setup_tests(void)433*e7be843bSPierre Pronchery int setup_tests(void)
434*e7be843bSPierre Pronchery {
435*e7be843bSPierre Pronchery     if (!test_skip_common_options()) {
436*e7be843bSPierre Pronchery         TEST_error("Error parsing test options\n");
437*e7be843bSPierre Pronchery         return 0;
438*e7be843bSPierre Pronchery     }
439*e7be843bSPierre Pronchery 
440*e7be843bSPierre Pronchery     if (!TEST_ptr(certfile = test_get_argument(0))
441*e7be843bSPierre Pronchery             || !TEST_ptr(keyfile = test_get_argument(1)))
442*e7be843bSPierre Pronchery         return 0;
443*e7be843bSPierre Pronchery 
444*e7be843bSPierre Pronchery     if ((fake_time_lock = CRYPTO_THREAD_lock_new()) == NULL)
445*e7be843bSPierre Pronchery         return 0;
446*e7be843bSPierre Pronchery 
447*e7be843bSPierre Pronchery     ADD_ALL_TESTS(test_tserver, 2 * 2 * 2);
448*e7be843bSPierre Pronchery     return 1;
449*e7be843bSPierre Pronchery }
450