1 /*
2 * Copyright 2024 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 <openssl/ssl.h>
12 #include <openssl/err.h>
13 #include "../ssl_local.h"
14
15 #define ITEM_N(items, stride, n) \
16 (*(SSL_POLL_ITEM *)((char *)(items) + (n)*(stride)))
17
18 #define FAIL_FROM(n) \
19 do { \
20 size_t j; \
21 \
22 for (j = (n); j < num_items; ++j) \
23 ITEM_N(items, stride, j).revents = 0; \
24 \
25 ok = 0; \
26 goto out; \
27 } while (0)
28
29 #define FAIL_ITEM(i) \
30 do { \
31 ITEM_N(items, stride, i).revents = SSL_POLL_EVENT_F; \
32 ++result_count; \
33 FAIL_FROM(i + 1); \
34 } while (0)
35
SSL_poll(SSL_POLL_ITEM * items,size_t num_items,size_t stride,const struct timeval * timeout,uint64_t flags,size_t * p_result_count)36 int SSL_poll(SSL_POLL_ITEM *items,
37 size_t num_items,
38 size_t stride,
39 const struct timeval *timeout,
40 uint64_t flags,
41 size_t *p_result_count)
42 {
43 int ok = 1;
44 size_t i, result_count = 0;
45 SSL_POLL_ITEM *item;
46 SSL *ssl;
47 uint64_t revents;
48 ossl_unused uint64_t events;
49 ossl_unused int do_tick = ((flags & SSL_POLL_FLAG_NO_HANDLE_EVENTS) == 0);
50 int is_immediate
51 = (timeout != NULL
52 && timeout->tv_sec == 0 && timeout->tv_usec == 0);
53
54 /*
55 * Prevent calls which use SSL_poll functionality which is not currently
56 * supported.
57 */
58 if (!is_immediate) {
59 ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED,
60 "SSL_poll does not currently support blocking "
61 "operation");
62 FAIL_FROM(0);
63 }
64
65 /* Trivial case. */
66 if (num_items == 0)
67 goto out;
68
69 /* Poll current state of each item. */
70 for (i = 0; i < num_items; ++i) {
71 item = &ITEM_N(items, stride, i);
72 events = item->events;
73 revents = 0;
74
75 switch (item->desc.type) {
76 case BIO_POLL_DESCRIPTOR_TYPE_SSL:
77 ssl = item->desc.value.ssl;
78 if (ssl == NULL)
79 /* NULL items are no-ops and have revents reported as 0 */
80 break;
81
82 switch (ssl->type) {
83 #ifndef OPENSSL_NO_QUIC
84 case SSL_TYPE_QUIC_CONNECTION:
85 case SSL_TYPE_QUIC_XSO:
86 if (!ossl_quic_conn_poll_events(ssl, events, do_tick, &revents))
87 /* above call raises ERR */
88 FAIL_ITEM(i);
89
90 if (revents != 0)
91 ++result_count;
92
93 break;
94 #endif
95
96 default:
97 ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED,
98 "SSL_poll currently only supports QUIC SSL "
99 "objects");
100 FAIL_ITEM(i);
101 }
102 break;
103 case BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD:
104 ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED,
105 "SSL_poll currently does not support polling "
106 "sockets");
107 FAIL_ITEM(i);
108 default:
109 ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED,
110 "SSL_poll does not support unknown poll descriptor "
111 "type %d", item->desc.type);
112 FAIL_ITEM(i);
113 }
114
115 item->revents = revents;
116 }
117
118 /* TODO(QUIC POLLING): Blocking mode */
119 /* TODO(QUIC POLLING): Support for polling FDs */
120
121 out:
122 if (p_result_count != NULL)
123 *p_result_count = result_count;
124
125 return ok;
126 }
127