Path: blob/main/crypto/openssl/ssl/quic/quic_txpim.c
48266 views
/*1* Copyright 2022-2023 The OpenSSL Project Authors. All Rights Reserved.2*3* Licensed under the Apache License 2.0 (the "License"). You may not use4* this file except in compliance with the License. You can obtain a copy5* in the file LICENSE in the source distribution or at6* https://www.openssl.org/source/license.html7*/89#include "internal/quic_txpim.h"10#include <stdlib.h>1112typedef struct quic_txpim_pkt_ex_st QUIC_TXPIM_PKT_EX;1314struct quic_txpim_pkt_ex_st {15QUIC_TXPIM_PKT public;16QUIC_TXPIM_PKT_EX *prev, *next;17QUIC_TXPIM_CHUNK *chunks;18size_t num_chunks, alloc_chunks;19unsigned int chunks_need_sort : 1;20};2122typedef struct quic_txpim_pkt_ex_list {23QUIC_TXPIM_PKT_EX *head, *tail;24} QUIC_TXPIM_PKT_EX_LIST;2526struct quic_txpim_st {27QUIC_TXPIM_PKT_EX_LIST free_list;28size_t in_use;29};3031#define MAX_ALLOC_CHUNKS 5123233QUIC_TXPIM *ossl_quic_txpim_new(void)34{35QUIC_TXPIM *txpim = OPENSSL_zalloc(sizeof(*txpim));3637if (txpim == NULL)38return NULL;3940return txpim;41}4243static void free_list(QUIC_TXPIM_PKT_EX_LIST *l)44{45QUIC_TXPIM_PKT_EX *n, *nnext;4647for (n = l->head; n != NULL; n = nnext) {48nnext = n->next;4950OPENSSL_free(n->chunks);51OPENSSL_free(n);52}5354l->head = l->tail = NULL;55}5657void ossl_quic_txpim_free(QUIC_TXPIM *txpim)58{59if (txpim == NULL)60return;6162assert(txpim->in_use == 0);63free_list(&txpim->free_list);64OPENSSL_free(txpim);65}6667static void list_remove(QUIC_TXPIM_PKT_EX_LIST *l, QUIC_TXPIM_PKT_EX *n)68{69if (l->head == n)70l->head = n->next;71if (l->tail == n)72l->tail = n->prev;73if (n->prev != NULL)74n->prev->next = n->next;75if (n->next != NULL)76n->next->prev = n->prev;77n->prev = n->next = NULL;78}7980static void list_insert_tail(QUIC_TXPIM_PKT_EX_LIST *l, QUIC_TXPIM_PKT_EX *n)81{82n->prev = l->tail;83n->next = NULL;84l->tail = n;85if (n->prev != NULL)86n->prev->next = n;87if (l->head == NULL)88l->head = n;89}9091static QUIC_TXPIM_PKT_EX *txpim_get_free(QUIC_TXPIM *txpim)92{93QUIC_TXPIM_PKT_EX *ex = txpim->free_list.head;9495if (ex != NULL)96return ex;9798ex = OPENSSL_zalloc(sizeof(*ex));99if (ex == NULL)100return NULL;101102list_insert_tail(&txpim->free_list, ex);103return ex;104}105106static void txpim_clear(QUIC_TXPIM_PKT_EX *ex)107{108memset(&ex->public.ackm_pkt, 0, sizeof(ex->public.ackm_pkt));109ossl_quic_txpim_pkt_clear_chunks(&ex->public);110ex->public.retx_head = NULL;111ex->public.fifd = NULL;112ex->public.had_handshake_done_frame = 0;113ex->public.had_max_data_frame = 0;114ex->public.had_max_streams_bidi_frame = 0;115ex->public.had_max_streams_uni_frame = 0;116ex->public.had_ack_frame = 0;117ex->public.had_conn_close = 0;118}119120QUIC_TXPIM_PKT *ossl_quic_txpim_pkt_alloc(QUIC_TXPIM *txpim)121{122QUIC_TXPIM_PKT_EX *ex = txpim_get_free(txpim);123124if (ex == NULL)125return NULL;126127txpim_clear(ex);128list_remove(&txpim->free_list, ex);129++txpim->in_use;130return &ex->public;131}132133void ossl_quic_txpim_pkt_release(QUIC_TXPIM *txpim, QUIC_TXPIM_PKT *fpkt)134{135QUIC_TXPIM_PKT_EX *ex = (QUIC_TXPIM_PKT_EX *)fpkt;136137assert(txpim->in_use > 0);138--txpim->in_use;139list_insert_tail(&txpim->free_list, ex);140}141142void ossl_quic_txpim_pkt_add_cfq_item(QUIC_TXPIM_PKT *fpkt,143QUIC_CFQ_ITEM *item)144{145item->pkt_next = fpkt->retx_head;146item->pkt_prev = NULL;147fpkt->retx_head = item;148}149150void ossl_quic_txpim_pkt_clear_chunks(QUIC_TXPIM_PKT *fpkt)151{152QUIC_TXPIM_PKT_EX *ex = (QUIC_TXPIM_PKT_EX *)fpkt;153154ex->num_chunks = 0;155}156157int ossl_quic_txpim_pkt_append_chunk(QUIC_TXPIM_PKT *fpkt,158const QUIC_TXPIM_CHUNK *chunk)159{160QUIC_TXPIM_PKT_EX *ex = (QUIC_TXPIM_PKT_EX *)fpkt;161QUIC_TXPIM_CHUNK *new_chunk;162size_t new_alloc_chunks = ex->alloc_chunks;163164if (ex->num_chunks == ex->alloc_chunks) {165new_alloc_chunks = (ex->alloc_chunks == 0) ? 4 : ex->alloc_chunks * 8 / 5;166if (new_alloc_chunks > MAX_ALLOC_CHUNKS)167new_alloc_chunks = MAX_ALLOC_CHUNKS;168if (ex->num_chunks == new_alloc_chunks)169return 0;170171new_chunk = OPENSSL_realloc(ex->chunks,172new_alloc_chunks * sizeof(QUIC_TXPIM_CHUNK));173if (new_chunk == NULL)174return 0;175176ex->chunks = new_chunk;177ex->alloc_chunks = new_alloc_chunks;178}179180ex->chunks[ex->num_chunks++] = *chunk;181ex->chunks_need_sort = 1;182return 1;183}184185static int compare(const void *a, const void *b)186{187const QUIC_TXPIM_CHUNK *ac = a, *bc = b;188189if (ac->stream_id < bc->stream_id)190return -1;191else if (ac->stream_id > bc->stream_id)192return 1;193194if (ac->start < bc->start)195return -1;196else if (ac->start > bc->start)197return 1;198199return 0;200}201202const QUIC_TXPIM_CHUNK *ossl_quic_txpim_pkt_get_chunks(const QUIC_TXPIM_PKT *fpkt)203{204QUIC_TXPIM_PKT_EX *ex = (QUIC_TXPIM_PKT_EX *)fpkt;205206if (ex->chunks_need_sort) {207/*208* List of chunks will generally be very small so there is no issue209* simply sorting here.210*/211qsort(ex->chunks, ex->num_chunks, sizeof(QUIC_TXPIM_CHUNK), compare);212ex->chunks_need_sort = 0;213}214215return ex->chunks;216}217218size_t ossl_quic_txpim_pkt_get_num_chunks(const QUIC_TXPIM_PKT *fpkt)219{220QUIC_TXPIM_PKT_EX *ex = (QUIC_TXPIM_PKT_EX *)fpkt;221222return ex->num_chunks;223}224225size_t ossl_quic_txpim_get_in_use(const QUIC_TXPIM *txpim)226{227return txpim->in_use;228}229230231