QUIC Test Server: Basic echo server test
[openssl.git] / test / quic_tserver_test.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 #include <openssl/ssl.h>
10 #include <openssl/quic.h>
11 #include <openssl/bio.h>
12 #include "internal/common.h"
13 #include "internal/sockets.h"
14 #include "internal/quic_tserver.h"
15 #include "internal/time.h"
16 #include "testutil.h"
17
18 static const char msg1[] = "The quick brown fox jumped over the lazy dogs.";
19 static char msg2[1024], msg3[1024];
20
21 static int is_want(SSL *s, int ret)
22 {
23     int ec = SSL_get_error(s, ret);
24     return ec == SSL_ERROR_WANT_READ || ec == SSL_ERROR_WANT_WRITE;
25 }
26
27 static int test_tserver(void)
28 {
29     int testresult = 0, ret;
30     int s_fd = -1, c_fd = -1;
31     BIO *s_net_bio = NULL, *s_net_bio_own = NULL;
32     BIO *c_net_bio = NULL, *c_net_bio_own = NULL;
33     QUIC_TSERVER_ARGS tserver_args = {0};
34     QUIC_TSERVER *tserver = NULL;
35     BIO_ADDR *s_addr_ = NULL;
36     struct in_addr ina = {0};
37     union BIO_sock_info_u s_info = {0};
38     SSL_CTX *c_ctx = NULL;
39     SSL *c_ssl = NULL;
40     short port = 8186;
41     int c_connected = 0, c_write_done = 0, c_begin_read = 0;
42     size_t l = 0, s_total_read = 0, s_total_written = 0, c_total_read = 0;
43     int s_begin_write = 0;
44     OSSL_TIME start_time;
45
46     ina.s_addr = htonl(0x7f000001UL);
47
48     /* Setup test server. */
49     s_fd = BIO_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, 0);
50     if (!TEST_int_ge(s_fd, 0))
51         goto err;
52
53     if (!TEST_true(BIO_socket_nbio(s_fd, 1)))
54         goto err;
55
56     if (!TEST_ptr(s_addr_ = BIO_ADDR_new()))
57         goto err;
58
59     if (!TEST_true(BIO_ADDR_rawmake(s_addr_, AF_INET, &ina, sizeof(ina),
60                                     htons(port))))
61         goto err;
62
63     if (!TEST_true(BIO_bind(s_fd, s_addr_, 0)))
64         goto err;
65
66     s_info.addr = s_addr_;
67     if (!TEST_true(BIO_sock_info(s_fd, BIO_SOCK_INFO_ADDRESS, &s_info)))
68         goto err;
69
70     if (!TEST_int_gt(BIO_ADDR_rawport(s_addr_), 0))
71         goto err;
72
73     if (!TEST_ptr(s_net_bio = s_net_bio_own = BIO_new_dgram(s_fd, 0)))
74         goto err;
75
76     if (!BIO_up_ref(s_net_bio))
77         goto err;
78
79     tserver_args.net_rbio = s_net_bio;
80     tserver_args.net_wbio = s_net_bio;
81
82     if (!TEST_ptr(tserver = ossl_quic_tserver_new(&tserver_args))) {
83         BIO_free(s_net_bio);
84         goto err;
85     }
86
87     s_net_bio_own = NULL;
88
89     /* Setup test client. */
90     c_fd = BIO_socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP, 0);
91     if (!TEST_int_ge(c_fd, 0))
92         goto err;
93
94     if (!TEST_true(BIO_socket_nbio(c_fd, 1)))
95         goto err;
96
97     if (!TEST_ptr(c_net_bio = c_net_bio_own = BIO_new_dgram(c_fd, 0)))
98         goto err;
99
100     if (!BIO_dgram_set_peer(c_net_bio, s_addr_))
101         goto err;
102
103     if (!TEST_ptr(c_ctx = SSL_CTX_new(OSSL_QUIC_client_method())))
104         goto err;
105
106     if (!TEST_ptr(c_ssl = SSL_new(c_ctx)))
107         goto err;
108
109     /* Takes ownership of our reference to the BIO. */
110     SSL_set0_rbio(c_ssl, c_net_bio);
111
112     /* Get another reference to be transferred in the SSL_set0_wbio call. */
113     if (!TEST_true(BIO_up_ref(c_net_bio))) {
114         c_net_bio_own = NULL; /* SSL_free will free the first reference. */
115         goto err;
116     }
117
118     SSL_set0_wbio(c_ssl, c_net_bio);
119     c_net_bio_own = NULL;
120
121     if (!TEST_true(SSL_set_blocking_mode(c_ssl, 0)))
122         goto err;
123
124     start_time = ossl_time_now();
125
126     for (;;) {
127         if (ossl_time_compare(ossl_time_subtract(ossl_time_now(), start_time),
128                               ossl_ms2time(1000)) >= 0) {
129             TEST_error("timeout while attempting QUIC server test");
130             goto err;
131         }
132
133         ret = SSL_connect(c_ssl);
134         if (!TEST_true(ret == 1 || is_want(c_ssl, ret)))
135             goto err;
136
137         if (ret == 1)
138             c_connected = 1;
139
140         if (c_connected && !c_write_done) {
141             if (!TEST_int_eq(SSL_write(c_ssl, msg1, sizeof(msg1) - 1),
142                              (int)sizeof(msg1) - 1))
143                 goto err;
144
145             c_write_done = 1;
146         }
147
148         if (c_connected && c_write_done && s_total_read < sizeof(msg1) - 1) {
149             if (!TEST_true(ossl_quic_tserver_read(tserver,
150                                                   (unsigned char *)msg2 + s_total_read,
151                                                   sizeof(msg2) - s_total_read, &l)))
152                 goto err;
153
154             s_total_read += l;
155             if (s_total_read == sizeof(msg1) - 1) {
156                 if (!TEST_mem_eq(msg1, sizeof(msg1) - 1,
157                                  msg2, sizeof(msg1) - 1))
158                     goto err;
159
160                 s_begin_write = 1;
161             }
162         }
163
164         if (s_begin_write && s_total_written < sizeof(msg1) - 1) {
165             if (!TEST_true(ossl_quic_tserver_write(tserver,
166                                                    (unsigned char *)msg2 + s_total_written,
167                                                    sizeof(msg1) - 1 - s_total_written, &l)))
168                 goto err;
169
170             s_total_written += l;
171
172             if (s_total_written == sizeof(msg1) - 1)
173                 c_begin_read = 1;
174         }
175
176         if (c_begin_read && c_total_read < sizeof(msg1) - 1) {
177             ret = SSL_read_ex(c_ssl, msg3 + c_total_read,
178                               sizeof(msg1) - 1 - c_total_read, &l);
179             if (!TEST_true(ret == 1 || is_want(c_ssl, ret)))
180                 goto err;
181
182             c_total_read += l;
183
184             if (c_total_read == sizeof(msg1) - 1) {
185                 if (!TEST_mem_eq(msg1, sizeof(msg1) - 1,
186                                  msg3, c_total_read))
187                     goto err;
188
189                 /* MATCH */
190                 break;
191             }
192         }
193
194         /*
195          * This is inefficient because we spin until things work without
196          * blocking but this is just a test.
197          */
198         SSL_tick(c_ssl);
199         ossl_quic_tserver_tick(tserver);
200     }
201
202     testresult = 1;
203 err:
204     SSL_free(c_ssl);
205     SSL_CTX_free(c_ctx);
206     ossl_quic_tserver_free(tserver);
207     BIO_ADDR_free(s_addr_);
208     BIO_free(s_net_bio_own);
209     BIO_free(c_net_bio_own);
210     if (s_fd >= 0)
211         BIO_closesocket(s_fd);
212     if (c_fd >= 0)
213         BIO_closesocket(c_fd);
214     return testresult;
215 }
216
217 int setup_tests(void)
218 {
219     ADD_TEST(test_tserver);
220     return 1;
221 }