2 * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
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
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"
16 struct quic_rstream_st {
20 UINT_RANGE head_range;
24 QUIC_RSTREAM *ossl_quic_rstream_new(QUIC_RXFC *rxfc,
25 OSSL_STATM *statm, size_t rbuf_size)
27 QUIC_RSTREAM *ret = OPENSSL_zalloc(sizeof(*ret));
32 ring_buf_init(&ret->rbuf);
33 if (!ring_buf_resize(&ret->rbuf, rbuf_size)) {
38 ossl_sframe_list_init(&ret->fl);
44 void ossl_quic_rstream_free(QUIC_RSTREAM *qrs)
49 ossl_sframe_list_destroy(&qrs->fl);
50 ring_buf_destroy(&qrs->rbuf);
54 int ossl_quic_rstream_queue_data(QUIC_RSTREAM *qrs, OSSL_QRX_PKT *pkt,
56 const unsigned char *data, uint64_t data_len,
61 if ((data == NULL && data_len != 0) || (data_len == 0 && fin == 0)) {
62 /* empty frame allowed only at the end of the stream */
63 ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);
68 range.end = offset + data_len;
70 return ossl_sframe_list_insert(&qrs->fl, &range, pkt, data, fin);
73 static int read_internal(QUIC_RSTREAM *qrs, unsigned char *buf, size_t size,
74 size_t *readbytes, int *fin, int drop)
78 const unsigned char *data;
80 size_t readbytes_ = 0;
81 int fin_ = 0, ret = 1;
83 while (ossl_sframe_list_peek(&qrs->fl, &iter, &range, &data, &fin_)) {
84 size_t l = (size_t)(range.end - range.start);
90 offset = range.start + l;
97 data = ring_buf_get_ptr(&qrs->rbuf, range.start, &max_len);
98 if (!ossl_assert(data != NULL))
101 memcpy(buf, data, max_len);
104 readbytes_ += max_len;
106 data = ring_buf_get_ptr(&qrs->rbuf, range.start + max_len,
108 if (!ossl_assert(data != NULL) || !ossl_assert(max_len > l))
113 memcpy(buf, data, l);
121 if (drop && offset != 0) {
122 ret = ossl_sframe_list_drop_frames(&qrs->fl, offset);
123 ring_buf_cpop_range(&qrs->rbuf, 0, offset - 1, qrs->fl.cleanse);
127 *readbytes = readbytes_;
134 static OSSL_TIME get_rtt(QUIC_RSTREAM *qrs)
138 if (qrs->statm != NULL) {
139 OSSL_RTT_INFO rtt_info;
141 ossl_statm_get_rtt_info(qrs->statm, &rtt_info);
142 rtt = rtt_info.smoothed_rtt;
144 rtt = ossl_time_zero();
149 int ossl_quic_rstream_read(QUIC_RSTREAM *qrs, unsigned char *buf, size_t size,
150 size_t *readbytes, int *fin)
152 OSSL_TIME rtt = get_rtt(qrs);
154 if (!read_internal(qrs, buf, size, readbytes, fin, 1))
157 if (qrs->rxfc != NULL
158 && !ossl_quic_rxfc_on_retire(qrs->rxfc, *readbytes, rtt))
164 int ossl_quic_rstream_peek(QUIC_RSTREAM *qrs, unsigned char *buf, size_t size,
165 size_t *readbytes, int *fin)
167 return read_internal(qrs, buf, size, readbytes, fin, 0);
170 int ossl_quic_rstream_available(QUIC_RSTREAM *qrs, size_t *avail, int *fin)
174 const unsigned char *data;
177 while (ossl_sframe_list_peek(&qrs->fl, &iter, &range, &data, fin))
178 avail_ += range.end - range.start;
180 #if SIZE_MAX < UINT64_MAX
181 *avail = avail_ > SIZE_MAX ? SIZE_MAX : (size_t)avail_;
183 *avail = (size_t)avail_;
188 int ossl_quic_rstream_get_record(QUIC_RSTREAM *qrs,
189 const unsigned char **record, size_t *rec_len,
192 const unsigned char *record_ = NULL;
193 size_t rec_len_, max_len;
195 if (!ossl_sframe_list_lock_head(&qrs->fl, &qrs->head_range, &record_, fin)) {
196 /* No head frame to lock and return */
202 /* if final empty frame, we drop it immediately */
203 if (qrs->head_range.end == qrs->head_range.start) {
204 if (!ossl_assert(*fin))
206 if (!ossl_sframe_list_drop_frames(&qrs->fl, qrs->head_range.end))
210 rec_len_ = (size_t)(qrs->head_range.end - qrs->head_range.start);
212 if (record_ == NULL && rec_len_ != 0) {
213 record_ = ring_buf_get_ptr(&qrs->rbuf, qrs->head_range.start,
215 if (!ossl_assert(record_ != NULL))
217 if (max_len < rec_len_) {
219 qrs->head_range.end = qrs->head_range.start + max_len;
229 int ossl_quic_rstream_release_record(QUIC_RSTREAM *qrs, size_t read_len)
233 if (!ossl_sframe_list_is_head_locked(&qrs->fl))
236 if (read_len > qrs->head_range.end - qrs->head_range.start) {
237 if (read_len != SIZE_MAX)
239 offset = qrs->head_range.end;
241 offset = qrs->head_range.start + read_len;
244 if (!ossl_sframe_list_drop_frames(&qrs->fl, offset))
248 ring_buf_cpop_range(&qrs->rbuf, 0, offset - 1, qrs->fl.cleanse);
250 if (qrs->rxfc != NULL) {
251 OSSL_TIME rtt = get_rtt(qrs);
253 if (!ossl_quic_rxfc_on_retire(qrs->rxfc, offset, rtt))
260 static int write_at_ring_buf_cb(uint64_t logical_offset,
261 const unsigned char *buf,
265 struct ring_buf *rbuf = cb_arg;
267 return ring_buf_write_at(rbuf, logical_offset, buf, buf_len);
270 int ossl_quic_rstream_move_to_rbuf(QUIC_RSTREAM *qrs)
272 if (ring_buf_avail(&qrs->rbuf) == 0)
274 return ossl_sframe_list_move_data(&qrs->fl,
275 write_at_ring_buf_cb, &qrs->rbuf);
278 int ossl_quic_rstream_resize_rbuf(QUIC_RSTREAM *qrs, size_t rbuf_size)
280 /* TODO(QUIC): Do we need to distinguish different error conditions ? */
281 if (ossl_sframe_list_is_head_locked(&qrs->fl))
284 if (!ring_buf_resize(&qrs->rbuf, rbuf_size))
290 void ossl_quic_rstream_set_cleanse(QUIC_RSTREAM *qrs, int cleanse)
292 qrs->fl.cleanse = cleanse;