Path: blob/main/crypto/openssl/ssl/quic/quic_rstream.c
48266 views
/*1* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/8#include <openssl/err.h>9#include "internal/common.h"10#include "internal/time.h"11#include "internal/quic_stream.h"12#include "internal/quic_sf_list.h"13#include "internal/ring_buf.h"1415struct quic_rstream_st {16SFRAME_LIST fl;17QUIC_RXFC *rxfc;18OSSL_STATM *statm;19UINT_RANGE head_range;20struct ring_buf rbuf;21};2223QUIC_RSTREAM *ossl_quic_rstream_new(QUIC_RXFC *rxfc,24OSSL_STATM *statm, size_t rbuf_size)25{26QUIC_RSTREAM *ret = OPENSSL_zalloc(sizeof(*ret));2728if (ret == NULL)29return NULL;3031ring_buf_init(&ret->rbuf);32if (!ring_buf_resize(&ret->rbuf, rbuf_size, 0)) {33OPENSSL_free(ret);34return NULL;35}3637ossl_sframe_list_init(&ret->fl);38ret->rxfc = rxfc;39ret->statm = statm;40return ret;41}4243void ossl_quic_rstream_free(QUIC_RSTREAM *qrs)44{45int cleanse;4647if (qrs == NULL)48return;4950cleanse = qrs->fl.cleanse;51ossl_sframe_list_destroy(&qrs->fl);52ring_buf_destroy(&qrs->rbuf, cleanse);53OPENSSL_free(qrs);54}5556int ossl_quic_rstream_queue_data(QUIC_RSTREAM *qrs, OSSL_QRX_PKT *pkt,57uint64_t offset,58const unsigned char *data, uint64_t data_len,59int fin)60{61UINT_RANGE range;6263if ((data == NULL && data_len != 0) || (data_len == 0 && fin == 0)) {64/* empty frame allowed only at the end of the stream */65ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR);66return 0;67}6869range.start = offset;70range.end = offset + data_len;7172return ossl_sframe_list_insert(&qrs->fl, &range, pkt, data, fin);73}7475static int read_internal(QUIC_RSTREAM *qrs, unsigned char *buf, size_t size,76size_t *readbytes, int *fin, int drop)77{78void *iter = NULL;79UINT_RANGE range;80const unsigned char *data;81uint64_t offset = 0;82size_t readbytes_ = 0;83int fin_ = 0, ret = 1;8485while (ossl_sframe_list_peek(&qrs->fl, &iter, &range, &data, &fin_)) {86size_t l = (size_t)(range.end - range.start);8788if (l > size) {89l = size;90fin_ = 0;91}92offset = range.start + l;93if (l == 0)94break;9596if (data == NULL) {97size_t max_len;9899data = ring_buf_get_ptr(&qrs->rbuf, range.start, &max_len);100if (!ossl_assert(data != NULL))101return 0;102if (max_len < l) {103memcpy(buf, data, max_len);104size -= max_len;105buf += max_len;106readbytes_ += max_len;107l -= max_len;108data = ring_buf_get_ptr(&qrs->rbuf, range.start + max_len,109&max_len);110if (!ossl_assert(data != NULL) || !ossl_assert(max_len > l))111return 0;112}113}114115memcpy(buf, data, l);116size -= l;117buf += l;118readbytes_ += l;119if (size == 0)120break;121}122123if (drop && offset != 0) {124ret = ossl_sframe_list_drop_frames(&qrs->fl, offset);125ring_buf_cpop_range(&qrs->rbuf, 0, offset - 1, qrs->fl.cleanse);126}127128if (ret) {129*readbytes = readbytes_;130*fin = fin_;131}132133return ret;134}135136static OSSL_TIME get_rtt(QUIC_RSTREAM *qrs)137{138OSSL_TIME rtt;139140if (qrs->statm != NULL) {141OSSL_RTT_INFO rtt_info;142143ossl_statm_get_rtt_info(qrs->statm, &rtt_info);144rtt = rtt_info.smoothed_rtt;145} else {146rtt = ossl_time_zero();147}148return rtt;149}150151int ossl_quic_rstream_read(QUIC_RSTREAM *qrs, unsigned char *buf, size_t size,152size_t *readbytes, int *fin)153{154OSSL_TIME rtt = get_rtt(qrs);155156if (!read_internal(qrs, buf, size, readbytes, fin, 1))157return 0;158159if (qrs->rxfc != NULL160&& !ossl_quic_rxfc_on_retire(qrs->rxfc, *readbytes, rtt))161return 0;162163return 1;164}165166int ossl_quic_rstream_peek(QUIC_RSTREAM *qrs, unsigned char *buf, size_t size,167size_t *readbytes, int *fin)168{169return read_internal(qrs, buf, size, readbytes, fin, 0);170}171172int ossl_quic_rstream_available(QUIC_RSTREAM *qrs, size_t *avail, int *fin)173{174void *iter = NULL;175UINT_RANGE range;176const unsigned char *data;177uint64_t avail_ = 0;178179while (ossl_sframe_list_peek(&qrs->fl, &iter, &range, &data, fin))180avail_ += range.end - range.start;181182#if SIZE_MAX < UINT64_MAX183*avail = avail_ > SIZE_MAX ? SIZE_MAX : (size_t)avail_;184#else185*avail = (size_t)avail_;186#endif187return 1;188}189190int ossl_quic_rstream_get_record(QUIC_RSTREAM *qrs,191const unsigned char **record, size_t *rec_len,192int *fin)193{194const unsigned char *record_ = NULL;195size_t rec_len_, max_len;196197if (!ossl_sframe_list_lock_head(&qrs->fl, &qrs->head_range, &record_, fin)) {198/* No head frame to lock and return */199*record = NULL;200*rec_len = 0;201return 1;202}203204/* if final empty frame, we drop it immediately */205if (qrs->head_range.end == qrs->head_range.start) {206if (!ossl_assert(*fin))207return 0;208if (!ossl_sframe_list_drop_frames(&qrs->fl, qrs->head_range.end))209return 0;210}211212rec_len_ = (size_t)(qrs->head_range.end - qrs->head_range.start);213214if (record_ == NULL && rec_len_ != 0) {215record_ = ring_buf_get_ptr(&qrs->rbuf, qrs->head_range.start,216&max_len);217if (!ossl_assert(record_ != NULL))218return 0;219if (max_len < rec_len_) {220rec_len_ = max_len;221qrs->head_range.end = qrs->head_range.start + max_len;222}223}224225*rec_len = rec_len_;226*record = record_;227return 1;228}229230231int ossl_quic_rstream_release_record(QUIC_RSTREAM *qrs, size_t read_len)232{233uint64_t offset;234235if (!ossl_sframe_list_is_head_locked(&qrs->fl))236return 0;237238if (read_len > qrs->head_range.end - qrs->head_range.start) {239if (read_len != SIZE_MAX)240return 0;241offset = qrs->head_range.end;242} else {243offset = qrs->head_range.start + read_len;244}245246if (!ossl_sframe_list_drop_frames(&qrs->fl, offset))247return 0;248249if (offset > 0)250ring_buf_cpop_range(&qrs->rbuf, 0, offset - 1, qrs->fl.cleanse);251252if (qrs->rxfc != NULL) {253OSSL_TIME rtt = get_rtt(qrs);254255if (!ossl_quic_rxfc_on_retire(qrs->rxfc, offset, rtt))256return 0;257}258259return 1;260}261262static int write_at_ring_buf_cb(uint64_t logical_offset,263const unsigned char *buf,264size_t buf_len,265void *cb_arg)266{267struct ring_buf *rbuf = cb_arg;268269return ring_buf_write_at(rbuf, logical_offset, buf, buf_len);270}271272int ossl_quic_rstream_move_to_rbuf(QUIC_RSTREAM *qrs)273{274if (ring_buf_avail(&qrs->rbuf) == 0)275return 0;276return ossl_sframe_list_move_data(&qrs->fl,277write_at_ring_buf_cb, &qrs->rbuf);278}279280int ossl_quic_rstream_resize_rbuf(QUIC_RSTREAM *qrs, size_t rbuf_size)281{282if (ossl_sframe_list_is_head_locked(&qrs->fl))283return 0;284285if (!ring_buf_resize(&qrs->rbuf, rbuf_size, qrs->fl.cleanse))286return 0;287288return 1;289}290291void ossl_quic_rstream_set_cleanse(QUIC_RSTREAM *qrs, int cleanse)292{293qrs->fl.cleanse = cleanse;294}295296297