Coverage Report

Created: 2026-09-12 06:55

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl41/ssl/quic/quic_obj.c
Line
Count
Source
1
/*
2
 * Copyright 2024-2026 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 "quic_obj_local.h"
11
#include "quic_local.h"
12
#include "internal/ssl_unwrap.h"
13
14
static int obj_update_cache(QUIC_OBJ *obj);
15
16
int ossl_quic_obj_init(QUIC_OBJ *obj,
17
    SSL_CTX *ctx,
18
    int type,
19
    SSL *parent_obj,
20
    QUIC_ENGINE *engine,
21
    QUIC_PORT *port)
22
10.8k
{
23
10.8k
    QUIC_OBJ *parent = (QUIC_OBJ *)parent_obj;
24
10.8k
    int is_event_leader = (engine != NULL);
25
10.8k
    int is_port_leader = (port != NULL);
26
27
10.8k
    if (!ossl_assert(obj != NULL && !obj->init_done && SSL_TYPE_IS_QUIC(type)
28
10.8k
            && (parent_obj == NULL
29
10.8k
                || (IS_QUIC(parent_obj) && parent->init_done))))
30
0
        return 0;
31
32
    /* Event leader is always the root object. */
33
10.8k
    if (!ossl_assert(!is_event_leader || parent_obj == NULL))
34
0
        return 0;
35
36
10.8k
    if (!ossl_ssl_init(&obj->ssl, ctx, ctx->method, type))
37
0
        goto err;
38
39
10.8k
    obj->domain_flags
40
10.8k
        = parent != NULL ? parent->domain_flags : ctx->domain_flags;
41
10.8k
    obj->parent_obj = parent;
42
10.8k
    obj->is_event_leader = is_event_leader;
43
10.8k
    obj->is_port_leader = is_port_leader;
44
10.8k
    obj->engine = engine;
45
10.8k
    obj->port = port;
46
10.8k
    obj->req_blocking_mode = QUIC_BLOCKING_MODE_INHERIT;
47
10.8k
    if (!obj_update_cache(obj))
48
0
        goto err;
49
50
10.8k
    obj->init_done = 1;
51
10.8k
    return 1;
52
53
0
err:
54
0
    obj->is_event_leader = 0;
55
0
    obj->is_port_leader = 0;
56
0
    return 0;
57
10.8k
}
58
59
void ossl_quic_obj_reparent(QUIC_OBJ *obj, QUIC_OBJ *parent)
60
0
{
61
0
    if (!ossl_assert(obj != NULL && obj->init_done
62
0
            && parent != NULL && parent->init_done
63
0
            && obj->is_event_leader && obj->is_port_leader
64
0
            && obj->parent_obj == NULL))
65
0
        return;
66
67
0
    obj->parent_obj = parent;
68
0
    obj->is_event_leader = 0;
69
0
    obj->is_port_leader = 0;
70
0
    obj->domain_flags = parent->domain_flags;
71
0
    (void)obj_update_cache(obj);
72
0
}
73
74
static int obj_update_cache(QUIC_OBJ *obj)
75
40.0k
{
76
40.0k
    QUIC_OBJ *p;
77
78
46.9k
    for (p = obj; p != NULL && !p->is_event_leader;
79
40.0k
        p = p->parent_obj)
80
6.88k
        if (!ossl_assert(p == obj || p->init_done))
81
0
            return 0;
82
83
40.0k
    if (!ossl_assert(p != NULL))
84
0
        return 0;
85
86
    /*
87
     * Offset of ->ssl is guaranteed to be 0 but the NULL check makes ubsan
88
     * happy.
89
     */
90
40.0k
    obj->cached_event_leader = p;
91
40.0k
    obj->engine = p->engine;
92
93
46.9k
    for (p = obj; p != NULL && !p->is_port_leader;
94
40.0k
        p = p->parent_obj)
95
6.88k
        ;
96
97
40.0k
    obj->cached_port_leader = p;
98
40.0k
    obj->port = (p != NULL) ? p->port : NULL;
99
40.0k
    return 1;
100
40.0k
}
101
102
SSL_CONNECTION *ossl_quic_obj_get0_handshake_layer(QUIC_OBJ *obj)
103
93.6M
{
104
93.6M
    assert(obj != NULL && obj->init_done);
105
106
93.6M
    if (obj->ssl.type != SSL_TYPE_QUIC_CONNECTION)
107
5.75M
        return NULL;
108
109
87.8M
    return SSL_CONNECTION_FROM_SSL_ONLY(((QUIC_CONNECTION *)obj)->tls);
110
93.6M
}
111
112
/* (Returns a cached result.) */
113
int ossl_quic_obj_can_support_blocking(const QUIC_OBJ *obj)
114
71.3M
{
115
71.3M
    QUIC_REACTOR *rtor;
116
117
71.3M
    assert(obj != NULL);
118
71.3M
    rtor = ossl_quic_obj_get0_reactor(obj);
119
120
71.3M
    if ((obj->domain_flags
121
71.3M
            & (SSL_DOMAIN_FLAG_LEGACY_BLOCKING | SSL_DOMAIN_FLAG_BLOCKING))
122
71.3M
        == 0)
123
0
        return 0;
124
125
71.3M
    return ossl_quic_reactor_can_poll_r(rtor)
126
71.3M
        || ossl_quic_reactor_can_poll_w(rtor);
127
71.3M
}
128
129
int ossl_quic_obj_desires_blocking(const QUIC_OBJ *obj)
130
100M
{
131
100M
    unsigned int req_blocking_mode;
132
133
100M
    assert(obj != NULL);
134
102M
    for (; (req_blocking_mode = obj->req_blocking_mode) == QUIC_BLOCKING_MODE_INHERIT
135
102M
        && obj->parent_obj != NULL;
136
100M
        obj = obj->parent_obj)
137
2.11M
        ;
138
139
100M
    return req_blocking_mode != QUIC_BLOCKING_MODE_NONBLOCKING;
140
100M
}
141
142
int ossl_quic_obj_blocking(const QUIC_OBJ *obj)
143
71.3M
{
144
71.3M
    assert(obj != NULL);
145
146
71.3M
    if (!ossl_quic_obj_desires_blocking(obj))
147
0
        return 0;
148
149
71.3M
    ossl_quic_engine_update_poll_descriptors(ossl_quic_obj_get0_engine(obj),
150
71.3M
        /*force=*/0);
151
71.3M
    return ossl_quic_obj_can_support_blocking(obj);
152
71.3M
}
153
154
void ossl_quic_obj_set_blocking_mode(QUIC_OBJ *obj, unsigned int mode)
155
0
{
156
0
    assert(obj != NULL);
157
158
0
    obj->req_blocking_mode = mode;
159
0
}