ef447b78c324ddebc1f4249a15c7f6303426d145
[openssl.git] / ssl / quic / quic_reactor.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 "internal/quic_reactor.h"
10 #include "internal/common.h"
11 #include "internal/thread_arch.h"
12
13 /*
14  * Core I/O Reactor Framework
15  * ==========================
16  */
17 void ossl_quic_reactor_init(QUIC_REACTOR *rtor,
18                             void (*tick_cb)(QUIC_TICK_RESULT *res, void *arg,
19                                             uint32_t flags),
20                             void *tick_cb_arg,
21                             OSSL_TIME initial_tick_deadline)
22 {
23     rtor->poll_r.type       = BIO_POLL_DESCRIPTOR_TYPE_NONE;
24     rtor->poll_w.type       = BIO_POLL_DESCRIPTOR_TYPE_NONE;
25     rtor->net_read_desired  = 0;
26     rtor->net_write_desired = 0;
27     rtor->tick_deadline     = initial_tick_deadline;
28
29     rtor->tick_cb           = tick_cb;
30     rtor->tick_cb_arg       = tick_cb_arg;
31 }
32
33 void ossl_quic_reactor_set_poll_r(QUIC_REACTOR *rtor, const BIO_POLL_DESCRIPTOR *r)
34 {
35     rtor->poll_r = *r;
36 }
37
38 void ossl_quic_reactor_set_poll_w(QUIC_REACTOR *rtor, const BIO_POLL_DESCRIPTOR *w)
39 {
40     rtor->poll_w = *w;
41 }
42
43 const BIO_POLL_DESCRIPTOR *ossl_quic_reactor_get_poll_r(QUIC_REACTOR *rtor)
44 {
45     return &rtor->poll_r;
46 }
47
48 const BIO_POLL_DESCRIPTOR *ossl_quic_reactor_get_poll_w(QUIC_REACTOR *rtor)
49 {
50     return &rtor->poll_w;
51 }
52
53 int ossl_quic_reactor_net_read_desired(QUIC_REACTOR *rtor)
54 {
55     return rtor->net_read_desired;
56 }
57
58 int ossl_quic_reactor_net_write_desired(QUIC_REACTOR *rtor)
59 {
60     return rtor->net_write_desired;
61 }
62
63 OSSL_TIME ossl_quic_reactor_get_tick_deadline(QUIC_REACTOR *rtor)
64 {
65     return rtor->tick_deadline;
66 }
67
68 int ossl_quic_reactor_tick(QUIC_REACTOR *rtor, uint32_t flags)
69 {
70     QUIC_TICK_RESULT res = {0};
71
72     /*
73      * Note that the tick callback cannot fail; this is intentional. Arguably it
74      * does not make that much sense for ticking to 'fail' (in the sense of an
75      * explicit error indicated to the user) because ticking is by its nature
76      * best effort. If something fatal happens with a connection we can report
77      * it on the next actual application I/O call.
78      */
79     rtor->tick_cb(&res, rtor->tick_cb_arg, flags);
80
81     rtor->net_read_desired  = res.net_read_desired;
82     rtor->net_write_desired = res.net_write_desired;
83     rtor->tick_deadline     = res.tick_deadline;
84     return 1;
85 }
86
87 /*
88  * Blocking I/O Adaptation Layer
89  * =============================
90  */
91
92 /*
93  * Utility which can be used to poll on up to two FDs. This is designed to
94  * support use of split FDs (e.g. with SSL_set_rfd and SSL_set_wfd where
95  * different FDs are used for read and write).
96  *
97  * Generally use of poll(2) is preferred where available. Windows, however,
98  * hasn't traditionally offered poll(2), only select(2). WSAPoll() was
99  * introduced in Vista but has seemingly been buggy until relatively recent
100  * versions of Windows 10. Moreover we support XP so this is not a suitable
101  * target anyway. However, the traditional issues with select(2) turn out not to
102  * be an issue on Windows; whereas traditional *NIX select(2) uses a bitmap of
103  * FDs (and thus is limited in the magnitude of the FDs expressible), Windows
104  * select(2) is very different. In Windows, socket handles are not allocated
105  * contiguously from zero and thus this bitmap approach was infeasible. Thus in
106  * adapting the Berkeley sockets API to Windows a different approach was taken
107  * whereby the fd_set contains a fixed length array of socket handles and an
108  * integer indicating how many entries are valid; thus Windows select()
109  * ironically is actually much more like *NIX poll(2) than *NIX select(2). In
110  * any case, this means that the relevant limit for Windows select() is the
111  * number of FDs being polled, not the magnitude of those FDs. Since we only
112  * poll for two FDs here, this limit does not concern us.
113  *
114  * Usage: rfd and wfd may be the same or different. Either or both may also be
115  * -1. If rfd_want_read is 1, rfd is polled for readability, and if
116  * wfd_want_write is 1, wfd is polled for writability. Note that since any
117  * passed FD is always polled for error conditions, setting rfd_want_read=0 and
118  * wfd_want_write=0 is not the same as passing -1 for both FDs.
119  *
120  * deadline is a timestamp to return at. If it is ossl_time_infinite(), the call
121  * never times out.
122  *
123  * Returns 0 on error and 1 on success. Timeout expiry is considered a success
124  * condition. We don't elaborate our return values here because the way we are
125  * actually using this doesn't currently care.
126  *
127  * If mutex is non-NULL, it is assumed to be held for write and is unlocked for
128  * the duration of the call.
129  *
130  * Precondition:   mutex is NULL or is held for write (unchecked)
131  * Postcondition:  mutex is NULL or is held for write (unless
132  *                   CRYPTO_THREAD_write_lock fails)
133  */
134 static int poll_two_fds(int rfd, int rfd_want_read,
135                         int wfd, int wfd_want_write,
136                         OSSL_TIME deadline,
137                         CRYPTO_MUTEX *mutex)
138 {
139 #if defined(OPENSSL_SYS_WINDOWS) || !defined(POLLIN)
140     fd_set rfd_set, wfd_set, efd_set;
141     OSSL_TIME now, timeout;
142     struct timeval tv, *ptv;
143     int maxfd, pres;
144
145 # ifndef OPENSSL_SYS_WINDOWS
146     /*
147      * On Windows there is no relevant limit to the magnitude of a fd value (see
148      * above). On *NIX the fd_set uses a bitmap and we must check the limit.
149      */
150     if (rfd >= FD_SETSIZE || wfd >= FD_SETSIZE)
151         return 0;
152 # endif
153
154     FD_ZERO(&rfd_set);
155     FD_ZERO(&wfd_set);
156     FD_ZERO(&efd_set);
157
158     if (rfd != -1 && rfd_want_read)
159         openssl_fdset(rfd, &rfd_set);
160     if (wfd != -1 && wfd_want_write)
161         openssl_fdset(wfd, &wfd_set);
162
163     /* Always check for error conditions. */
164     if (rfd != -1)
165         openssl_fdset(rfd, &efd_set);
166     if (wfd != -1)
167         openssl_fdset(wfd, &efd_set);
168
169     maxfd = rfd;
170     if (wfd > maxfd)
171         maxfd = wfd;
172
173     if (!ossl_assert(rfd != -1 || wfd != -1
174                      || !ossl_time_is_infinite(deadline)))
175         /* Do not block forever; should not happen. */
176         return 0;
177
178 # if defined(OPENSSL_THREADS)
179     if (mutex != NULL)
180         ossl_crypto_mutex_unlock(mutex);
181 # endif
182
183     do {
184         /*
185          * select expects a timeout, not a deadline, so do the conversion.
186          * Update for each call to ensure the correct value is used if we repeat
187          * due to EINTR.
188          */
189         if (ossl_time_is_infinite(deadline)) {
190             ptv = NULL;
191         } else {
192             now = ossl_time_now();
193             /*
194              * ossl_time_subtract saturates to zero so we don't need to check if
195              * now > deadline.
196              */
197             timeout = ossl_time_subtract(deadline, now);
198             tv      = ossl_time_to_timeval(timeout);
199             ptv     = &tv;
200         }
201
202         pres = select(maxfd + 1, &rfd_set, &wfd_set, &efd_set, ptv);
203     } while (pres == -1 && get_last_socket_error_is_eintr());
204
205 # if defined(OPENSSL_THREADS)
206     if (mutex != NULL)
207         ossl_crypto_mutex_lock(mutex);
208 # endif
209
210     return pres < 0 ? 0 : 1;
211 #else
212     int pres, timeout_ms;
213     OSSL_TIME now, timeout;
214     struct pollfd pfds[2] = {0};
215     size_t npfd = 0;
216
217     if (rfd == wfd) {
218         pfds[npfd].fd = rfd;
219         pfds[npfd].events = (rfd_want_read  ? POLLIN  : 0)
220                           | (wfd_want_write ? POLLOUT : 0);
221         if (rfd >= 0 && pfds[npfd].events != 0)
222             ++npfd;
223     } else {
224         pfds[npfd].fd     = rfd;
225         pfds[npfd].events = (rfd_want_read ? POLLIN : 0);
226         if (rfd >= 0 && pfds[npfd].events != 0)
227             ++npfd;
228
229         pfds[npfd].fd     = wfd;
230         pfds[npfd].events = (wfd_want_write ? POLLOUT : 0);
231         if (wfd >= 0 && pfds[npfd].events != 0)
232             ++npfd;
233     }
234
235     if (!ossl_assert(npfd != 0 || !ossl_time_is_infinite(deadline)))
236         /* Do not block forever; should not happen. */
237         return 0;
238
239 # if defined(OPENSSL_THREADS)
240     if (mutex != NULL)
241         ossl_crypto_mutex_unlock(mutex);
242 # endif
243
244     do {
245         if (ossl_time_is_infinite(deadline)) {
246             timeout_ms = -1;
247         } else {
248             now         = ossl_time_now();
249             timeout     = ossl_time_subtract(deadline, now);
250             timeout_ms  = ossl_time2ms(timeout);
251         }
252
253         pres = poll(pfds, npfd, timeout_ms);
254     } while (pres == -1 && get_last_socket_error_is_eintr());
255
256 # if defined(OPENSSL_THREADS)
257     if (mutex != NULL)
258         ossl_crypto_mutex_lock(mutex);
259 # endif
260
261     return pres < 0 ? 0 : 1;
262 #endif
263 }
264
265 static int poll_descriptor_to_fd(const BIO_POLL_DESCRIPTOR *d, int *fd)
266 {
267     if (d == NULL || d->type == BIO_POLL_DESCRIPTOR_TYPE_NONE) {
268         *fd = INVALID_SOCKET;
269         return 1;
270     }
271
272     if (d->type != BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD
273             || d->value.fd == INVALID_SOCKET)
274         return 0;
275
276     *fd = d->value.fd;
277     return 1;
278 }
279
280 /*
281  * Poll up to two abstract poll descriptors. Currently we only support
282  * poll descriptors which represent FDs.
283  *
284  * If mutex is non-NULL, it is assumed be a lock currently held for write and is
285  * unlocked for the duration of any wait.
286  *
287  * Precondition:   mutex is NULL or is held for write (unchecked)
288  * Postcondition:  mutex is NULL or is held for write (unless
289  *                   CRYPTO_THREAD_write_lock fails)
290  */
291 static int poll_two_descriptors(const BIO_POLL_DESCRIPTOR *r, int r_want_read,
292                                 const BIO_POLL_DESCRIPTOR *w, int w_want_write,
293                                 OSSL_TIME deadline,
294                                 CRYPTO_MUTEX *mutex)
295 {
296     int rfd, wfd;
297
298     if (!poll_descriptor_to_fd(r, &rfd)
299         || !poll_descriptor_to_fd(w, &wfd))
300         return 0;
301
302     return poll_two_fds(rfd, r_want_read, wfd, w_want_write, deadline, mutex);
303 }
304
305 /*
306  * Block until a predicate function evaluates to true.
307  *
308  * If mutex is non-NULL, it is assumed be a lock currently held for write and is
309  * unlocked for the duration of any wait.
310  *
311  * Precondition:   Must hold channel write lock (unchecked)
312  * Precondition:   mutex is NULL or is held for write (unchecked)
313  * Postcondition:  mutex is NULL or is held for write (unless
314  *                   CRYPTO_THREAD_write_lock fails)
315  */
316 int ossl_quic_reactor_block_until_pred(QUIC_REACTOR *rtor,
317                                        int (*pred)(void *arg), void *pred_arg,
318                                        uint32_t flags,
319                                        CRYPTO_MUTEX *mutex)
320 {
321     int res;
322
323     for (;;) {
324         if ((flags & SKIP_FIRST_TICK) != 0)
325             flags &= ~SKIP_FIRST_TICK;
326         else
327             /* best effort */
328             ossl_quic_reactor_tick(rtor, 0);
329
330         if ((res = pred(pred_arg)) != 0)
331             return res;
332
333         if (!poll_two_descriptors(ossl_quic_reactor_get_poll_r(rtor),
334                                   ossl_quic_reactor_net_read_desired(rtor),
335                                   ossl_quic_reactor_get_poll_w(rtor),
336                                   ossl_quic_reactor_net_write_desired(rtor),
337                                   ossl_quic_reactor_get_tick_deadline(rtor),
338                                   mutex))
339             /*
340              * We don't actually care why the call succeeded (timeout, FD
341              * readiness), we just call reactor_tick and start trying to do I/O
342              * things again. If poll_two_fds returns 0, this is some other
343              * non-timeout failure and we should stop here.
344              *
345              * TODO(QUIC): In the future we could avoid unnecessary syscalls by
346              * not retrying network I/O that isn't ready based on the result of
347              * the poll call. However this might be difficult because it
348              * requires we do the call to poll(2) or equivalent syscall
349              * ourselves, whereas in the general case the application does the
350              * polling and just calls SSL_handle_events(). Implementing this
351              * optimisation in the future will probably therefore require API
352              * changes.
353              */
354             return 0;
355     }
356 }