Path: blob/main/crypto/openssl/ssl/quic/quic_engine.c
48266 views
/*1* Copyright 2023-2025 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/89#include "internal/quic_engine.h"10#include "internal/quic_port.h"11#include "quic_engine_local.h"12#include "quic_port_local.h"13#include "../ssl_local.h"1415/*16* QUIC Engine17* ===========18*/19static int qeng_init(QUIC_ENGINE *qeng, uint64_t reactor_flags);20static void qeng_cleanup(QUIC_ENGINE *qeng);21static void qeng_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags);2223DEFINE_LIST_OF_IMPL(port, QUIC_PORT);2425QUIC_ENGINE *ossl_quic_engine_new(const QUIC_ENGINE_ARGS *args)26{27QUIC_ENGINE *qeng;2829if ((qeng = OPENSSL_zalloc(sizeof(QUIC_ENGINE))) == NULL)30return NULL;3132qeng->libctx = args->libctx;33qeng->propq = args->propq;34qeng->mutex = args->mutex;3536if (!qeng_init(qeng, args->reactor_flags)) {37OPENSSL_free(qeng);38return NULL;39}4041return qeng;42}4344void ossl_quic_engine_free(QUIC_ENGINE *qeng)45{46if (qeng == NULL)47return;4849qeng_cleanup(qeng);50OPENSSL_free(qeng);51}5253static int qeng_init(QUIC_ENGINE *qeng, uint64_t reactor_flags)54{55return ossl_quic_reactor_init(&qeng->rtor, qeng_tick, qeng,56qeng->mutex,57ossl_time_zero(), reactor_flags);58}5960static void qeng_cleanup(QUIC_ENGINE *qeng)61{62assert(ossl_list_port_num(&qeng->port_list) == 0);63ossl_quic_reactor_cleanup(&qeng->rtor);64}6566QUIC_REACTOR *ossl_quic_engine_get0_reactor(QUIC_ENGINE *qeng)67{68return &qeng->rtor;69}7071CRYPTO_MUTEX *ossl_quic_engine_get0_mutex(QUIC_ENGINE *qeng)72{73return qeng->mutex;74}7576OSSL_TIME ossl_quic_engine_get_time(QUIC_ENGINE *qeng)77{78if (qeng->now_cb == NULL)79return ossl_time_now();8081return qeng->now_cb(qeng->now_cb_arg);82}8384OSSL_TIME ossl_quic_engine_make_real_time(QUIC_ENGINE *qeng, OSSL_TIME tm)85{86OSSL_TIME offset;8788if (qeng->now_cb != NULL89&& !ossl_time_is_zero(tm)90&& !ossl_time_is_infinite(tm)) {9192offset = qeng->now_cb(qeng->now_cb_arg);9394/* If tm is earlier than offset then tm will end up as "now" */95tm = ossl_time_add(ossl_time_subtract(tm, offset), ossl_time_now());96}9798return tm;99}100101void ossl_quic_engine_set_time_cb(QUIC_ENGINE *qeng,102OSSL_TIME (*now_cb)(void *arg),103void *now_cb_arg)104{105qeng->now_cb = now_cb;106qeng->now_cb_arg = now_cb_arg;107}108109void ossl_quic_engine_set_inhibit_tick(QUIC_ENGINE *qeng, int inhibit)110{111qeng->inhibit_tick = (inhibit != 0);112}113114OSSL_LIB_CTX *ossl_quic_engine_get0_libctx(QUIC_ENGINE *qeng)115{116return qeng->libctx;117}118119const char *ossl_quic_engine_get0_propq(QUIC_ENGINE *qeng)120{121return qeng->propq;122}123124void ossl_quic_engine_update_poll_descriptors(QUIC_ENGINE *qeng, int force)125{126QUIC_PORT *port;127128/*129* TODO(QUIC MULTIPORT): The implementation of130* ossl_quic_port_update_poll_descriptors assumes an engine only ever has a131* single port for now due to reactor limitations. This limitation will be132* removed in future.133*134* TODO(QUIC MULTIPORT): Consider only iterating the port list when dirty at135* the engine level in future when we can have multiple ports. This is not136* important currently as the port list has a single entry.137*/138OSSL_LIST_FOREACH(port, port, &qeng->port_list)139ossl_quic_port_update_poll_descriptors(port, force);140}141142/*143* QUIC Engine: Child Object Lifecycle Management144* ==============================================145*/146147QUIC_PORT *ossl_quic_engine_create_port(QUIC_ENGINE *qeng,148const QUIC_PORT_ARGS *args)149{150QUIC_PORT_ARGS largs = *args;151152if (ossl_list_port_num(&qeng->port_list) > 0)153/* TODO(QUIC MULTIPORT): We currently support only one port. */154return NULL;155156if (largs.engine != NULL)157return NULL;158159largs.engine = qeng;160return ossl_quic_port_new(&largs);161}162163/*164* QUIC Engine: Ticker-Mutator165* ===========================166*/167168/*169* The central ticker function called by the reactor. This does everything, or170* at least everything network I/O related. Best effort - not allowed to fail171* "loudly".172*/173static void qeng_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags)174{175QUIC_ENGINE *qeng = arg;176QUIC_PORT *port;177178res->net_read_desired = 0;179res->net_write_desired = 0;180res->notify_other_threads = 0;181res->tick_deadline = ossl_time_infinite();182183if (qeng->inhibit_tick)184return;185186/* Iterate through all ports and service them. */187OSSL_LIST_FOREACH(port, port, &qeng->port_list) {188QUIC_TICK_RESULT subr = {0};189190ossl_quic_port_subtick(port, &subr, flags);191ossl_quic_tick_result_merge_into(res, &subr);192}193}194195196