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