/src/openssl32/ssl/quic/quic_rstream.c
Line | Count | Source (jump to first uncovered line) |
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 | | #include <openssl/err.h> |
10 | | #include "internal/common.h" |
11 | | #include "internal/time.h" |
12 | | #include "internal/quic_stream.h" |
13 | | #include "internal/quic_sf_list.h" |
14 | | #include "internal/ring_buf.h" |
15 | | |
16 | | struct quic_rstream_st { |
17 | | SFRAME_LIST fl; |
18 | | QUIC_RXFC *rxfc; |
19 | | OSSL_STATM *statm; |
20 | | UINT_RANGE head_range; |
21 | | struct ring_buf rbuf; |
22 | | }; |
23 | | |
24 | | QUIC_RSTREAM *ossl_quic_rstream_new(QUIC_RXFC *rxfc, |
25 | | OSSL_STATM *statm, size_t rbuf_size) |
26 | 127k | { |
27 | 127k | QUIC_RSTREAM *ret = OPENSSL_zalloc(sizeof(*ret)); |
28 | | |
29 | 127k | if (ret == NULL) |
30 | 0 | return NULL; |
31 | | |
32 | 127k | ring_buf_init(&ret->rbuf); |
33 | 127k | if (!ring_buf_resize(&ret->rbuf, rbuf_size, 0)) { |
34 | 0 | OPENSSL_free(ret); |
35 | 0 | return NULL; |
36 | 0 | } |
37 | | |
38 | 127k | ossl_sframe_list_init(&ret->fl); |
39 | 127k | ret->rxfc = rxfc; |
40 | 127k | ret->statm = statm; |
41 | 127k | return ret; |
42 | 127k | } |
43 | | |
44 | | void ossl_quic_rstream_free(QUIC_RSTREAM *qrs) |
45 | 141k | { |
46 | 141k | int cleanse; |
47 | | |
48 | 141k | if (qrs == NULL) |
49 | 13.6k | return; |
50 | | |
51 | 127k | cleanse = qrs->fl.cleanse; |
52 | 127k | ossl_sframe_list_destroy(&qrs->fl); |
53 | 127k | ring_buf_destroy(&qrs->rbuf, cleanse); |
54 | 127k | OPENSSL_free(qrs); |
55 | 127k | } |
56 | | |
57 | | int ossl_quic_rstream_queue_data(QUIC_RSTREAM *qrs, OSSL_QRX_PKT *pkt, |
58 | | uint64_t offset, |
59 | | const unsigned char *data, uint64_t data_len, |
60 | | int fin) |
61 | 116k | { |
62 | 116k | UINT_RANGE range; |
63 | | |
64 | 116k | if ((data == NULL && data_len != 0) || (data_len == 0 && fin == 0)) { |
65 | | /* empty frame allowed only at the end of the stream */ |
66 | 0 | ERR_raise(ERR_LIB_SSL, ERR_R_INTERNAL_ERROR); |
67 | 0 | return 0; |
68 | 0 | } |
69 | | |
70 | 116k | range.start = offset; |
71 | 116k | range.end = offset + data_len; |
72 | | |
73 | 116k | return ossl_sframe_list_insert(&qrs->fl, &range, pkt, data, fin); |
74 | 116k | } |
75 | | |
76 | | static int read_internal(QUIC_RSTREAM *qrs, unsigned char *buf, size_t size, |
77 | | size_t *readbytes, int *fin, int drop) |
78 | 11.5M | { |
79 | 11.5M | void *iter = NULL; |
80 | 11.5M | UINT_RANGE range; |
81 | 11.5M | const unsigned char *data; |
82 | 11.5M | uint64_t offset = 0; |
83 | 11.5M | size_t readbytes_ = 0; |
84 | 11.5M | int fin_ = 0, ret = 1; |
85 | | |
86 | 11.6M | while (ossl_sframe_list_peek(&qrs->fl, &iter, &range, &data, &fin_)) { |
87 | 2.06k | size_t l = (size_t)(range.end - range.start); |
88 | | |
89 | 2.06k | if (l > size) { |
90 | 469 | l = size; |
91 | 469 | fin_ = 0; |
92 | 469 | } |
93 | 2.06k | offset = range.start + l; |
94 | 2.06k | if (l == 0) |
95 | 0 | break; |
96 | | |
97 | 2.06k | if (data == NULL) { |
98 | 0 | size_t max_len; |
99 | |
|
100 | 0 | data = ring_buf_get_ptr(&qrs->rbuf, range.start, &max_len); |
101 | 0 | if (!ossl_assert(data != NULL)) |
102 | 0 | return 0; |
103 | 0 | if (max_len < l) { |
104 | 0 | memcpy(buf, data, max_len); |
105 | 0 | size -= max_len; |
106 | 0 | buf += max_len; |
107 | 0 | readbytes_ += max_len; |
108 | 0 | l -= max_len; |
109 | 0 | data = ring_buf_get_ptr(&qrs->rbuf, range.start + max_len, |
110 | 0 | &max_len); |
111 | 0 | if (!ossl_assert(data != NULL) || !ossl_assert(max_len > l)) |
112 | 0 | return 0; |
113 | 0 | } |
114 | 0 | } |
115 | | |
116 | 2.06k | memcpy(buf, data, l); |
117 | 2.06k | size -= l; |
118 | 2.06k | buf += l; |
119 | 2.06k | readbytes_ += l; |
120 | 2.06k | if (size == 0) |
121 | 469 | break; |
122 | 2.06k | } |
123 | | |
124 | 11.5M | if (drop && offset != 0) { |
125 | 2.00k | ret = ossl_sframe_list_drop_frames(&qrs->fl, offset); |
126 | 2.00k | ring_buf_cpop_range(&qrs->rbuf, 0, offset - 1, qrs->fl.cleanse); |
127 | 2.00k | } |
128 | | |
129 | 11.5M | if (ret) { |
130 | 11.5M | *readbytes = readbytes_; |
131 | 11.5M | *fin = fin_; |
132 | 11.5M | } |
133 | | |
134 | 11.5M | return ret; |
135 | 11.5M | } |
136 | | |
137 | | static OSSL_TIME get_rtt(QUIC_RSTREAM *qrs) |
138 | 11.5M | { |
139 | 11.5M | OSSL_TIME rtt; |
140 | | |
141 | 11.5M | if (qrs->statm != NULL) { |
142 | 0 | OSSL_RTT_INFO rtt_info; |
143 | |
|
144 | 0 | ossl_statm_get_rtt_info(qrs->statm, &rtt_info); |
145 | 0 | rtt = rtt_info.smoothed_rtt; |
146 | 11.5M | } else { |
147 | 11.5M | rtt = ossl_time_zero(); |
148 | 11.5M | } |
149 | 11.5M | return rtt; |
150 | 11.5M | } |
151 | | |
152 | | int ossl_quic_rstream_read(QUIC_RSTREAM *qrs, unsigned char *buf, size_t size, |
153 | | size_t *readbytes, int *fin) |
154 | 11.5M | { |
155 | 11.5M | OSSL_TIME rtt = get_rtt(qrs); |
156 | | |
157 | 11.5M | if (!read_internal(qrs, buf, size, readbytes, fin, 1)) |
158 | 0 | return 0; |
159 | | |
160 | 11.5M | if (qrs->rxfc != NULL |
161 | 11.5M | && !ossl_quic_rxfc_on_retire(qrs->rxfc, *readbytes, rtt)) |
162 | 0 | return 0; |
163 | | |
164 | 11.5M | return 1; |
165 | 11.5M | } |
166 | | |
167 | | int ossl_quic_rstream_peek(QUIC_RSTREAM *qrs, unsigned char *buf, size_t size, |
168 | | size_t *readbytes, int *fin) |
169 | 0 | { |
170 | 0 | return read_internal(qrs, buf, size, readbytes, fin, 0); |
171 | 0 | } |
172 | | |
173 | | int ossl_quic_rstream_available(QUIC_RSTREAM *qrs, size_t *avail, int *fin) |
174 | 4.06M | { |
175 | 4.06M | void *iter = NULL; |
176 | 4.06M | UINT_RANGE range; |
177 | 4.06M | const unsigned char *data; |
178 | 4.06M | uint64_t avail_ = 0; |
179 | | |
180 | 4.06M | while (ossl_sframe_list_peek(&qrs->fl, &iter, &range, &data, fin)) |
181 | 1.90k | avail_ += range.end - range.start; |
182 | | |
183 | | #if SIZE_MAX < UINT64_MAX |
184 | | *avail = avail_ > SIZE_MAX ? SIZE_MAX : (size_t)avail_; |
185 | | #else |
186 | 4.06M | *avail = (size_t)avail_; |
187 | 4.06M | #endif |
188 | 4.06M | return 1; |
189 | 4.06M | } |
190 | | |
191 | | int ossl_quic_rstream_get_record(QUIC_RSTREAM *qrs, |
192 | | const unsigned char **record, size_t *rec_len, |
193 | | int *fin) |
194 | 29.1M | { |
195 | 29.1M | const unsigned char *record_ = NULL; |
196 | 29.1M | size_t rec_len_, max_len; |
197 | | |
198 | 29.1M | if (!ossl_sframe_list_lock_head(&qrs->fl, &qrs->head_range, &record_, fin)) { |
199 | | /* No head frame to lock and return */ |
200 | 29.1M | *record = NULL; |
201 | 29.1M | *rec_len = 0; |
202 | 29.1M | return 1; |
203 | 29.1M | } |
204 | | |
205 | | /* if final empty frame, we drop it immediately */ |
206 | 30.4k | if (qrs->head_range.end == qrs->head_range.start) { |
207 | 0 | if (!ossl_assert(*fin)) |
208 | 0 | return 0; |
209 | 0 | if (!ossl_sframe_list_drop_frames(&qrs->fl, qrs->head_range.end)) |
210 | 0 | return 0; |
211 | 0 | } |
212 | | |
213 | 30.4k | rec_len_ = (size_t)(qrs->head_range.end - qrs->head_range.start); |
214 | | |
215 | 30.4k | if (record_ == NULL && rec_len_ != 0) { |
216 | 0 | record_ = ring_buf_get_ptr(&qrs->rbuf, qrs->head_range.start, |
217 | 0 | &max_len); |
218 | 0 | if (!ossl_assert(record_ != NULL)) |
219 | 0 | return 0; |
220 | 0 | if (max_len < rec_len_) { |
221 | 0 | rec_len_ = max_len; |
222 | 0 | qrs->head_range.end = qrs->head_range.start + max_len; |
223 | 0 | } |
224 | 0 | } |
225 | | |
226 | 30.4k | *rec_len = rec_len_; |
227 | 30.4k | *record = record_; |
228 | 30.4k | return 1; |
229 | 30.4k | } |
230 | | |
231 | | |
232 | | int ossl_quic_rstream_release_record(QUIC_RSTREAM *qrs, size_t read_len) |
233 | 30.4k | { |
234 | 30.4k | uint64_t offset; |
235 | | |
236 | 30.4k | if (!ossl_sframe_list_is_head_locked(&qrs->fl)) |
237 | 0 | return 0; |
238 | | |
239 | 30.4k | if (read_len > qrs->head_range.end - qrs->head_range.start) { |
240 | 0 | if (read_len != SIZE_MAX) |
241 | 0 | return 0; |
242 | 0 | offset = qrs->head_range.end; |
243 | 30.4k | } else { |
244 | 30.4k | offset = qrs->head_range.start + read_len; |
245 | 30.4k | } |
246 | | |
247 | 30.4k | if (!ossl_sframe_list_drop_frames(&qrs->fl, offset)) |
248 | 0 | return 0; |
249 | | |
250 | 30.4k | if (offset > 0) |
251 | 30.4k | ring_buf_cpop_range(&qrs->rbuf, 0, offset - 1, qrs->fl.cleanse); |
252 | | |
253 | 30.4k | if (qrs->rxfc != NULL) { |
254 | 0 | OSSL_TIME rtt = get_rtt(qrs); |
255 | |
|
256 | 0 | if (!ossl_quic_rxfc_on_retire(qrs->rxfc, offset, rtt)) |
257 | 0 | return 0; |
258 | 0 | } |
259 | | |
260 | 30.4k | return 1; |
261 | 30.4k | } |
262 | | |
263 | | static int write_at_ring_buf_cb(uint64_t logical_offset, |
264 | | const unsigned char *buf, |
265 | | size_t buf_len, |
266 | | void *cb_arg) |
267 | 0 | { |
268 | 0 | struct ring_buf *rbuf = cb_arg; |
269 | |
|
270 | 0 | return ring_buf_write_at(rbuf, logical_offset, buf, buf_len); |
271 | 0 | } |
272 | | |
273 | | int ossl_quic_rstream_move_to_rbuf(QUIC_RSTREAM *qrs) |
274 | 0 | { |
275 | 0 | if (ring_buf_avail(&qrs->rbuf) == 0) |
276 | 0 | return 0; |
277 | 0 | return ossl_sframe_list_move_data(&qrs->fl, |
278 | 0 | write_at_ring_buf_cb, &qrs->rbuf); |
279 | 0 | } |
280 | | |
281 | | int ossl_quic_rstream_resize_rbuf(QUIC_RSTREAM *qrs, size_t rbuf_size) |
282 | 0 | { |
283 | 0 | if (ossl_sframe_list_is_head_locked(&qrs->fl)) |
284 | 0 | return 0; |
285 | | |
286 | 0 | if (!ring_buf_resize(&qrs->rbuf, rbuf_size, qrs->fl.cleanse)) |
287 | 0 | return 0; |
288 | | |
289 | 0 | return 1; |
290 | 0 | } |
291 | | |
292 | | void ossl_quic_rstream_set_cleanse(QUIC_RSTREAM *qrs, int cleanse) |
293 | 5.54k | { |
294 | 5.54k | qrs->fl.cleanse = cleanse; |
295 | 5.54k | } |