Coverage Report

Created: 2026-10-28 06:28

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl36/ssl/quic/quic_rstream.c
Line
Count
Source
1
/*
2
 * Copyright 2022-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
#include <openssl/err.h>
10
#include "internal/common.h"
11
#include "internal/time.h"
12
#include "internal/quic_stream.h"
13
#include "internal/quic_strm_reas.h"
14
#include "internal/ring_buf.h"
15
16
struct quic_rstream_st {
17
    SFRAME_SET fs;
18
    QUIC_RXFC *rxfc;
19
    OSSL_STATM *statm;
20
    UINT_RANGE head_range;
21
};
22
23
#if !defined(NDEBUG) && defined(WITH_RSTREAM_DEBUG)
24
#include <stdio.h>
25
#define DEBUG_PRINT(...) fprintf(__VA_ARGS__)
26
#else
27
87.1M
#define DEBUG_PRINT(...) (void)(0)
28
#endif
29
30
QUIC_RSTREAM *ossl_quic_rstream_new(QUIC_RXFC *rxfc,
31
    OSSL_STATM *statm, QUIC_RSTREAM_QPARM *rsqp)
32
299k
{
33
299k
    QUIC_RSTREAM *ret = OPENSSL_zalloc(sizeof(*ret));
34
35
299k
    if (ret == NULL)
36
0
        return NULL;
37
38
299k
    ossl_sframe_set_init(&ret->fs, rsqp);
39
299k
    ret->rxfc = rxfc;
40
299k
    ret->statm = statm;
41
299k
    return ret;
42
299k
}
43
44
void ossl_quic_rstream_free(QUIC_RSTREAM *qrs)
45
331k
{
46
331k
    if (qrs == NULL)
47
31.9k
        return;
48
49
299k
    ossl_sframe_set_destroy_ranges(&qrs->fs);
50
299k
    OPENSSL_free(qrs);
51
299k
}
52
53
int ossl_quic_rstream_queue_data(QUIC_RSTREAM *qrs, OSSL_QRX_PKT *pkt,
54
    uint64_t offset,
55
    const unsigned char *data, uint64_t data_len,
56
    int fin)
57
215k
{
58
215k
    UINT_RANGE range;
59
60
215k
    if ((data == NULL && data_len != 0) || (data_len == 0 && fin == 0)) {
61
        /* empty frame allowed only at the end of the stream */
62
0
        ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
63
0
        return 0;
64
0
    }
65
66
215k
    range.start = offset;
67
215k
    range.end = offset + data_len;
68
69
215k
    return ossl_sframe_set_insert(&qrs->fs, &range, pkt, data, fin);
70
215k
}
71
72
static int read_internal(QUIC_RSTREAM *qrs, unsigned char *buf, size_t size,
73
    size_t *readbytes, int *fin, int drop)
74
43.5M
{
75
43.5M
    void *iter = NULL;
76
43.5M
    UINT_RANGE range;
77
43.5M
    const unsigned char *data;
78
43.5M
    uint64_t offset = 0;
79
43.5M
    size_t readbytes_ = 0;
80
43.5M
    int fin_ = 0, ret = 1;
81
82
43.5M
    DEBUG_PRINT(stderr, "%s want: %zu\n", OPENSSL_FUNC, size);
83
43.5M
    while (ossl_sframe_set_peek(&qrs->fs, &iter, &range, &data, &fin_)) {
84
5.09k
        size_t l = (size_t)(range.end - range.start);
85
86
5.09k
        DEBUG_PRINT(stderr, "\t[ %llu, %llu ]\n", range.start, range.end);
87
5.09k
        if (l > size) {
88
1.47k
            l = size;
89
1.47k
            fin_ = 0;
90
1.47k
        }
91
5.09k
        offset = range.start + l;
92
5.09k
        if (l == 0)
93
0
            break;
94
95
5.09k
        memcpy(buf, data, l);
96
5.09k
        size -= l;
97
5.09k
        buf += l;
98
5.09k
        readbytes_ += l;
99
5.09k
        if (size == 0)
100
1.47k
            break;
101
5.09k
    }
102
103
43.5M
    if (drop && offset != 0)
104
4.95k
        ret = ossl_sframe_set_move_offset(&qrs->fs, offset);
105
106
43.5M
    if (ret) {
107
43.5M
        DEBUG_PRINT(stderr, "%s got: %zu\n", OPENSSL_FUNC, readbytes_);
108
43.5M
        *readbytes = readbytes_;
109
43.5M
        *fin = fin_;
110
43.5M
    } else {
111
0
        DEBUG_PRINT(stderr, "%s got: nothing\n", OPENSSL_FUNC);
112
0
    }
113
114
43.5M
    return ret;
115
43.5M
}
116
117
static OSSL_TIME get_rtt(QUIC_RSTREAM *qrs)
118
43.5M
{
119
43.5M
    OSSL_TIME rtt;
120
121
43.5M
    if (qrs->statm != NULL) {
122
0
        OSSL_RTT_INFO rtt_info;
123
124
0
        ossl_statm_get_rtt_info(qrs->statm, &rtt_info);
125
0
        rtt = rtt_info.smoothed_rtt;
126
43.5M
    } else {
127
43.5M
        rtt = ossl_time_zero();
128
43.5M
    }
129
43.5M
    return rtt;
130
43.5M
}
131
132
int ossl_quic_rstream_read(QUIC_RSTREAM *qrs, unsigned char *buf, size_t size,
133
    size_t *readbytes, int *fin)
134
43.5M
{
135
43.5M
    OSSL_TIME rtt = get_rtt(qrs);
136
137
43.5M
    if (!read_internal(qrs, buf, size, readbytes, fin, 1))
138
0
        return 0;
139
140
43.5M
    if (qrs->rxfc != NULL
141
0
        && !ossl_quic_rxfc_on_retire(qrs->rxfc, *readbytes, rtt))
142
0
        return 0;
143
144
43.5M
    return 1;
145
43.5M
}
146
147
int ossl_quic_rstream_peek(QUIC_RSTREAM *qrs, unsigned char *buf, size_t size,
148
    size_t *readbytes, int *fin)
149
0
{
150
0
    return read_internal(qrs, buf, size, readbytes, fin, 0);
151
0
}
152
153
int ossl_quic_rstream_available(QUIC_RSTREAM *qrs, size_t *avail, int *fin)
154
17.9M
{
155
17.9M
    uint64_t avail_ = 0;
156
157
17.9M
    ossl_sframe_set_avail(&qrs->fs, &avail_, fin);
158
159
#if SIZE_MAX < UINT64_MAX
160
    *avail = avail_ > SIZE_MAX ? SIZE_MAX : (size_t)avail_;
161
#else
162
17.9M
    *avail = (size_t)avail_;
163
17.9M
#endif
164
17.9M
    return 1;
165
17.9M
}
166
167
int ossl_quic_rstream_get_record(QUIC_RSTREAM *qrs,
168
    const unsigned char **record, size_t *rec_len,
169
    int *fin)
170
71.2M
{
171
71.2M
    const unsigned char *record_ = NULL;
172
71.2M
    void *iterator = NULL;
173
71.2M
    size_t rec_len_;
174
71.2M
    int ok;
175
176
71.2M
    ok = ossl_sframe_set_peek(&qrs->fs, &iterator, &qrs->head_range, &record_,
177
71.2M
        fin);
178
71.2M
    if (ok == 0) {
179
71.1M
        *record = NULL;
180
71.1M
        *rec_len = 0;
181
71.1M
        return 1;
182
71.1M
    }
183
184
74.5k
    DEBUG_PRINT(stderr, "%s head: [ %llu, %llu ]\n", OPENSSL_FUNC,
185
74.5k
        qrs->head_range.start, qrs->head_range.end);
186
    /* if final empty frame, we drop it immediately */
187
74.5k
    if (qrs->head_range.end == qrs->head_range.start) {
188
0
        if (!ossl_assert(*fin))
189
0
            return 0;
190
0
        if (!ossl_sframe_set_move_offset(&qrs->fs, qrs->head_range.end))
191
0
            return 0;
192
0
    }
193
194
74.5k
    rec_len_ = (size_t)(qrs->head_range.end - qrs->head_range.start);
195
74.5k
    *rec_len = rec_len_;
196
74.5k
    *record = record_;
197
198
74.5k
    return 1;
199
74.5k
}
200
201
int ossl_quic_rstream_release_record(QUIC_RSTREAM *qrs, size_t read_len)
202
74.5k
{
203
74.5k
    uint64_t offset;
204
205
74.5k
    if (read_len > qrs->head_range.end - qrs->head_range.start) {
206
0
        if (read_len != SIZE_MAX)
207
0
            return 0;
208
0
        offset = qrs->head_range.end;
209
74.5k
    } else {
210
74.5k
        offset = qrs->head_range.start + read_len;
211
74.5k
    }
212
213
74.5k
    if (!ossl_sframe_set_move_offset(&qrs->fs, offset))
214
0
        return 0;
215
216
74.5k
    if (qrs->rxfc != NULL) {
217
0
        OSSL_TIME rtt = get_rtt(qrs);
218
219
0
        if (!ossl_quic_rxfc_on_retire(qrs->rxfc, offset, rtt))
220
0
            return 0;
221
0
    }
222
223
74.5k
    return 1;
224
74.5k
}
225
226
void ossl_quic_rstream_set_cleanse(QUIC_RSTREAM *qrs, int cleanse)
227
12.1k
{
228
12.1k
    qrs->fs.cleanse = cleanse;
229
12.1k
}
230
231
size_t ossl_quic_rstream_get_chunk_count(QUIC_RSTREAM *qrs)
232
0
{
233
0
    return qrs->fs.stream_chunks;
234
0
}
235
236
size_t ossl_quic_rstream_get_range_count(QUIC_RSTREAM *qrs)
237
0
{
238
0
    return qrs->fs.stream_ranges;
239
0
}