1 | /*
|
---|
2 | * Copyright 2023 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/quic_engine.h"
|
---|
11 | #include "internal/quic_port.h"
|
---|
12 | #include "quic_engine_local.h"
|
---|
13 | #include "quic_port_local.h"
|
---|
14 | #include "../ssl_local.h"
|
---|
15 |
|
---|
16 | /*
|
---|
17 | * QUIC Engine
|
---|
18 | * ===========
|
---|
19 | */
|
---|
20 | static int qeng_init(QUIC_ENGINE *qeng);
|
---|
21 | static void qeng_cleanup(QUIC_ENGINE *qeng);
|
---|
22 | static void qeng_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags);
|
---|
23 |
|
---|
24 | DEFINE_LIST_OF_IMPL(port, QUIC_PORT);
|
---|
25 |
|
---|
26 | QUIC_ENGINE *ossl_quic_engine_new(const QUIC_ENGINE_ARGS *args)
|
---|
27 | {
|
---|
28 | QUIC_ENGINE *qeng;
|
---|
29 |
|
---|
30 | if ((qeng = OPENSSL_zalloc(sizeof(QUIC_ENGINE))) == NULL)
|
---|
31 | return NULL;
|
---|
32 |
|
---|
33 | qeng->libctx = args->libctx;
|
---|
34 | qeng->propq = args->propq;
|
---|
35 | qeng->mutex = args->mutex;
|
---|
36 | qeng->now_cb = args->now_cb;
|
---|
37 | qeng->now_cb_arg = args->now_cb_arg;
|
---|
38 |
|
---|
39 | if (!qeng_init(qeng)) {
|
---|
40 | OPENSSL_free(qeng);
|
---|
41 | return NULL;
|
---|
42 | }
|
---|
43 |
|
---|
44 | return qeng;
|
---|
45 | }
|
---|
46 |
|
---|
47 | void ossl_quic_engine_free(QUIC_ENGINE *qeng)
|
---|
48 | {
|
---|
49 | if (qeng == NULL)
|
---|
50 | return;
|
---|
51 |
|
---|
52 | qeng_cleanup(qeng);
|
---|
53 | OPENSSL_free(qeng);
|
---|
54 | }
|
---|
55 |
|
---|
56 | static int qeng_init(QUIC_ENGINE *qeng)
|
---|
57 | {
|
---|
58 | ossl_quic_reactor_init(&qeng->rtor, qeng_tick, qeng, ossl_time_zero());
|
---|
59 | return 1;
|
---|
60 | }
|
---|
61 |
|
---|
62 | static void qeng_cleanup(QUIC_ENGINE *qeng)
|
---|
63 | {
|
---|
64 | assert(ossl_list_port_num(&qeng->port_list) == 0);
|
---|
65 | }
|
---|
66 |
|
---|
67 | QUIC_REACTOR *ossl_quic_engine_get0_reactor(QUIC_ENGINE *qeng)
|
---|
68 | {
|
---|
69 | return &qeng->rtor;
|
---|
70 | }
|
---|
71 |
|
---|
72 | CRYPTO_MUTEX *ossl_quic_engine_get0_mutex(QUIC_ENGINE *qeng)
|
---|
73 | {
|
---|
74 | return qeng->mutex;
|
---|
75 | }
|
---|
76 |
|
---|
77 | OSSL_TIME ossl_quic_engine_get_time(QUIC_ENGINE *qeng)
|
---|
78 | {
|
---|
79 | if (qeng->now_cb == NULL)
|
---|
80 | return ossl_time_now();
|
---|
81 |
|
---|
82 | return qeng->now_cb(qeng->now_cb_arg);
|
---|
83 | }
|
---|
84 |
|
---|
85 | void ossl_quic_engine_set_inhibit_tick(QUIC_ENGINE *qeng, int inhibit)
|
---|
86 | {
|
---|
87 | qeng->inhibit_tick = (inhibit != 0);
|
---|
88 | }
|
---|
89 |
|
---|
90 | /*
|
---|
91 | * QUIC Engine: Child Object Lifecycle Management
|
---|
92 | * ==============================================
|
---|
93 | */
|
---|
94 |
|
---|
95 | QUIC_PORT *ossl_quic_engine_create_port(QUIC_ENGINE *qeng,
|
---|
96 | const QUIC_PORT_ARGS *args)
|
---|
97 | {
|
---|
98 | QUIC_PORT_ARGS largs = *args;
|
---|
99 |
|
---|
100 | if (ossl_list_port_num(&qeng->port_list) > 0)
|
---|
101 | /* TODO(QUIC MULTIPORT): We currently support only one port. */
|
---|
102 | return NULL;
|
---|
103 |
|
---|
104 | if (largs.engine != NULL)
|
---|
105 | return NULL;
|
---|
106 |
|
---|
107 | largs.engine = qeng;
|
---|
108 | return ossl_quic_port_new(&largs);
|
---|
109 | }
|
---|
110 |
|
---|
111 | /*
|
---|
112 | * QUIC Engine: Ticker-Mutator
|
---|
113 | * ==========================
|
---|
114 | */
|
---|
115 |
|
---|
116 | /*
|
---|
117 | * The central ticker function called by the reactor. This does everything, or
|
---|
118 | * at least everything network I/O related. Best effort - not allowed to fail
|
---|
119 | * "loudly".
|
---|
120 | */
|
---|
121 | static void qeng_tick(QUIC_TICK_RESULT *res, void *arg, uint32_t flags)
|
---|
122 | {
|
---|
123 | QUIC_ENGINE *qeng = arg;
|
---|
124 | QUIC_PORT *port;
|
---|
125 |
|
---|
126 | res->net_read_desired = 0;
|
---|
127 | res->net_write_desired = 0;
|
---|
128 | res->tick_deadline = ossl_time_infinite();
|
---|
129 |
|
---|
130 | if (qeng->inhibit_tick)
|
---|
131 | return;
|
---|
132 |
|
---|
133 | /* Iterate through all ports and service them. */
|
---|
134 | LIST_FOREACH(port, port, &qeng->port_list) {
|
---|
135 | QUIC_TICK_RESULT subr = {0};
|
---|
136 |
|
---|
137 | ossl_quic_port_subtick(port, &subr, flags);
|
---|
138 | ossl_quic_tick_result_merge_into(res, &subr);
|
---|
139 | }
|
---|
140 | }
|
---|