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