1 /* 2 * Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved. 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 */ 9 10 #ifndef OSSL_QUIC_SF_LIST_H 11 # define OSSL_QUIC_SF_LIST_H 12 13 #include "internal/common.h" 14 #include "internal/uint_set.h" 15 #include "internal/quic_record_rx.h" 16 17 /* 18 * Stream frame list 19 * ================= 20 * 21 * This data structure supports similar operations as uint64 set but 22 * it has slightly different invariants and also carries data associated with 23 * the ranges in the list. 24 * 25 * Operations: 26 * Insert frame (optimized insertion at the beginning and at the end). 27 * Iterated peek into the frame(s) from the beginning. 28 * Dropping frames from the beginning up to an offset (exclusive). 29 * 30 * Invariant: The frames in the list are sorted by the start and end bounds. 31 * Invariant: There are no fully overlapping frames or frames that would 32 * be fully encompassed by another frame in the list. 33 * Invariant: No frame has start > end. 34 * Invariant: The range start is inclusive the end is exclusive to be 35 * able to mark an empty frame. 36 * Invariant: The offset never points further than into the first frame. 37 */ 38 # ifndef OPENSSL_NO_QUIC 39 40 typedef struct stream_frame_st STREAM_FRAME; 41 42 typedef struct sframe_list_st { 43 STREAM_FRAME *head, *tail; 44 /* Is the tail frame final. */ 45 unsigned int fin; 46 /* Number of stream frames in the list. */ 47 size_t num_frames; 48 /* Offset of data not yet dropped */ 49 uint64_t offset; 50 /* Is head locked ? */ 51 int head_locked; 52 /* Cleanse data on release? */ 53 int cleanse; 54 } SFRAME_LIST; 55 56 /* 57 * Initializes the stream frame list fl. 58 */ 59 void ossl_sframe_list_init(SFRAME_LIST *fl); 60 61 /* 62 * Destroys the stream frame list fl releasing any data 63 * still present inside it. 64 */ 65 void ossl_sframe_list_destroy(SFRAME_LIST *fl); 66 67 /* 68 * Insert a stream frame data into the list. 69 * The data covers an offset range (range.start is inclusive, 70 * range.end is exclusive). 71 * fin should be set if this is the final frame of the stream. 72 * Returns an error if a frame cannot be inserted - due to 73 * STREAM_FRAME allocation error, or in case of erroneous 74 * fin flag (this is an ossl_assert() check so a caller must 75 * check it on its own too). 76 */ 77 int ossl_sframe_list_insert(SFRAME_LIST *fl, UINT_RANGE *range, 78 OSSL_QRX_PKT *pkt, 79 const unsigned char *data, int fin); 80 81 /* 82 * Iterator to peek at the contiguous frames at the beginning 83 * of the frame list fl. 84 * The *data covers an offset range (range.start is inclusive, 85 * range.end is exclusive). 86 * *fin is set if this is the final frame of the stream. 87 * Opaque iterator *iter can be used to peek at the subsequent 88 * frame if there is any without any gap before it. 89 * Returns 1 on success. 90 * Returns 0 if there is no further contiguous frame. In that 91 * case *fin is set, if the end of the stream is reached. 92 */ 93 int ossl_sframe_list_peek(const SFRAME_LIST *fl, void **iter, 94 UINT_RANGE *range, const unsigned char **data, 95 int *fin); 96 97 /* 98 * Drop all frames up to the offset limit. 99 * Also unlocks the head frame if locked. 100 * Returns 1 on success. 101 * Returns 0 when trying to drop frames at offsets that were not 102 * received yet. (ossl_assert() is used to check, so this is an invalid call.) 103 */ 104 int ossl_sframe_list_drop_frames(SFRAME_LIST *fl, uint64_t limit); 105 106 /* 107 * Locks and returns the head frame of fl if it is readable - read offset is 108 * at the beginning or middle of the frame. 109 * range is set to encompass the not yet read part of the head frame, 110 * data pointer is set to appropriate offset within the frame if the read 111 * offset points in the middle of the frame, 112 * fin is set to 1 if the head frame is also the tail frame. 113 * Returns 1 on success, 0 if there is no readable data or the head 114 * frame is already locked. 115 */ 116 int ossl_sframe_list_lock_head(SFRAME_LIST *fl, UINT_RANGE *range, 117 const unsigned char **data, 118 int *fin); 119 120 /* 121 * Just returns whether the head frame is locked by previous 122 * ossl_sframe_list_lock_head() call. 123 */ 124 int ossl_sframe_list_is_head_locked(SFRAME_LIST *fl); 125 126 /* 127 * Callback function type to write stream frame data to some 128 * side storage before the packet containing the frame data 129 * is released. 130 * It should return 1 on success or 0 if there is not enough 131 * space available in the side storage. 132 */ 133 typedef int (sframe_list_write_at_cb)(uint64_t logical_offset, 134 const unsigned char *buf, 135 size_t buf_len, 136 void *cb_arg); 137 138 /* 139 * Move the frame data in all the stream frames in the list fl 140 * from the packets to the side storage using the write_at_cb 141 * callback. 142 * Returns 1 if all the calls to the callback return 1. 143 * If the callback returns 0, the function stops processing further 144 * frames and returns 0. 145 */ 146 int ossl_sframe_list_move_data(SFRAME_LIST *fl, 147 sframe_list_write_at_cb *write_at_cb, 148 void *cb_arg); 149 # endif 150 151 #endif 152