xref: /freebsd/crypto/openssl/include/internal/quic_sf_list.h (revision e7be843b4a162e68651d3911f0357ed464915629)
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