/src/openssl/ssl/rio/poll_immediate.c
Line | Count | Source |
1 | | /* |
2 | | * Copyright 2024-2025 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/common.h" |
11 | | #include "internal/quic_ssl.h" |
12 | | #include "internal/quic_reactor_wait_ctx.h" |
13 | | #include "internal/ssl_unwrap.h" |
14 | | #include <openssl/ssl.h> |
15 | | #include <openssl/err.h> |
16 | | #include "../ssl_local.h" |
17 | | #include "poll_builder.h" |
18 | | |
19 | | #ifdef OPENSSL_NO_QUIC |
20 | | /* Stub type when QUIC is disabled so function signatures remain consistent */ |
21 | | typedef int QUIC_REACTOR_WAIT_CTX; |
22 | | #endif |
23 | | |
24 | | #if defined(_AIX) |
25 | | /* |
26 | | * Some versions of AIX define macros for events and revents for use when |
27 | | * accessing pollfd structures (see Github issue #24236). That interferes |
28 | | * with our use of these names here. We simply undef them. |
29 | | */ |
30 | | #undef revents |
31 | | #undef events |
32 | | #endif |
33 | | |
34 | | #define ITEM_N(items, stride, n) \ |
35 | 0 | (*(SSL_POLL_ITEM *)((char *)(items) + (n) * (stride))) |
36 | | |
37 | | #define FAIL_FROM(n) \ |
38 | 0 | do { \ |
39 | 0 | size_t j; \ |
40 | 0 | \ |
41 | 0 | for (j = (n); j < num_items; ++j) \ |
42 | 0 | ITEM_N(items, stride, j).revents = 0; \ |
43 | 0 | \ |
44 | 0 | ok = 0; \ |
45 | 0 | goto out; \ |
46 | 0 | } while (0) |
47 | | |
48 | | #define FAIL_ITEM(idx) \ |
49 | 0 | do { \ |
50 | 0 | size_t idx_ = (idx); \ |
51 | 0 | \ |
52 | 0 | ITEM_N(items, stride, idx_).revents = SSL_POLL_EVENT_F; \ |
53 | 0 | ++result_count; \ |
54 | 0 | FAIL_FROM(idx_ + 1); \ |
55 | 0 | } while (0) |
56 | | |
57 | | #ifndef OPENSSL_NO_QUIC |
58 | | /* |
59 | | * Test instrumentation only; see poll_builder.h. Always NULL in production |
60 | | * use. |
61 | | */ |
62 | | void (*ossl_quic_poll_translate_test_step_cb)(size_t idx, void *arg) = NULL; |
63 | | void *ossl_quic_poll_translate_test_step_cb_arg = NULL; |
64 | | |
65 | | static int poll_translate_ssl_quic(SSL *ssl, |
66 | | QUIC_REACTOR_WAIT_CTX *wctx, |
67 | | RIO_POLL_BUILDER *rpb, |
68 | | uint64_t events, |
69 | | int *abort_blocking) |
70 | 0 | { |
71 | 0 | BIO_POLL_DESCRIPTOR rd, wd; |
72 | 0 | int fd1 = -1, fd2 = -1, fd_nfy = -1; |
73 | 0 | int fd1_r = 0, fd1_w = 0, fd2_w = 0; |
74 | |
|
75 | 0 | if (SSL_net_read_desired(ssl)) { |
76 | 0 | if (!SSL_get_rpoll_descriptor(ssl, &rd)) { |
77 | 0 | ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, |
78 | 0 | "SSL_poll requires the network BIOs underlying " |
79 | 0 | "a QUIC SSL object provide poll descriptors"); |
80 | 0 | return 0; |
81 | 0 | } |
82 | | |
83 | 0 | if (rd.type != BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD) { |
84 | 0 | ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, |
85 | 0 | "SSL_poll requires the poll descriptors of the " |
86 | 0 | "network BIOs underlying a QUIC SSL object be " |
87 | 0 | "of socket type"); |
88 | 0 | return 0; |
89 | 0 | } |
90 | | |
91 | 0 | fd1 = rd.value.fd; |
92 | 0 | fd1_r = 1; |
93 | 0 | } |
94 | | |
95 | 0 | if (SSL_net_write_desired(ssl)) { |
96 | 0 | if (!SSL_get_wpoll_descriptor(ssl, &wd)) { |
97 | 0 | ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, |
98 | 0 | "SSL_poll requires the network BIOs underlying " |
99 | 0 | "a QUIC SSL object provide poll descriptors"); |
100 | 0 | return 0; |
101 | 0 | } |
102 | | |
103 | 0 | if (wd.type != BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD) { |
104 | 0 | ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, |
105 | 0 | "SSL_poll requires the poll descriptors of the " |
106 | 0 | "network BIOs underlying a QUIC SSL object be " |
107 | 0 | "of socket type"); |
108 | 0 | return 0; |
109 | 0 | } |
110 | | |
111 | 0 | fd2 = wd.value.fd; |
112 | 0 | fd2_w = 1; |
113 | 0 | } |
114 | | |
115 | 0 | if (fd2 == fd1) { |
116 | 0 | fd2 = -1; |
117 | 0 | fd1_w = fd2_w; |
118 | 0 | } |
119 | |
|
120 | 0 | if (fd1 != -1) |
121 | 0 | if (!ossl_rio_poll_builder_add_fd(rpb, fd1, fd1_r, fd1_w)) |
122 | 0 | return 0; |
123 | | |
124 | 0 | if (fd2 != -1 && fd2_w) |
125 | 0 | if (!ossl_rio_poll_builder_add_fd(rpb, fd2, /*r = */ 0, fd2_w)) |
126 | 0 | return 0; |
127 | | |
128 | | /* |
129 | | * Add the notifier FD for the QUIC domain this SSL object is a part of (if |
130 | | * there is one). This ensures we get woken up if another thread calls into |
131 | | * that QUIC domain and some readiness event relevant to the SSL_poll call |
132 | | * on this thread arises without the underlying network socket ever becoming |
133 | | * readable. |
134 | | */ |
135 | 0 | fd_nfy = ossl_quic_get_notifier_fd(ssl); |
136 | 0 | if (fd_nfy != -1) { |
137 | 0 | uint64_t revents = 0; |
138 | |
|
139 | 0 | if (!ossl_rio_poll_builder_add_fd(rpb, fd_nfy, /*r = */ 1, /*w = */ 0)) |
140 | 0 | return 0; |
141 | | |
142 | | /* Tell QUIC domain we need to receive notifications. */ |
143 | 0 | ossl_quic_enter_blocking_section(ssl, wctx); |
144 | | |
145 | | /* |
146 | | * Only after the above call returns is it guaranteed that any readiness |
147 | | * events will cause the above notifier to become readable. Therefore, |
148 | | * it is possible the object became ready after our initial |
149 | | * poll_readout() call (before we determined that nothing was ready and |
150 | | * we needed to block). We now need to do another readout, in which case |
151 | | * blocking is to be aborted. |
152 | | */ |
153 | 0 | if (!ossl_quic_conn_poll_events(ssl, events, /*do_tick = */ 0, &revents)) { |
154 | 0 | ossl_quic_leave_blocking_section(ssl, wctx); |
155 | 0 | return 0; |
156 | 0 | } |
157 | | |
158 | 0 | if (revents != 0) { |
159 | 0 | ossl_quic_leave_blocking_section(ssl, wctx); |
160 | 0 | *abort_blocking = 1; |
161 | 0 | return 1; |
162 | 0 | } |
163 | 0 | } |
164 | | |
165 | 0 | return 1; |
166 | 0 | } |
167 | | |
168 | | static void postpoll_translation_cleanup_ssl_quic(SSL *ssl, |
169 | | QUIC_REACTOR_WAIT_CTX *wctx) |
170 | 0 | { |
171 | 0 | if (ossl_quic_get_notifier_fd(ssl) != -1) |
172 | 0 | ossl_quic_leave_blocking_section(ssl, wctx); |
173 | 0 | } |
174 | | #endif /* OPENSSL_NO_QUIC */ |
175 | | |
176 | | #ifndef OPENSSL_NO_DTLS |
177 | | static int poll_translate_ssl_dtls_listener(SSL *ssl, |
178 | | RIO_POLL_BUILDER *rpb, |
179 | | uint64_t events, |
180 | | int *abort_blocking) |
181 | 0 | { |
182 | 0 | BIO *rbio; |
183 | 0 | BIO_POLL_DESCRIPTOR desc; |
184 | 0 | DTLS_LISTENER *dl = (DTLS_LISTENER *)ssl; |
185 | 0 | uint64_t revents = 0; |
186 | 0 | int nfd; |
187 | |
|
188 | 0 | rbio = SSL_get_rbio(ssl); |
189 | 0 | if (rbio == NULL) |
190 | 0 | return 0; |
191 | | |
192 | 0 | if (!BIO_get_rpoll_descriptor(rbio, &desc) |
193 | 0 | || desc.type != BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD) { |
194 | 0 | ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, |
195 | 0 | "DTLS listener requires a socket BIO for blocking poll"); |
196 | 0 | return 0; |
197 | 0 | } |
198 | | |
199 | | /* |
200 | | * Watch the socket for readability whatever was asked for. Every event a |
201 | | * listener reports is ultimately driven by a datagram arriving, both an |
202 | | * incoming connection and data pending on the listener itself, so there is |
203 | | * no event for which this is the wrong thing to wait on. events is |
204 | | * therefore only consulted for the readiness re-check below. |
205 | | */ |
206 | 0 | if (!ossl_rio_poll_builder_add_fd(rpb, desc.value.fd, /*r=*/1, /*w=*/0)) |
207 | 0 | return 0; |
208 | | |
209 | | /* |
210 | | * Add the notifier FD for the DTLS listener (if multi-threaded mode is |
211 | | * enabled). Another thread may queue an incoming connection for us, or |
212 | | * demux data to one of our connections, without the underlying network |
213 | | * socket ever becoming readable from our perspective. |
214 | | */ |
215 | 0 | if (dl->have_notifier) { |
216 | 0 | nfd = ossl_rio_notifier_as_fd(&dl->notifier); |
217 | 0 | if (nfd != -1) { |
218 | 0 | if (!ossl_rio_poll_builder_add_fd(rpb, nfd, /*r=*/1, /*w=*/0)) |
219 | 0 | return 0; |
220 | | |
221 | | /* Tell the listener we need to receive notifications. */ |
222 | 0 | ossl_dtls_listener_enter_blocking_section(ssl); |
223 | | |
224 | | /* |
225 | | * Only after the above call returns is it guaranteed that any |
226 | | * readiness events will cause the notifier to become readable. |
227 | | * Therefore it is possible the listener became ready after the |
228 | | * readout which decided we needed to block. Re-check now. |
229 | | */ |
230 | 0 | if (!ossl_dtls_listener_poll_events(ssl, events, /*do_tick=*/0, |
231 | 0 | &revents)) { |
232 | 0 | ossl_dtls_listener_leave_blocking_section(ssl); |
233 | 0 | return 0; |
234 | 0 | } |
235 | | |
236 | 0 | if (revents != 0) { |
237 | 0 | ossl_dtls_listener_leave_blocking_section(ssl); |
238 | 0 | *abort_blocking = 1; |
239 | 0 | return 1; |
240 | 0 | } |
241 | 0 | } |
242 | 0 | } |
243 | | |
244 | 0 | return 1; |
245 | 0 | } |
246 | | |
247 | | static int poll_translate_ssl_dtls_conn(SSL *ssl, |
248 | | RIO_POLL_BUILDER *rpb, |
249 | | uint64_t events, |
250 | | int *abort_blocking) |
251 | 0 | { |
252 | 0 | BIO *rbio, *wbio; |
253 | 0 | BIO_POLL_DESCRIPTOR rdesc, wdesc; |
254 | 0 | int rfd = -1, wfd = -1, nfd = -1; |
255 | 0 | SSL_CONNECTION *sc; |
256 | 0 | DTLS_LISTENER *dl = NULL; |
257 | 0 | int has_pending; |
258 | |
|
259 | 0 | sc = SSL_CONNECTION_FROM_SSL_ONLY(ssl); |
260 | |
|
261 | 0 | if (sc != NULL && sc->d1 != NULL && sc->d1->listener != NULL) |
262 | 0 | dl = (DTLS_LISTENER *)sc->d1->listener; |
263 | |
|
264 | 0 | if ((events & SSL_POLL_EVENT_R) != 0) { |
265 | 0 | rbio = SSL_get_rbio(ssl); |
266 | |
|
267 | 0 | if (rbio == NULL && dl != NULL) { |
268 | | /* |
269 | | * Listener-based DTLS connection. First, pump the listener's |
270 | | * demux to ensure any pending datagrams on the socket are |
271 | | * routed to their respective connection URXE queues. |
272 | | */ |
273 | 0 | ossl_dtls_tick(dl); |
274 | | |
275 | | /* |
276 | | * Now check the URXE buffer. If data has been demuxed into |
277 | | * this connection's receive queue, abort blocking immediately - |
278 | | * there is no need to wait on the socket FD. |
279 | | */ |
280 | 0 | if (sc->d1->rx != NULL) { |
281 | 0 | ossl_crypto_mutex_lock(sc->d1->rx->mutex); |
282 | 0 | has_pending = !ossl_list_urxe_is_empty(&sc->d1->rx->urxe_pending); |
283 | 0 | ossl_crypto_mutex_unlock(sc->d1->rx->mutex); |
284 | 0 | if (has_pending) { |
285 | 0 | *abort_blocking = 1; |
286 | 0 | return 1; |
287 | 0 | } |
288 | 0 | } |
289 | | |
290 | | /* |
291 | | * Add the notifier FD for the DTLS listener (if multi-threaded |
292 | | * mode is enabled). This ensures we get woken up if another thread |
293 | | * demuxes data to this connection's URXE queue without the |
294 | | * underlying network socket ever becoming readable from our |
295 | | * perspective. |
296 | | */ |
297 | 0 | if (dl->have_notifier) { |
298 | 0 | nfd = ossl_rio_notifier_as_fd(&dl->notifier); |
299 | 0 | if (nfd != -1) { |
300 | 0 | if (!ossl_rio_poll_builder_add_fd(rpb, nfd, /*r=*/1, /*w=*/0)) |
301 | 0 | return 0; |
302 | | |
303 | | /* Tell listener we need to receive notifications. */ |
304 | 0 | ossl_dtls_listener_enter_blocking_section(sc->d1->listener); |
305 | | |
306 | | /* |
307 | | * Only after the above call returns is it guaranteed that |
308 | | * any readiness events will cause the notifier to become |
309 | | * readable. Therefore, it is possible data was demuxed to |
310 | | * our URXE queue after our initial check above but before |
311 | | * we entered the blocking section. Re-check now. |
312 | | */ |
313 | 0 | if (sc->d1->rx != NULL) { |
314 | 0 | ossl_crypto_mutex_lock(sc->d1->rx->mutex); |
315 | 0 | has_pending = !ossl_list_urxe_is_empty(&sc->d1->rx->urxe_pending); |
316 | 0 | ossl_crypto_mutex_unlock(sc->d1->rx->mutex); |
317 | 0 | if (has_pending) { |
318 | 0 | ossl_dtls_listener_leave_blocking_section(sc->d1->listener); |
319 | 0 | *abort_blocking = 1; |
320 | 0 | return 1; |
321 | 0 | } |
322 | 0 | } |
323 | 0 | } |
324 | 0 | } |
325 | | |
326 | | /* |
327 | | * URXE buffer is empty. Fall back to the listener's rbio so the |
328 | | * OS-level poll() wakes us up when the shared socket becomes |
329 | | * readable and new datagrams may arrive. |
330 | | */ |
331 | 0 | rbio = SSL_get_rbio(sc->d1->listener); |
332 | 0 | } |
333 | | |
334 | 0 | if (rbio != NULL) { |
335 | 0 | if (BIO_get_rpoll_descriptor(rbio, &rdesc) |
336 | 0 | && rdesc.type == BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD) |
337 | 0 | rfd = rdesc.value.fd; |
338 | 0 | } |
339 | 0 | } |
340 | | |
341 | 0 | if ((events & SSL_POLL_EVENT_W) != 0) { |
342 | 0 | wbio = SSL_get_wbio(ssl); |
343 | 0 | if (wbio != NULL) { |
344 | 0 | if (BIO_get_wpoll_descriptor(wbio, &wdesc) |
345 | 0 | && wdesc.type == BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD) |
346 | 0 | wfd = wdesc.value.fd; |
347 | 0 | } |
348 | 0 | } |
349 | | |
350 | | /* If same FD for read and write, combine them */ |
351 | 0 | if (rfd != -1 && wfd == rfd) { |
352 | 0 | if (!ossl_rio_poll_builder_add_fd(rpb, rfd, /*r=*/1, /*w=*/1)) |
353 | 0 | return 0; |
354 | 0 | } else { |
355 | 0 | if (rfd != -1) |
356 | 0 | if (!ossl_rio_poll_builder_add_fd(rpb, rfd, /*r=*/1, /*w=*/0)) |
357 | 0 | return 0; |
358 | 0 | if (wfd != -1) |
359 | 0 | if (!ossl_rio_poll_builder_add_fd(rpb, wfd, /*r=*/0, /*w=*/1)) |
360 | 0 | return 0; |
361 | 0 | } |
362 | | |
363 | 0 | return 1; |
364 | 0 | } |
365 | | |
366 | | static void postpoll_translation_cleanup_ssl_dtls_listener(SSL *ssl) |
367 | 0 | { |
368 | 0 | DTLS_LISTENER *dl = (DTLS_LISTENER *)ssl; |
369 | | |
370 | | /* Need to mirror the enter blocking section call */ |
371 | 0 | if (dl->have_notifier && ossl_rio_notifier_as_fd(&dl->notifier) != -1) |
372 | 0 | ossl_dtls_listener_leave_blocking_section(ssl); |
373 | 0 | } |
374 | | |
375 | | static void postpoll_translation_cleanup_ssl_dtls_conn(SSL *ssl, uint64_t events) |
376 | 0 | { |
377 | 0 | SSL_CONNECTION *sc; |
378 | 0 | DTLS_LISTENER *dl; |
379 | | |
380 | | /* |
381 | | * We only enter blocking section when read events are requested. |
382 | | * Don't call leave if we never entered. |
383 | | */ |
384 | 0 | if ((events & SSL_POLL_EVENT_R) == 0) |
385 | 0 | return; |
386 | | |
387 | 0 | sc = SSL_CONNECTION_FROM_SSL_ONLY(ssl); |
388 | 0 | if (sc == NULL || sc->d1 == NULL || sc->d1->listener == NULL) |
389 | 0 | return; |
390 | | |
391 | | /* Need to mirror the enter blocking section call */ |
392 | 0 | if (SSL_get_rbio(ssl) != NULL) |
393 | 0 | return; |
394 | | |
395 | 0 | dl = (DTLS_LISTENER *)sc->d1->listener; |
396 | 0 | if (dl->have_notifier && ossl_rio_notifier_as_fd(&dl->notifier) != -1) |
397 | 0 | ossl_dtls_listener_leave_blocking_section(sc->d1->listener); |
398 | 0 | } |
399 | | #endif /* OPENSSL_NO_DTLS */ |
400 | | |
401 | | #if !defined(OPENSSL_NO_QUIC) || !defined(OPENSSL_NO_DTLS) |
402 | | static void postpoll_translation_cleanup(SSL_POLL_ITEM *items, |
403 | | size_t num_items, |
404 | | size_t stride, |
405 | | ossl_unused QUIC_REACTOR_WAIT_CTX *wctx) |
406 | 0 | { |
407 | 0 | SSL_POLL_ITEM *item; |
408 | 0 | SSL *ssl; |
409 | 0 | size_t i; |
410 | |
|
411 | 0 | for (i = 0; i < num_items; ++i) { |
412 | 0 | item = &ITEM_N(items, stride, i); |
413 | |
|
414 | 0 | switch (item->desc.type) { |
415 | 0 | case BIO_POLL_DESCRIPTOR_TYPE_SSL: |
416 | 0 | ssl = item->desc.value.ssl; |
417 | 0 | if (ssl == NULL) |
418 | 0 | break; |
419 | | |
420 | 0 | switch (ssl->type) { |
421 | 0 | #ifndef OPENSSL_NO_QUIC |
422 | 0 | case SSL_TYPE_QUIC_LISTENER: |
423 | 0 | case SSL_TYPE_QUIC_CONNECTION: |
424 | 0 | case SSL_TYPE_QUIC_XSO: |
425 | 0 | postpoll_translation_cleanup_ssl_quic(ssl, wctx); |
426 | 0 | break; |
427 | 0 | #endif |
428 | | |
429 | 0 | #ifndef OPENSSL_NO_DTLS |
430 | 0 | case SSL_TYPE_DTLS_LISTENER: |
431 | 0 | postpoll_translation_cleanup_ssl_dtls_listener(ssl); |
432 | 0 | break; |
433 | 0 | case SSL_TYPE_SSL_CONNECTION: |
434 | 0 | if (SSL_is_dtls(ssl)) |
435 | 0 | postpoll_translation_cleanup_ssl_dtls_conn(ssl, item->events); |
436 | 0 | break; |
437 | 0 | #endif |
438 | | |
439 | 0 | default: |
440 | 0 | break; |
441 | 0 | } |
442 | 0 | break; |
443 | 0 | default: |
444 | 0 | break; |
445 | 0 | } |
446 | 0 | } |
447 | 0 | } |
448 | | |
449 | | static int poll_translate(SSL_POLL_ITEM *items, |
450 | | size_t num_items, |
451 | | size_t stride, |
452 | | ossl_unused QUIC_REACTOR_WAIT_CTX *wctx, |
453 | | RIO_POLL_BUILDER *rpb, |
454 | | OSSL_TIME *p_earliest_wakeup_deadline, |
455 | | int *abort_blocking, |
456 | | int bound_by_event_timeout, |
457 | | size_t *p_result_count) |
458 | 0 | { |
459 | 0 | int ok = 1; |
460 | 0 | SSL_POLL_ITEM *item; |
461 | 0 | size_t result_count = 0; |
462 | 0 | SSL *ssl; |
463 | 0 | OSSL_TIME earliest_wakeup_deadline = ossl_time_infinite(); |
464 | 0 | #if !defined(OPENSSL_NO_QUIC) || !defined(OPENSSL_NO_DTLS) |
465 | 0 | struct timeval timeout; |
466 | 0 | int is_infinite = 0; |
467 | 0 | #endif |
468 | 0 | size_t i; |
469 | |
|
470 | 0 | for (i = 0; i < num_items; ++i) { |
471 | 0 | item = &ITEM_N(items, stride, i); |
472 | |
|
473 | 0 | #ifndef OPENSSL_NO_QUIC |
474 | 0 | if (ossl_quic_poll_translate_test_step_cb != NULL) |
475 | 0 | ossl_quic_poll_translate_test_step_cb(i, |
476 | 0 | ossl_quic_poll_translate_test_step_cb_arg); |
477 | 0 | #endif |
478 | |
|
479 | 0 | switch (item->desc.type) { |
480 | 0 | case BIO_POLL_DESCRIPTOR_TYPE_SSL: |
481 | 0 | ssl = item->desc.value.ssl; |
482 | 0 | if (ssl == NULL) |
483 | | /* NULL items are no-ops and have revents reported as 0 */ |
484 | 0 | break; |
485 | | |
486 | 0 | switch (ssl->type) { |
487 | 0 | #ifndef OPENSSL_NO_QUIC |
488 | 0 | case SSL_TYPE_QUIC_LISTENER: |
489 | 0 | case SSL_TYPE_QUIC_CONNECTION: |
490 | 0 | case SSL_TYPE_QUIC_XSO: |
491 | 0 | if (!poll_translate_ssl_quic(ssl, wctx, rpb, item->events, |
492 | 0 | abort_blocking)) |
493 | 0 | FAIL_ITEM(i); |
494 | | |
495 | 0 | if (*abort_blocking) |
496 | 0 | goto out; |
497 | | |
498 | 0 | if (!SSL_get_event_timeout(ssl, &timeout, &is_infinite)) |
499 | 0 | FAIL_ITEM(i++); /* need to clean up this item too */ |
500 | | |
501 | 0 | if (!is_infinite) |
502 | 0 | earliest_wakeup_deadline |
503 | 0 | = ossl_time_min(earliest_wakeup_deadline, |
504 | 0 | ossl_time_add(ossl_time_now(), |
505 | 0 | ossl_time_from_timeval(timeout))); |
506 | |
|
507 | 0 | break; |
508 | 0 | #endif |
509 | | |
510 | 0 | #ifndef OPENSSL_NO_DTLS |
511 | 0 | case SSL_TYPE_DTLS_LISTENER: |
512 | 0 | if (!poll_translate_ssl_dtls_listener(ssl, rpb, item->events, |
513 | 0 | abort_blocking)) |
514 | 0 | FAIL_ITEM(i); |
515 | | |
516 | 0 | if (*abort_blocking) |
517 | 0 | goto out; |
518 | | |
519 | 0 | break; |
520 | 0 | case SSL_TYPE_SSL_CONNECTION: |
521 | 0 | if (SSL_is_dtls(ssl)) { |
522 | 0 | if (!poll_translate_ssl_dtls_conn(ssl, rpb, item->events, |
523 | 0 | abort_blocking)) |
524 | 0 | FAIL_ITEM(i); |
525 | | |
526 | 0 | if (*abort_blocking) |
527 | 0 | goto out; |
528 | | |
529 | | /* |
530 | | * Bound the wait by the DTLS retransmission timer, |
531 | | * otherwise a poll with no timeout sleeps straight through |
532 | | * the point at which we should be retransmitting. |
533 | | * |
534 | | * Unless the caller has told us not to. A waiter which |
535 | | * cannot service the timer must not be woken by it: it |
536 | | * would find the timeout still expired on the next wait, |
537 | | * which reads as a zero deadline, and spin. |
538 | | */ |
539 | 0 | if (bound_by_event_timeout) { |
540 | 0 | if (!SSL_get_event_timeout(ssl, &timeout, &is_infinite)) |
541 | 0 | FAIL_ITEM(i++); /* need to clean up this item too */ |
542 | | |
543 | 0 | if (!is_infinite) |
544 | 0 | earliest_wakeup_deadline |
545 | 0 | = ossl_time_min(earliest_wakeup_deadline, |
546 | 0 | ossl_time_add(ossl_time_now(), |
547 | 0 | ossl_time_from_timeval(timeout))); |
548 | 0 | } |
549 | |
|
550 | 0 | } else { |
551 | 0 | ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, |
552 | 0 | "SSL_poll currently only supports DTLS listeners for DTLS connections"); |
553 | 0 | } |
554 | 0 | break; |
555 | 0 | #endif |
556 | | |
557 | 0 | default: |
558 | 0 | ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, |
559 | 0 | "SSL_poll currently only supports QUIC SSL " |
560 | 0 | "objects"); |
561 | 0 | FAIL_ITEM(i); |
562 | 0 | } |
563 | 0 | break; |
564 | | |
565 | 0 | case BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD: |
566 | 0 | ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, |
567 | 0 | "SSL_poll currently does not support polling " |
568 | 0 | "sockets"); |
569 | 0 | FAIL_ITEM(i); |
570 | | |
571 | 0 | default: |
572 | 0 | ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, |
573 | 0 | "SSL_poll does not support unknown poll descriptor " |
574 | 0 | "type %d", |
575 | 0 | item->desc.type); |
576 | 0 | FAIL_ITEM(i); |
577 | 0 | } |
578 | 0 | } |
579 | | |
580 | 0 | out: |
581 | | /* |
582 | | * On abort_blocking, the item which triggered the abort has already |
583 | | * balanced its own enter/leave of the blocking section (see |
584 | | * poll_translate_ssl_quic()); only items 0..i-1 still need cleanup here. |
585 | | */ |
586 | 0 | if (!ok || *abort_blocking) |
587 | 0 | postpoll_translation_cleanup(items, i, stride, wctx); |
588 | |
|
589 | 0 | *p_earliest_wakeup_deadline = earliest_wakeup_deadline; |
590 | 0 | *p_result_count = result_count; |
591 | 0 | return ok; |
592 | 0 | } |
593 | | |
594 | | static int poll_block(SSL_POLL_ITEM *items, |
595 | | size_t num_items, |
596 | | size_t stride, |
597 | | OSSL_TIME user_deadline, |
598 | | int bound_by_event_timeout, |
599 | | size_t *p_result_count) |
600 | 0 | { |
601 | 0 | int ok = 0, abort_blocking = 0; |
602 | 0 | RIO_POLL_BUILDER rpb; |
603 | 0 | QUIC_REACTOR_WAIT_CTX wctx; |
604 | 0 | OSSL_TIME earliest_wakeup_deadline; |
605 | | |
606 | | /* |
607 | | * Blocking is somewhat involved and involves the following steps: |
608 | | * |
609 | | * - Translation, in which the various logical items (SSL objects, etc.) to |
610 | | * be polled are translated into items an OS polling API understands. |
611 | | * |
612 | | * - Synchronisation bookkeeping. This ensures that we can be woken up |
613 | | * not just by readiness of any underlying file descriptor distilled from |
614 | | * the provided items but also by other threads, which might do work |
615 | | * on a relevant QUIC object to cause the object to be ready without the |
616 | | * underlying file descriptor ever becoming ready from our perspective. |
617 | | * |
618 | | * - The blocking call to the OS polling API. |
619 | | * |
620 | | * - Currently we do not do reverse translation but simply call |
621 | | * poll_readout() again to read out all readiness state for all |
622 | | * descriptors which the user passed. |
623 | | * |
624 | | * TODO(QUIC POLLING): In the future we will do reverse translation here |
625 | | * also to facilitate a more efficient readout. |
626 | | */ |
627 | 0 | #ifndef OPENSSL_NO_QUIC |
628 | 0 | ossl_quic_reactor_wait_ctx_init(&wctx); |
629 | 0 | #endif |
630 | 0 | ossl_rio_poll_builder_init(&rpb); |
631 | |
|
632 | 0 | if (!poll_translate(items, num_items, stride, &wctx, &rpb, |
633 | 0 | &earliest_wakeup_deadline, |
634 | 0 | &abort_blocking, |
635 | 0 | bound_by_event_timeout, |
636 | 0 | p_result_count)) |
637 | 0 | goto out; |
638 | | |
639 | 0 | if (abort_blocking) { |
640 | | /* |
641 | | * Nothing actually failed; we just shouldn't block because an item |
642 | | * may have become ready while we were setting up. The caller's |
643 | | * retry loop will call poll_readout() again to pick this up. |
644 | | */ |
645 | 0 | ok = 1; |
646 | 0 | goto out; |
647 | 0 | } |
648 | | |
649 | 0 | earliest_wakeup_deadline = ossl_time_min(earliest_wakeup_deadline, |
650 | 0 | user_deadline); |
651 | |
|
652 | 0 | ok = ossl_rio_poll_builder_poll(&rpb, earliest_wakeup_deadline); |
653 | |
|
654 | 0 | postpoll_translation_cleanup(items, num_items, stride, &wctx); |
655 | |
|
656 | 0 | out: |
657 | 0 | ossl_rio_poll_builder_cleanup(&rpb); |
658 | 0 | #ifndef OPENSSL_NO_QUIC |
659 | 0 | ossl_quic_reactor_wait_ctx_cleanup(&wctx); |
660 | 0 | #endif |
661 | 0 | return ok; |
662 | 0 | } |
663 | | |
664 | | #ifndef OPENSSL_NO_DTLS |
665 | | /* |
666 | | * Wait until the given DTLS listener or listener-based connection may have |
667 | | * become ready for one of the given events, or until the deadline expires. |
668 | | * |
669 | | * This is the wait that libssl itself performs when a DTLS object is used in |
670 | | * blocking mode. It is the same wait SSL_poll() performs, and reuses it, so a |
671 | | * blocking call is woken by the same means an application polling the object |
672 | | * would be: readiness of the listener's socket, or the listener's notifier if |
673 | | * another thread produces readiness without the socket becoming readable here. |
674 | | * |
675 | | * No readout is performed. A spurious wakeup is always possible - the socket |
676 | | * becoming readable says nothing about which connection the datagram is for - |
677 | | * so the caller must re-test its own condition and wait again if needed. |
678 | | * |
679 | | * bound_by_event_timeout says whether the connection's own event timeout, which |
680 | | * for DTLS is the retransmission timer, should shorten the wait. Pass 1 unless |
681 | | * the caller is unable to service that timer when it fires: waking for a |
682 | | * timeout nothing then handles leaves it expired, and an expired timeout reads |
683 | | * as a zero deadline, so every later wait returns at once. |
684 | | * |
685 | | * Returns 1 if the wait completed and 0 on error. |
686 | | */ |
687 | | int ossl_dtls_block_until_ready(SSL *ssl, uint64_t events, OSSL_TIME deadline, |
688 | | int bound_by_event_timeout) |
689 | 0 | { |
690 | 0 | SSL_POLL_ITEM item; |
691 | 0 | size_t result_count = 0; |
692 | |
|
693 | 0 | item.desc.type = BIO_POLL_DESCRIPTOR_TYPE_SSL; |
694 | 0 | item.desc.value.ssl = ssl; |
695 | 0 | item.events = events; |
696 | 0 | item.revents = 0; |
697 | |
|
698 | 0 | return poll_block(&item, 1, sizeof(item), deadline, bound_by_event_timeout, |
699 | 0 | &result_count); |
700 | 0 | } |
701 | | #endif /* OPENSSL_NO_DTLS */ |
702 | | #endif |
703 | | |
704 | | static int poll_readout(SSL_POLL_ITEM *items, |
705 | | size_t num_items, |
706 | | size_t stride, |
707 | | int do_tick, |
708 | | size_t *p_result_count) |
709 | 0 | { |
710 | 0 | int ok = 1; |
711 | 0 | size_t i, result_count = 0; |
712 | 0 | SSL_POLL_ITEM *item; |
713 | 0 | SSL *ssl; |
714 | 0 | #if !defined(OPENSSL_NO_QUIC) || !defined(OPENSSL_NO_DTLS) |
715 | 0 | uint64_t events; |
716 | 0 | #endif |
717 | 0 | uint64_t revents; |
718 | |
|
719 | 0 | for (i = 0; i < num_items; ++i) { |
720 | 0 | item = &ITEM_N(items, stride, i); |
721 | 0 | #if !defined(OPENSSL_NO_QUIC) || !defined(OPENSSL_NO_DTLS) |
722 | 0 | events = item->events; |
723 | 0 | #endif |
724 | 0 | revents = 0; |
725 | |
|
726 | 0 | switch (item->desc.type) { |
727 | 0 | case BIO_POLL_DESCRIPTOR_TYPE_SSL: |
728 | 0 | ssl = item->desc.value.ssl; |
729 | 0 | if (ssl == NULL) |
730 | | /* NULL items are no-ops and have revents reported as 0 */ |
731 | 0 | break; |
732 | | |
733 | 0 | switch (ssl->type) { |
734 | 0 | #ifndef OPENSSL_NO_QUIC |
735 | 0 | case SSL_TYPE_QUIC_LISTENER: |
736 | 0 | case SSL_TYPE_QUIC_CONNECTION: |
737 | 0 | case SSL_TYPE_QUIC_XSO: |
738 | 0 | if (!ossl_quic_conn_poll_events(ssl, events, do_tick, &revents)) |
739 | | /* above call raises ERR */ |
740 | 0 | FAIL_ITEM(i); |
741 | | |
742 | 0 | if (revents != 0) |
743 | 0 | ++result_count; |
744 | |
|
745 | 0 | break; |
746 | 0 | #endif |
747 | | |
748 | 0 | #ifndef OPENSSL_NO_DTLS |
749 | 0 | case SSL_TYPE_DTLS_LISTENER: |
750 | 0 | if (!ossl_dtls_listener_poll_events(ssl, events, do_tick, &revents)) |
751 | | /* above call raises ERR */ |
752 | 0 | FAIL_ITEM(i); |
753 | | |
754 | 0 | if (revents != 0) |
755 | 0 | ++result_count; |
756 | 0 | break; |
757 | 0 | case SSL_TYPE_SSL_CONNECTION: |
758 | 0 | if (SSL_is_dtls(ssl)) { |
759 | 0 | if (!ossl_dtls_conn_poll_events(ssl, events, do_tick, &revents)) |
760 | | /* above call raises ERR */ |
761 | 0 | FAIL_ITEM(i); |
762 | | |
763 | 0 | if (revents != 0) |
764 | 0 | ++result_count; |
765 | 0 | } else { |
766 | | /* TLS Connections not supported */ |
767 | 0 | ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, |
768 | 0 | "SSL_poll currently only supports QUIC and DTLS SSL objects"); |
769 | 0 | FAIL_ITEM(i); |
770 | 0 | } |
771 | 0 | break; |
772 | 0 | #endif |
773 | | |
774 | 0 | default: |
775 | 0 | ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, |
776 | 0 | "SSL_poll currently only supports QUIC and DTLS SSL objects"); |
777 | 0 | FAIL_ITEM(i); |
778 | 0 | } |
779 | 0 | break; |
780 | 0 | case BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD: |
781 | 0 | ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, |
782 | 0 | "SSL_poll currently does not support polling " |
783 | 0 | "sockets"); |
784 | 0 | FAIL_ITEM(i); |
785 | 0 | default: |
786 | 0 | ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED, |
787 | 0 | "SSL_poll does not support unknown poll descriptor " |
788 | 0 | "type %d", |
789 | 0 | item->desc.type); |
790 | 0 | FAIL_ITEM(i); |
791 | 0 | } |
792 | | |
793 | 0 | item->revents = revents; |
794 | 0 | } |
795 | | |
796 | 0 | out: |
797 | 0 | if (p_result_count != NULL) |
798 | 0 | *p_result_count = result_count; |
799 | |
|
800 | 0 | return ok; |
801 | 0 | } |
802 | | |
803 | | int SSL_poll(SSL_POLL_ITEM *items, |
804 | | size_t num_items, |
805 | | size_t stride, |
806 | | const struct timeval *timeout, |
807 | | uint64_t flags, |
808 | | size_t *p_result_count) |
809 | 0 | { |
810 | 0 | int ok = 1; |
811 | 0 | size_t result_count = 0; |
812 | 0 | ossl_unused int do_tick = ((flags & SSL_POLL_FLAG_NO_HANDLE_EVENTS) == 0); |
813 | 0 | OSSL_TIME deadline; |
814 | | |
815 | | /* Trivial case. */ |
816 | 0 | if (num_items == 0) { |
817 | 0 | if (timeout == NULL) |
818 | 0 | goto out; |
819 | 0 | OSSL_sleep(ossl_time2ms(ossl_time_from_timeval(*timeout))); |
820 | 0 | goto out; |
821 | 0 | } |
822 | | |
823 | | /* Convert timeout to deadline. */ |
824 | 0 | if (timeout == NULL) |
825 | 0 | deadline = ossl_time_infinite(); |
826 | 0 | else if (timeout->tv_sec == 0 && timeout->tv_usec == 0) |
827 | 0 | deadline = ossl_time_zero(); |
828 | 0 | else |
829 | 0 | deadline = ossl_time_add(ossl_time_now(), |
830 | 0 | ossl_time_from_timeval(*timeout)); |
831 | | |
832 | | /* Loop until we have something to report. */ |
833 | 0 | for (;;) { |
834 | | /* Readout phase - poll current state of each item. */ |
835 | 0 | if (!poll_readout(items, num_items, stride, do_tick, &result_count)) { |
836 | 0 | ok = 0; |
837 | 0 | goto out; |
838 | 0 | } |
839 | | |
840 | | /* |
841 | | * If we got anything, or we are in immediate mode (zero timeout), or |
842 | | * the deadline has expired, we're done. |
843 | | */ |
844 | 0 | if (result_count > 0 |
845 | 0 | || ossl_time_is_zero(deadline) /* (avoids now call) */ |
846 | 0 | || ossl_time_compare(ossl_time_now(), deadline) >= 0) |
847 | 0 | goto out; |
848 | | |
849 | | /* |
850 | | * Block until something is ready. Ignore NO_HANDLE_EVENTS from this |
851 | | * point onwards. |
852 | | */ |
853 | 0 | do_tick = 1; |
854 | 0 | #if !defined(OPENSSL_NO_QUIC) || !defined(OPENSSL_NO_DTLS) |
855 | 0 | if (!poll_block(items, num_items, stride, deadline, |
856 | 0 | /*bound_by_event_timeout=*/1, &result_count)) { |
857 | 0 | ok = 0; |
858 | 0 | goto out; |
859 | 0 | } |
860 | 0 | #endif |
861 | 0 | } |
862 | | |
863 | | /* TODO(QUIC POLLING): Support for polling FDs */ |
864 | | |
865 | 0 | out: |
866 | 0 | if (p_result_count != NULL) |
867 | 0 | *p_result_count = result_count; |
868 | |
|
869 | 0 | return ok; |
870 | 0 | } |