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