mirror of
https://github.com/openssl/openssl.git
synced 2024-12-27 06:21:43 +08:00
2113ea584c
Add API calls to avoid copying data when reading These are ossl_quic_rstream_get_record() and ossl_quic_rstream_release_record(). Add side storage for the stream frame data. When there are too many packets referenced by the receiving stream the function ossl_quic_rstream_move_to_rbuf() can be called to move the data to a ring buffer. Reviewed-by: Matt Caswell <matt@openssl.org> Reviewed-by: Hugo Landau <hlandau@openssl.org> (Merged from https://github.com/openssl/openssl/pull/19794)
150 lines
5.2 KiB
C
150 lines
5.2 KiB
C
/*
|
|
* Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
|
|
*
|
|
* Licensed under the Apache License 2.0 (the "License"). You may not use
|
|
* this file except in compliance with the License. You can obtain a copy
|
|
* in the file LICENSE in the source distribution or at
|
|
* https://www.openssl.org/source/license.html
|
|
*/
|
|
|
|
#ifndef OSSL_QUIC_SF_LIST_H
|
|
# define OSSL_QUIC_SF_LIST_H
|
|
|
|
#include "internal/common.h"
|
|
#include "internal/uint_set.h"
|
|
#include "internal/quic_record_rx.h"
|
|
|
|
/*
|
|
* Stream frame list
|
|
* =================
|
|
*
|
|
* This data structure supports similar operations as uint64 set but
|
|
* it has slightly different invariants and also carries data associated with
|
|
* the ranges in the list.
|
|
*
|
|
* Operations:
|
|
* Insert frame (optimized insertion at the beginning and at the end).
|
|
* Iterated peek into the frame(s) from the beginning.
|
|
* Dropping frames from the beginning up to an offset (exclusive).
|
|
*
|
|
* Invariant: The frames in the list are sorted by the start and end bounds.
|
|
* Invariant: There are no fully overlapping frames or frames that would
|
|
* be fully encompassed by another frame in the list.
|
|
* Invariant: No frame has start > end.
|
|
* Invariant: The range start is inclusive the end is exclusive to be
|
|
* able to mark an empty frame.
|
|
* Invariant: The offset never points further than into the first frame.
|
|
*/
|
|
# ifndef OPENSSL_NO_QUIC
|
|
|
|
typedef struct stream_frame_st STREAM_FRAME;
|
|
|
|
typedef struct sframe_list_st {
|
|
STREAM_FRAME *head, *tail;
|
|
/* Is the tail frame final. */
|
|
unsigned int fin;
|
|
/* Number of stream frames in the list. */
|
|
size_t num_frames;
|
|
/* Offset of data not yet dropped */
|
|
uint64_t offset;
|
|
/* Is head locked ? */
|
|
int head_locked;
|
|
} SFRAME_LIST;
|
|
|
|
/*
|
|
* Initializes the stream frame list fl.
|
|
*/
|
|
void ossl_sframe_list_init(SFRAME_LIST *fl);
|
|
|
|
/*
|
|
* Destroys the stream frame list fl releasing any data
|
|
* still present inside it.
|
|
*/
|
|
void ossl_sframe_list_destroy(SFRAME_LIST *fl);
|
|
|
|
/*
|
|
* Insert a stream frame data into the list.
|
|
* The data covers an offset range (range.start is inclusive,
|
|
* range.end is exclusive).
|
|
* fin should be set if this is the final frame of the stream.
|
|
* Returns an error if a frame cannot be inserted - due to
|
|
* STREAM_FRAME allocation error, or in case of erroneous
|
|
* fin flag (this is an ossl_assert() check so a caller must
|
|
* check it on its own too).
|
|
*/
|
|
int ossl_sframe_list_insert(SFRAME_LIST *fl, UINT_RANGE *range,
|
|
OSSL_QRX_PKT *pkt,
|
|
const unsigned char *data, int fin);
|
|
|
|
/*
|
|
* Iterator to peek at the contiguous frames at the beginning
|
|
* of the frame list fl.
|
|
* The *data covers an offset range (range.start is inclusive,
|
|
* range.end is exclusive).
|
|
* *fin is set if this is the final frame of the stream.
|
|
* Opaque iterator *iter can be used to peek at the subsequent
|
|
* frame if there is any without any gap before it.
|
|
* Returns 1 on success.
|
|
* Returns 0 if there is no further contiguous frame. In that
|
|
* case *fin is set, if the end of the stream is reached.
|
|
*/
|
|
int ossl_sframe_list_peek(const SFRAME_LIST *fl, void **iter,
|
|
UINT_RANGE *range, const unsigned char **data,
|
|
int *fin);
|
|
|
|
/*
|
|
* Drop all frames up to the offset limit.
|
|
* Also unlocks the head frame if locked.
|
|
* Returns 1 on success.
|
|
* Returns 0 when trying to drop frames at offsets that were not
|
|
* received yet. (ossl_assert() is used to check, so this is an invalid call.)
|
|
*/
|
|
int ossl_sframe_list_drop_frames(SFRAME_LIST *fl, uint64_t limit);
|
|
|
|
/*
|
|
* Locks and returns the head frame of fl if it is readable - read offset is
|
|
* at the beginning or middle of the frame.
|
|
* range is set to encompass the not yet read part of the head frame,
|
|
* data pointer is set to appropriate offset within the frame if the read
|
|
* offset points in the middle of the frame,
|
|
* fin is set to 1 if the head frame is also the tail frame.
|
|
* Returns 1 on success, 0 if there is no readable data or the head
|
|
* frame is already locked.
|
|
*/
|
|
int ossl_sframe_list_lock_head(SFRAME_LIST *fl, UINT_RANGE *range,
|
|
const unsigned char **data,
|
|
int *fin);
|
|
|
|
/*
|
|
* Just returns whether the head frame is locked by previous
|
|
* ossl_sframe_list_lock_head() call.
|
|
*/
|
|
int ossl_sframe_list_is_head_locked(SFRAME_LIST *fl);
|
|
|
|
/*
|
|
* Callback function type to write stream frame data to some
|
|
* side storage before the packet containing the frame data
|
|
* is released.
|
|
* It should return 1 on success or 0 if there is not enough
|
|
* space available in the side storage.
|
|
*/
|
|
typedef int (sframe_list_write_at_cb)(uint64_t logical_offset,
|
|
const unsigned char *buf,
|
|
size_t buf_len,
|
|
void *cb_arg);
|
|
|
|
/*
|
|
* Move the frame data in all the stream frames in the list fl
|
|
* from the packets to the side storage using the write_at_cb
|
|
* callback.
|
|
* Returns 1 if all the calls to the callback return 1.
|
|
* If the callback returns 0, the function stops processing further
|
|
* frames and returns 0.
|
|
*/
|
|
int ossl_sframe_list_move_data(SFRAME_LIST *fl,
|
|
sframe_list_write_at_cb *write_at_cb,
|
|
void *cb_arg);
|
|
# endif
|
|
|
|
#endif
|