Home | History | Annotate | Line # | Download | only in internal
      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