]>
git.ipfire.org Git - thirdparty/openssl.git/blob - ssl/quic/quic_rstream.c
2 * Copyright 2022 The OpenSSL Project Authors. All Rights Reserved.
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
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"
16 struct quic_rstream_st
{
20 UINT_RANGE head_range
;
24 QUIC_RSTREAM
*ossl_quic_rstream_new(QUIC_RXFC
*rxfc
,
25 OSSL_STATM
*statm
, size_t rbuf_size
)
27 QUIC_RSTREAM
*ret
= OPENSSL_zalloc(sizeof(*ret
));
32 ring_buf_init(&ret
->rbuf
);
33 if (!ring_buf_resize(&ret
->rbuf
, rbuf_size
)) {
38 ossl_sframe_list_init(&ret
->fl
);
44 void ossl_quic_rstream_free(QUIC_RSTREAM
*qrs
)
49 ossl_sframe_list_destroy(&qrs
->fl
);
50 ring_buf_destroy(&qrs
->rbuf
);
54 int ossl_quic_rstream_queue_data(QUIC_RSTREAM
*qrs
, OSSL_QRX_PKT
*pkt
,
56 const unsigned char *data
, uint64_t data_len
,
61 if ((data
== NULL
&& data_len
!= 0) || (data_len
== 0 && fin
== 0)) {
62 /* empty frame allowed only at the end of the stream */
63 ERR_raise(ERR_LIB_SSL
, ERR_R_INTERNAL_ERROR
);
68 range
.end
= offset
+ data_len
;
70 return ossl_sframe_list_insert(&qrs
->fl
, &range
, pkt
, data
, fin
);
73 static int read_internal(QUIC_RSTREAM
*qrs
, unsigned char *buf
, size_t size
,
74 size_t *readbytes
, int *fin
, int drop
)
78 const unsigned char *data
;
80 size_t readbytes_
= 0;
81 int fin_
= 0, ret
= 1;
83 while (ossl_sframe_list_peek(&qrs
->fl
, &iter
, &range
, &data
, &fin_
)) {
84 size_t l
= (size_t)(range
.end
- range
.start
);
90 offset
= range
.start
+ l
;
97 data
= ring_buf_get_ptr(&qrs
->rbuf
, range
.start
, &max_len
);
98 if (!ossl_assert(data
!= NULL
))
101 memcpy(buf
, data
, max_len
);
104 readbytes_
+= max_len
;
106 data
= ring_buf_get_ptr(&qrs
->rbuf
, range
.start
+ max_len
,
108 if (!ossl_assert(data
!= NULL
) || !ossl_assert(max_len
> l
))
113 memcpy(buf
, data
, l
);
121 if (drop
&& offset
!= 0) {
122 ret
= ossl_sframe_list_drop_frames(&qrs
->fl
, offset
);
123 ring_buf_cpop_range(&qrs
->rbuf
, 0, offset
- 1, qrs
->fl
.cleanse
);
127 *readbytes
= readbytes_
;
134 static OSSL_TIME
get_rtt(QUIC_RSTREAM
*qrs
)
138 if (qrs
->statm
!= NULL
) {
139 OSSL_RTT_INFO rtt_info
;
141 ossl_statm_get_rtt_info(qrs
->statm
, &rtt_info
);
142 rtt
= rtt_info
.smoothed_rtt
;
144 rtt
= ossl_time_zero();
149 int ossl_quic_rstream_read(QUIC_RSTREAM
*qrs
, unsigned char *buf
, size_t size
,
150 size_t *readbytes
, int *fin
)
152 OSSL_TIME rtt
= get_rtt(qrs
);
154 if (!read_internal(qrs
, buf
, size
, readbytes
, fin
, 1))
157 if (qrs
->rxfc
!= NULL
158 && !ossl_quic_rxfc_on_retire(qrs
->rxfc
, *readbytes
, rtt
))
164 int ossl_quic_rstream_peek(QUIC_RSTREAM
*qrs
, unsigned char *buf
, size_t size
,
165 size_t *readbytes
, int *fin
)
167 return read_internal(qrs
, buf
, size
, readbytes
, fin
, 0);
170 int ossl_quic_rstream_available(QUIC_RSTREAM
*qrs
, size_t *avail
, int *fin
)
174 const unsigned char *data
;
177 while (ossl_sframe_list_peek(&qrs
->fl
, &iter
, &range
, &data
, fin
))
178 avail_
+= range
.end
- range
.start
;
180 #if SIZE_MAX < UINT64_MAX
181 *avail
= avail_
> SIZE_MAX
? SIZE_MAX
: (size_t)avail_
;
183 *avail
= (size_t)avail_
;
188 int ossl_quic_rstream_get_record(QUIC_RSTREAM
*qrs
,
189 const unsigned char **record
, size_t *rec_len
,
192 const unsigned char *record_
= NULL
;
193 size_t rec_len_
, max_len
;
195 if (!ossl_sframe_list_lock_head(&qrs
->fl
, &qrs
->head_range
, &record_
, fin
)) {
196 /* No head frame to lock and return */
202 /* if final empty frame, we drop it immediately */
203 if (qrs
->head_range
.end
== qrs
->head_range
.start
) {
204 if (!ossl_assert(*fin
))
206 if (!ossl_sframe_list_drop_frames(&qrs
->fl
, qrs
->head_range
.end
))
210 rec_len_
= (size_t)(qrs
->head_range
.end
- qrs
->head_range
.start
);
212 if (record_
== NULL
&& rec_len_
!= 0) {
213 record_
= ring_buf_get_ptr(&qrs
->rbuf
, qrs
->head_range
.start
,
215 if (!ossl_assert(record_
!= NULL
))
217 if (max_len
< rec_len_
) {
219 qrs
->head_range
.end
= qrs
->head_range
.start
+ max_len
;
229 int ossl_quic_rstream_release_record(QUIC_RSTREAM
*qrs
, size_t read_len
)
233 if (!ossl_sframe_list_is_head_locked(&qrs
->fl
))
236 if (read_len
> qrs
->head_range
.end
- qrs
->head_range
.start
) {
237 if (read_len
!= SIZE_MAX
)
239 offset
= qrs
->head_range
.end
;
241 offset
= qrs
->head_range
.start
+ read_len
;
244 if (!ossl_sframe_list_drop_frames(&qrs
->fl
, offset
))
248 ring_buf_cpop_range(&qrs
->rbuf
, 0, offset
- 1, qrs
->fl
.cleanse
);
250 if (qrs
->rxfc
!= NULL
) {
251 OSSL_TIME rtt
= get_rtt(qrs
);
253 if (!ossl_quic_rxfc_on_retire(qrs
->rxfc
, offset
, rtt
))
260 static int write_at_ring_buf_cb(uint64_t logical_offset
,
261 const unsigned char *buf
,
265 struct ring_buf
*rbuf
= cb_arg
;
267 return ring_buf_write_at(rbuf
, logical_offset
, buf
, buf_len
);
270 int ossl_quic_rstream_move_to_rbuf(QUIC_RSTREAM
*qrs
)
272 if (ring_buf_avail(&qrs
->rbuf
) == 0)
274 return ossl_sframe_list_move_data(&qrs
->fl
,
275 write_at_ring_buf_cb
, &qrs
->rbuf
);
278 int ossl_quic_rstream_resize_rbuf(QUIC_RSTREAM
*qrs
, size_t rbuf_size
)
280 /* TODO(QUIC): Do we need to distinguish different error conditions ? */
281 if (ossl_sframe_list_is_head_locked(&qrs
->fl
))
284 if (!ring_buf_resize(&qrs
->rbuf
, rbuf_size
))
290 void ossl_quic_rstream_set_cleanse(QUIC_RSTREAM
*qrs
, int cleanse
)
292 qrs
->fl
.cleanse
= cleanse
;