Home | History | Annotate | Line # | Download | only in quic
      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 int ossl_quic_rstream_release_record(QUIC_RSTREAM *qrs, size_t read_len)
    232 {
    233     uint64_t offset;
    234 
    235     if (!ossl_sframe_list_is_head_locked(&qrs->fl))
    236         return 0;
    237 
    238     if (read_len > qrs->head_range.end - qrs->head_range.start) {
    239         if (read_len != SIZE_MAX)
    240             return 0;
    241         offset = qrs->head_range.end;
    242     } else {
    243         offset = qrs->head_range.start + read_len;
    244     }
    245 
    246     if (!ossl_sframe_list_drop_frames(&qrs->fl, offset))
    247         return 0;
    248 
    249     if (offset > 0)
    250         ring_buf_cpop_range(&qrs->rbuf, 0, offset - 1, qrs->fl.cleanse);
    251 
    252     if (qrs->rxfc != NULL) {
    253         OSSL_TIME rtt = get_rtt(qrs);
    254 
    255         if (!ossl_quic_rxfc_on_retire(qrs->rxfc, offset, rtt))
    256             return 0;
    257     }
    258 
    259     return 1;
    260 }
    261 
    262 static int write_at_ring_buf_cb(uint64_t logical_offset,
    263     const unsigned char *buf,
    264     size_t buf_len,
    265     void *cb_arg)
    266 {
    267     struct ring_buf *rbuf = cb_arg;
    268 
    269     return ring_buf_write_at(rbuf, logical_offset, buf, buf_len);
    270 }
    271 
    272 int ossl_quic_rstream_move_to_rbuf(QUIC_RSTREAM *qrs)
    273 {
    274     if (ring_buf_avail(&qrs->rbuf) == 0)
    275         return 0;
    276     return ossl_sframe_list_move_data(&qrs->fl,
    277         write_at_ring_buf_cb, &qrs->rbuf);
    278 }
    279 
    280 int ossl_quic_rstream_resize_rbuf(QUIC_RSTREAM *qrs, size_t rbuf_size)
    281 {
    282     if (ossl_sframe_list_is_head_locked(&qrs->fl))
    283         return 0;
    284 
    285     if (!ring_buf_resize(&qrs->rbuf, rbuf_size, qrs->fl.cleanse))
    286         return 0;
    287 
    288     return 1;
    289 }
    290 
    291 void ossl_quic_rstream_set_cleanse(QUIC_RSTREAM *qrs, int cleanse)
    292 {
    293     qrs->fl.cleanse = cleanse;
    294 }
    295