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