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