Coverage Report

Created: 2025-12-31 06:58

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/openssl34/ssl/quic/quic_rstream.c
Line
Count
Source
1
/*
2
 * Copyright 2022-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
#include <openssl/err.h>
10
#include "internal/common.h"
11
#include "internal/time.h"
12
#include "internal/quic_stream.h"
13
#include "internal/quic_sf_list.h"
14
#include "internal/ring_buf.h"
15
16
struct quic_rstream_st {
17
    SFRAME_LIST fl;
18
    QUIC_RXFC *rxfc;
19
    OSSL_STATM *statm;
20
    UINT_RANGE head_range;
21
    struct ring_buf rbuf;
22
};
23
24
QUIC_RSTREAM *ossl_quic_rstream_new(QUIC_RXFC *rxfc,
25
    OSSL_STATM *statm, size_t rbuf_size)
26
292k
{
27
292k
    QUIC_RSTREAM *ret = OPENSSL_zalloc(sizeof(*ret));
28
29
292k
    if (ret == NULL)
30
0
        return NULL;
31
32
292k
    ring_buf_init(&ret->rbuf);
33
292k
    if (!ring_buf_resize(&ret->rbuf, rbuf_size, 0)) {
34
0
        OPENSSL_free(ret);
35
0
        return NULL;
36
0
    }
37
38
292k
    ossl_sframe_list_init(&ret->fl);
39
292k
    ret->rxfc = rxfc;
40
292k
    ret->statm = statm;
41
292k
    return ret;
42
292k
}
43
44
void ossl_quic_rstream_free(QUIC_RSTREAM *qrs)
45
324k
{
46
324k
    int cleanse;
47
48
324k
    if (qrs == NULL)
49
31.2k
        return;
50
51
292k
    cleanse = qrs->fl.cleanse;
52
292k
    ossl_sframe_list_destroy(&qrs->fl);
53
292k
    ring_buf_destroy(&qrs->rbuf, cleanse);
54
292k
    OPENSSL_free(qrs);
55
292k
}
56
57
int ossl_quic_rstream_queue_data(QUIC_RSTREAM *qrs, OSSL_QRX_PKT *pkt,
58
    uint64_t offset,
59
    const unsigned char *data, uint64_t data_len,
60
    int fin)
61
279k
{
62
279k
    UINT_RANGE range;
63
64
279k
    if ((data == NULL && data_len != 0) || (data_len == 0 && fin == 0)) {
65
        /* empty frame allowed only at the end of the stream */
66
0
        ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
67
0
        return 0;
68
0
    }
69
70
279k
    range.start = offset;
71
279k
    range.end = offset + data_len;
72
73
279k
    return ossl_sframe_list_insert(&qrs->fl, &range, pkt, data, fin);
74
279k
}
75
76
static int read_internal(QUIC_RSTREAM *qrs, unsigned char *buf, size_t size,
77
    size_t *readbytes, int *fin, int drop)
78
33.0M
{
79
33.0M
    void *iter = NULL;
80
33.0M
    UINT_RANGE range;
81
33.0M
    const unsigned char *data;
82
33.0M
    uint64_t offset = 0;
83
33.0M
    size_t readbytes_ = 0;
84
33.0M
    int fin_ = 0, ret = 1;
85
86
33.0M
    while (ossl_sframe_list_peek(&qrs->fl, &iter, &range, &data, &fin_)) {
87
6.20k
        size_t l = (size_t)(range.end - range.start);
88
89
6.20k
        if (l > size) {
90
1.91k
            l = size;
91
1.91k
            fin_ = 0;
92
1.91k
        }
93
6.20k
        offset = range.start + l;
94
6.20k
        if (l == 0)
95
0
            break;
96
97
6.20k
        if (data == NULL) {
98
0
            size_t max_len;
99
100
0
            data = ring_buf_get_ptr(&qrs->rbuf, range.start, &max_len);
101
0
            if (!ossl_assert(data != NULL))
102
0
                return 0;
103
0
            if (max_len < l) {
104
0
                memcpy(buf, data, max_len);
105
0
                size -= max_len;
106
0
                buf += max_len;
107
0
                readbytes_ += max_len;
108
0
                l -= max_len;
109
0
                data = ring_buf_get_ptr(&qrs->rbuf, range.start + max_len,
110
0
                    &max_len);
111
0
                if (!ossl_assert(data != NULL) || !ossl_assert(max_len > l))
112
0
                    return 0;
113
0
            }
114
0
        }
115
116
6.20k
        memcpy(buf, data, l);
117
6.20k
        size -= l;
118
6.20k
        buf += l;
119
6.20k
        readbytes_ += l;
120
6.20k
        if (size == 0)
121
1.91k
            break;
122
6.20k
    }
123
124
33.0M
    if (drop && offset != 0) {
125
5.98k
        ret = ossl_sframe_list_drop_frames(&qrs->fl, offset);
126
5.98k
        ring_buf_cpop_range(&qrs->rbuf, 0, offset - 1, qrs->fl.cleanse);
127
5.98k
    }
128
129
33.0M
    if (ret) {
130
33.0M
        *readbytes = readbytes_;
131
33.0M
        *fin = fin_;
132
33.0M
    }
133
134
33.0M
    return ret;
135
33.0M
}
136
137
static OSSL_TIME get_rtt(QUIC_RSTREAM *qrs)
138
33.0M
{
139
33.0M
    OSSL_TIME rtt;
140
141
33.0M
    if (qrs->statm != NULL) {
142
0
        OSSL_RTT_INFO rtt_info;
143
144
0
        ossl_statm_get_rtt_info(qrs->statm, &rtt_info);
145
0
        rtt = rtt_info.smoothed_rtt;
146
33.0M
    } else {
147
33.0M
        rtt = ossl_time_zero();
148
33.0M
    }
149
33.0M
    return rtt;
150
33.0M
}
151
152
int ossl_quic_rstream_read(QUIC_RSTREAM *qrs, unsigned char *buf, size_t size,
153
    size_t *readbytes, int *fin)
154
33.0M
{
155
33.0M
    OSSL_TIME rtt = get_rtt(qrs);
156
157
33.0M
    if (!read_internal(qrs, buf, size, readbytes, fin, 1))
158
0
        return 0;
159
160
33.0M
    if (qrs->rxfc != NULL
161
0
        && !ossl_quic_rxfc_on_retire(qrs->rxfc, *readbytes, rtt))
162
0
        return 0;
163
164
33.0M
    return 1;
165
33.0M
}
166
167
int ossl_quic_rstream_peek(QUIC_RSTREAM *qrs, unsigned char *buf, size_t size,
168
    size_t *readbytes, int *fin)
169
0
{
170
0
    return read_internal(qrs, buf, size, readbytes, fin, 0);
171
0
}
172
173
int ossl_quic_rstream_available(QUIC_RSTREAM *qrs, size_t *avail, int *fin)
174
13.9M
{
175
13.9M
    void *iter = NULL;
176
13.9M
    UINT_RANGE range;
177
13.9M
    const unsigned char *data;
178
13.9M
    uint64_t avail_ = 0;
179
180
13.9M
    while (ossl_sframe_list_peek(&qrs->fl, &iter, &range, &data, fin))
181
4.49k
        avail_ += range.end - range.start;
182
183
#if SIZE_MAX < UINT64_MAX
184
    *avail = avail_ > SIZE_MAX ? SIZE_MAX : (size_t)avail_;
185
#else
186
13.9M
    *avail = (size_t)avail_;
187
13.9M
#endif
188
13.9M
    return 1;
189
13.9M
}
190
191
int ossl_quic_rstream_get_record(QUIC_RSTREAM *qrs,
192
    const unsigned char **record, size_t *rec_len,
193
    int *fin)
194
70.7M
{
195
70.7M
    const unsigned char *record_ = NULL;
196
70.7M
    size_t rec_len_, max_len;
197
198
70.7M
    if (!ossl_sframe_list_lock_head(&qrs->fl, &qrs->head_range, &record_, fin)) {
199
        /* No head frame to lock and return */
200
70.7M
        *record = NULL;
201
70.7M
        *rec_len = 0;
202
70.7M
        return 1;
203
70.7M
    }
204
205
    /* if final empty frame, we drop it immediately */
206
71.4k
    if (qrs->head_range.end == qrs->head_range.start) {
207
0
        if (!ossl_assert(*fin))
208
0
            return 0;
209
0
        if (!ossl_sframe_list_drop_frames(&qrs->fl, qrs->head_range.end))
210
0
            return 0;
211
0
    }
212
213
71.4k
    rec_len_ = (size_t)(qrs->head_range.end - qrs->head_range.start);
214
215
71.4k
    if (record_ == NULL && rec_len_ != 0) {
216
0
        record_ = ring_buf_get_ptr(&qrs->rbuf, qrs->head_range.start,
217
0
            &max_len);
218
0
        if (!ossl_assert(record_ != NULL))
219
0
            return 0;
220
0
        if (max_len < rec_len_) {
221
0
            rec_len_ = max_len;
222
0
            qrs->head_range.end = qrs->head_range.start + max_len;
223
0
        }
224
0
    }
225
226
71.4k
    *rec_len = rec_len_;
227
71.4k
    *record = record_;
228
71.4k
    return 1;
229
71.4k
}
230
231
int ossl_quic_rstream_release_record(QUIC_RSTREAM *qrs, size_t read_len)
232
71.4k
{
233
71.4k
    uint64_t offset;
234
235
71.4k
    if (!ossl_sframe_list_is_head_locked(&qrs->fl))
236
0
        return 0;
237
238
71.4k
    if (read_len > qrs->head_range.end - qrs->head_range.start) {
239
0
        if (read_len != SIZE_MAX)
240
0
            return 0;
241
0
        offset = qrs->head_range.end;
242
71.4k
    } else {
243
71.4k
        offset = qrs->head_range.start + read_len;
244
71.4k
    }
245
246
71.4k
    if (!ossl_sframe_list_drop_frames(&qrs->fl, offset))
247
0
        return 0;
248
249
71.4k
    if (offset > 0)
250
71.4k
        ring_buf_cpop_range(&qrs->rbuf, 0, offset - 1, qrs->fl.cleanse);
251
252
71.4k
    if (qrs->rxfc != NULL) {
253
0
        OSSL_TIME rtt = get_rtt(qrs);
254
255
0
        if (!ossl_quic_rxfc_on_retire(qrs->rxfc, offset, rtt))
256
0
            return 0;
257
0
    }
258
259
71.4k
    return 1;
260
71.4k
}
261
262
static int write_at_ring_buf_cb(uint64_t logical_offset,
263
    const unsigned char *buf,
264
    size_t buf_len,
265
    void *cb_arg)
266
0
{
267
0
    struct ring_buf *rbuf = cb_arg;
268
269
0
    return ring_buf_write_at(rbuf, logical_offset, buf, buf_len);
270
0
}
271
272
int ossl_quic_rstream_move_to_rbuf(QUIC_RSTREAM *qrs)
273
0
{
274
0
    if (ring_buf_avail(&qrs->rbuf) == 0)
275
0
        return 0;
276
0
    return ossl_sframe_list_move_data(&qrs->fl,
277
0
        write_at_ring_buf_cb, &qrs->rbuf);
278
0
}
279
280
int ossl_quic_rstream_resize_rbuf(QUIC_RSTREAM *qrs, size_t rbuf_size)
281
0
{
282
0
    if (ossl_sframe_list_is_head_locked(&qrs->fl))
283
0
        return 0;
284
285
0
    if (!ring_buf_resize(&qrs->rbuf, rbuf_size, qrs->fl.cleanse))
286
0
        return 0;
287
288
0
    return 1;
289
0
}
290
291
void ossl_quic_rstream_set_cleanse(QUIC_RSTREAM *qrs, int cleanse)
292
12.3k
{
293
12.3k
    qrs->fl.cleanse = cleanse;
294
12.3k
}