openssl/ssl/rio/poll_immediate.c
Hugo Landau 6d7b0e06a2 QUIC POLLING: Support no-quic builds
Reviewed-by: Neil Horman <nhorman@openssl.org>
Reviewed-by: Tomas Mraz <tomas@openssl.org>
(Merged from https://github.com/openssl/openssl/pull/23495)
2024-02-10 11:37:14 +00:00

127 lines
4.4 KiB
C

/*
* 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 revents;
ossl_unused uint64_t events;
ossl_unused int do_tick = ((flags & SSL_POLL_FLAG_NO_HANDLE_EVENTS) == 0);
int is_immediate
= (timeout != NULL
&& timeout->tv_sec == 0 && timeout->tv_usec == 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);
}
/* 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) {
#ifndef OPENSSL_NO_QUIC
case SSL_TYPE_QUIC_CONNECTION:
case SSL_TYPE_QUIC_XSO:
if (!ossl_quic_conn_poll_events(ssl, events, do_tick, &revents))
/* above call raises ERR */
FAIL_ITEM(i);
if (revents != 0)
++result_count;
break;
#endif
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 */
out:
if (p_result_count != NULL)
*p_result_count = result_count;
return ok;
}