Coverage Report

Created: 2026-10-28 06:28

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