summaryrefslogtreecommitdiffstats
path: root/ssl/quic/quic_engine.c
blob: 932ac2a7f047b30d6c5cc313d4b2640493bbaa63 (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
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
/*
 * Copyright 2023 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/quic_engine.h"
#include "internal/quic_port.h"
#include "quic_engine_local.h"
#include "quic_port_local.h"
#include "../ssl_local.h"

/*
 * QUIC Engine
 * ===========
 */
static int qeng_init(QUIC_ENGINE *qeng);
static void qeng_cleanup(QUIC_ENGINE *qeng);
static void qeng_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags);

DEFINE_LIST_OF_IMPL(port, QUIC_PORT);

QUIC_ENGINE *ossl_quic_engine_new(const QUIC_ENGINE_ARGS *args)
{
    QUIC_ENGINE *qeng;

    if ((qeng = OPENSSL_zalloc(sizeof(QUIC_ENGINE))) == NULL)
        return NULL;

    qeng->libctx            = args->libctx;
    qeng->propq             = args->propq;
    qeng->mutex             = args->mutex;
    qeng->now_cb            = args->now_cb;
    qeng->now_cb_arg        = args->now_cb_arg;

    if (!qeng_init(qeng)) {
        OPENSSL_free(qeng);
        return NULL;
    }

    return qeng;
}

void ossl_quic_engine_free(QUIC_ENGINE *qeng)
{
    if (qeng == NULL)
        return;

    qeng_cleanup(qeng);
    OPENSSL_free(qeng);
}

static int qeng_init(QUIC_ENGINE *qeng)
{
    ossl_quic_reactor_init(&qeng->rtor, qeng_tick, qeng, ossl_time_zero());
    return 1;
}

static void qeng_cleanup(QUIC_ENGINE *qeng)
{
    assert(ossl_list_port_num(&qeng->port_list) == 0);
}

QUIC_REACTOR *ossl_quic_engine_get0_reactor(QUIC_ENGINE *qeng)
{
    return &qeng->rtor;
}

CRYPTO_MUTEX *ossl_quic_engine_get0_mutex(QUIC_ENGINE *qeng)
{
    return qeng->mutex;
}

OSSL_TIME ossl_quic_engine_get_time(QUIC_ENGINE *qeng)
{
    if (qeng->now_cb == NULL)
        return ossl_time_now();

    return qeng->now_cb(qeng->now_cb_arg);
}

void ossl_quic_engine_set_inhibit_tick(QUIC_ENGINE *qeng, int inhibit)
{
    qeng->inhibit_tick = (inhibit != 0);
}

OSSL_LIB_CTX *ossl_quic_engine_get0_libctx(QUIC_ENGINE *qeng)
{
    return qeng->libctx;
}

const char *ossl_quic_engine_get0_propq(QUIC_ENGINE *qeng)
{
    return qeng->propq;
}

/*
 * QUIC Engine: Child Object Lifecycle Management
 * ==============================================
 */

QUIC_PORT *ossl_quic_engine_create_port(QUIC_ENGINE *qeng,
                                        const QUIC_PORT_ARGS *args)
{
    QUIC_PORT_ARGS largs = *args;

    if (ossl_list_port_num(&qeng->port_list) > 0)
        /* TODO(QUIC MULTIPORT): We currently support only one port. */
        return NULL;

    if (largs.engine != NULL)
        return NULL;

    largs.engine = qeng;
    return ossl_quic_port_new(&largs);
}

/*
 * QUIC Engine: Ticker-Mutator
 * ===========================
 */

/*
 * The central ticker function called by the reactor. This does everything, or
 * at least everything network I/O related. Best effort - not allowed to fail
 * "loudly".
 */
static void qeng_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags)
{
    QUIC_ENGINE *qeng = arg;
    QUIC_PORT *port;

    res->net_read_desired   = 0;
    res->net_write_desired  = 0;
    res->tick_deadline      = ossl_time_infinite();

    if (qeng->inhibit_tick)
        return;

    /* Iterate through all ports and service them. */
    LIST_FOREACH(port, port, &qeng->port_list) {
        QUIC_TICK_RESULT subr = {0};

        ossl_quic_port_subtick(port, &subr, flags);
        ossl_quic_tick_result_merge_into(res, &subr);
    }
}