summaryrefslogtreecommitdiffstats
path: root/ssl/rio/poll_immediate.c
blob: 7de211742add72b482edaa45813e5445361d9a97 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
/*
 * Copyright 2024 The OpenSSL Project Authors. All Rights Reserved.
 *
 * Licensed under the Apache License 2.0 (the "License").  You may not use
 * this file except in compliance with the License.  You can obtain a copy
 * in the file LICENSE in the source distribution or at
 * https://www.openssl.org/source/license.html
 */

#include "internal/common.h"
#include <openssl/ssl.h>
#include <openssl/err.h>
#include "../ssl_local.h"

#define ITEM_N(items, stride, n) \
    (*(SSL_POLL_ITEM *)((char *)(items) + (n)*(stride)))

#define FAIL_FROM(n)                                                        \
    do {                                                                    \
        size_t j;                                                           \
                                                                            \
        for (j = (n); j < num_items; ++j)                                   \
            ITEM_N(items, stride, j).revents = 0;                           \
                                                                            \
        ok = 0;                                                             \
        goto out;                                                           \
    } while (0)

#define FAIL_ITEM(i)                                                        \
    do {                                                                    \
        ITEM_N(items, stride, i).revents = SSL_POLL_EVENT_F;                \
        ++result_count;                                                     \
        FAIL_FROM(i + 1);                                                   \
    } while (0)

int 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)
{
    int ok = 1;
    size_t i, result_count = 0;
    SSL_POLL_ITEM *item;
    SSL *ssl;
    uint64_t events, revents;
    int is_immediate
        = (timeout != NULL
           && timeout->tv_sec == 0 && timeout->tv_usec == 0);
    int do_tick = ((flags & SSL_POLL_FLAG_NO_HANDLE_EVENTS) == 0);

    /*
     * Prevent calls which use SSL_poll functionality which is not currently
     * supported.
     */
    if (!is_immediate) {
        ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED,
                       "SSL_poll does not currently support blocking "
                       "operation");
        FAIL_FROM(0);
    }

    if (do_tick) {
        ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED,
                       "SSL_poll does not currently support implicit I/O "
                       "processing");
        FAIL_FROM(0);
    }

    /* Trivial case. */
    if (num_items == 0)
        goto out;

    /* Poll current state of each item. */
    for (i = 0; i < num_items; ++i) {
        item    = &ITEM_N(items, stride, i);
        events  = item->events;
        revents = 0;

        switch (item->desc.type) {
        case BIO_POLL_DESCRIPTOR_TYPE_SSL:
            ssl = item->desc.value.ssl;
            if (ssl == NULL)
                /* NULL items are no-ops and have revents reported as 0 */
                break;

            switch (ssl->type) {
            case SSL_TYPE_QUIC_CONNECTION:
            case SSL_TYPE_QUIC_XSO:
                if (!ossl_quic_conn_poll_events(ssl, events, &revents))
                    /* above call raises ERR */
                    FAIL_ITEM(i);

                if (revents != 0)
                    ++result_count;

                break;

            default:
                ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED,
                               "SSL_poll currently only supports QUIC SSL "
                               "objects");
                FAIL_ITEM(i);
            }
            break;
        case BIO_POLL_DESCRIPTOR_TYPE_SOCK_FD:
            ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED,
                           "SSL_poll currently does not support polling "
                           "sockets");
            FAIL_ITEM(i);
        default:
            ERR_raise_data(ERR_LIB_SSL, SSL_R_POLL_REQUEST_NOT_SUPPORTED,
                           "SSL_poll does not support unknown poll descriptor "
                           "type %d", item->desc.type);
            FAIL_ITEM(i);
        }

        item->revents = revents;
    }

    /* TODO(QUIC POLLING): Blocking mode */
    /* TODO(QUIC POLLING): Support for polling FDs */
    /* TODO(QUIC POLLING): Support for autotick */

out:
    if (p_result_count != NULL)
        *p_result_count = result_count;

    return ok;
}