lsquic_packet_resize.c revision a74702c6
1a74702c6SGeorge Wang/* Copyright (c) 2017 - 2022 LiteSpeed Technologies Inc. See LICENSE. */ 2b8fa6195SDmitri Tikhonov/* Functions to resize packets */ 3b8fa6195SDmitri Tikhonov 4b8fa6195SDmitri Tikhonov#include <assert.h> 5b8fa6195SDmitri Tikhonov#include <inttypes.h> 6b8fa6195SDmitri Tikhonov#include <stdint.h> 7b8fa6195SDmitri Tikhonov#include <string.h> 8b8fa6195SDmitri Tikhonov#include <sys/queue.h> 9b8fa6195SDmitri Tikhonov 10b8fa6195SDmitri Tikhonov#include "lsquic.h" 11b8fa6195SDmitri Tikhonov#include "lsquic_int_types.h" 12b8fa6195SDmitri Tikhonov#include "lsquic_packet_common.h" 13b8fa6195SDmitri Tikhonov#include "lsquic_packet_in.h" 14b8fa6195SDmitri Tikhonov#include "lsquic_packet_out.h" 15b8fa6195SDmitri Tikhonov#include "lsquic_packet_resize.h" 16b8fa6195SDmitri Tikhonov#include "lsquic_parse.h" 17b8fa6195SDmitri Tikhonov#include "lsquic_hash.h" 18b8fa6195SDmitri Tikhonov#include "lsquic_varint.h" 19b8fa6195SDmitri Tikhonov#include "lsquic_hq.h" 20b8fa6195SDmitri Tikhonov#include "lsquic_sfcw.h" 21b8fa6195SDmitri Tikhonov#include "lsquic_stream.h" 22b8fa6195SDmitri Tikhonov#include "lsquic_mm.h" 23b8fa6195SDmitri Tikhonov#include "lsquic_engine_public.h" 24b8fa6195SDmitri Tikhonov#include "lsquic_conn.h" 25b8fa6195SDmitri Tikhonov 26b8fa6195SDmitri Tikhonov#define LSQUIC_LOGGER_MODULE LSQLM_PACKET_RESIZE 27b8fa6195SDmitri Tikhonov#define LSQUIC_LOG_CONN_ID lsquic_conn_log_cid(prctx->prc_conn) 28b8fa6195SDmitri Tikhonov#include "lsquic_logger.h" 29b8fa6195SDmitri Tikhonov 30b8fa6195SDmitri Tikhonov 31b8fa6195SDmitri Tikhonovvoid 32b8fa6195SDmitri Tikhonovlsquic_packet_resize_init (struct packet_resize_ctx *prctx, 33b8fa6195SDmitri Tikhonov struct lsquic_engine_public *enpub, struct lsquic_conn *lconn, void *ctx, 34b8fa6195SDmitri Tikhonov const struct packet_resize_if *pr_if) 35b8fa6195SDmitri Tikhonov{ 36b8fa6195SDmitri Tikhonov memset(prctx, 0, sizeof(*prctx)); 37b8fa6195SDmitri Tikhonov prctx->prc_conn = lconn; 38b8fa6195SDmitri Tikhonov prctx->prc_pri = pr_if; 39b8fa6195SDmitri Tikhonov prctx->prc_enpub = enpub; 40b8fa6195SDmitri Tikhonov prctx->prc_data = ctx; 41b8fa6195SDmitri Tikhonov LSQ_DEBUG("initialized"); 42b8fa6195SDmitri Tikhonov} 43b8fa6195SDmitri Tikhonov 44b8fa6195SDmitri Tikhonov 45b8fa6195SDmitri Tikhonovstatic const struct frame_rec * 46b8fa6195SDmitri Tikhonovpacket_resize_next_frec (struct packet_resize_ctx *prctx) 47b8fa6195SDmitri Tikhonov{ 48b8fa6195SDmitri Tikhonov const struct frame_rec *frec; 49b8fa6195SDmitri Tikhonov 50b8fa6195SDmitri Tikhonov assert(!prctx->prc_cur_frec); 51b8fa6195SDmitri Tikhonov if (prctx->prc_cur_packet) 52b8fa6195SDmitri Tikhonov { 53b8fa6195SDmitri Tikhonov LSQ_DEBUG("get next frec from current packet %"PRIu64, 54b8fa6195SDmitri Tikhonov prctx->prc_cur_packet->po_packno); 55b8fa6195SDmitri Tikhonov frec = lsquic_pofi_next(&prctx->prc_pofi); 56b8fa6195SDmitri Tikhonov if (frec) 57b8fa6195SDmitri Tikhonov return frec; 58b8fa6195SDmitri Tikhonov LSQ_DEBUG("discard packet %"PRIu64, prctx->prc_cur_packet->po_packno); 59b8fa6195SDmitri Tikhonov prctx->prc_pri->pri_discard_packet(prctx->prc_data, 60b8fa6195SDmitri Tikhonov prctx->prc_cur_packet); 61b8fa6195SDmitri Tikhonov prctx->prc_cur_packet = NULL; /* Not necessary; just future-proofing */ 62b8fa6195SDmitri Tikhonov } 63b8fa6195SDmitri Tikhonov 64b8fa6195SDmitri Tikhonov prctx->prc_cur_packet = prctx->prc_pri->pri_next_packet(prctx->prc_data); 65b8fa6195SDmitri Tikhonov if (!prctx->prc_cur_packet) 66b8fa6195SDmitri Tikhonov { 67b8fa6195SDmitri Tikhonov LSQ_DEBUG("out of input packets"); 68b8fa6195SDmitri Tikhonov return NULL; 69b8fa6195SDmitri Tikhonov } 70b8fa6195SDmitri Tikhonov frec = lsquic_pofi_first(&prctx->prc_pofi, prctx->prc_cur_packet); 71b8fa6195SDmitri Tikhonov assert(frec); 72b8fa6195SDmitri Tikhonov LSQ_DEBUG("return first frec from new current packet %"PRIu64, 73b8fa6195SDmitri Tikhonov prctx->prc_cur_packet->po_packno); 74b8fa6195SDmitri Tikhonov return frec; 75b8fa6195SDmitri Tikhonov} 76b8fa6195SDmitri Tikhonov 77b8fa6195SDmitri Tikhonov 78b8fa6195SDmitri Tikhonovstatic const struct frame_rec * 79b8fa6195SDmitri Tikhonovpacket_resize_get_frec (struct packet_resize_ctx *prctx) 80b8fa6195SDmitri Tikhonov{ 81b8fa6195SDmitri Tikhonov if (!prctx->prc_cur_frec) 82b8fa6195SDmitri Tikhonov { 83b8fa6195SDmitri Tikhonov prctx->prc_cur_frec = packet_resize_next_frec(prctx); 84b8fa6195SDmitri Tikhonov if (prctx->prc_cur_frec) 85b8fa6195SDmitri Tikhonov prctx->prc_flags |= PRC_NEW_FREC; 86b8fa6195SDmitri Tikhonov } 87b8fa6195SDmitri Tikhonov return prctx->prc_cur_frec; 88b8fa6195SDmitri Tikhonov} 89b8fa6195SDmitri Tikhonov 90b8fa6195SDmitri Tikhonov 91b8fa6195SDmitri Tikhonovstatic size_t 92b8fa6195SDmitri Tikhonovpacket_resize_gsf_read (void *ctx, void *buf, size_t len, int *fin) 93b8fa6195SDmitri Tikhonov{ 94b8fa6195SDmitri Tikhonov struct packet_resize_ctx *const prctx = ctx; 95b8fa6195SDmitri Tikhonov size_t left; 96b8fa6195SDmitri Tikhonov 97b8fa6195SDmitri Tikhonov left = (size_t) prctx->prc_data_frame.df_size 98b8fa6195SDmitri Tikhonov - (size_t) prctx->prc_data_frame.df_read_off; 99b8fa6195SDmitri Tikhonov if (len > left) 100b8fa6195SDmitri Tikhonov len = left; 101b8fa6195SDmitri Tikhonov memcpy(buf, 102b8fa6195SDmitri Tikhonov prctx->prc_data_frame.df_data + prctx->prc_data_frame.df_read_off, len); 103b8fa6195SDmitri Tikhonov prctx->prc_data_frame.df_read_off += len; 104b8fa6195SDmitri Tikhonov *fin = prctx->prc_data_frame.df_fin 105b8fa6195SDmitri Tikhonov && prctx->prc_data_frame.df_size == prctx->prc_data_frame.df_read_off; 106b8fa6195SDmitri Tikhonov 107b8fa6195SDmitri Tikhonov return len; 108b8fa6195SDmitri Tikhonov} 109b8fa6195SDmitri Tikhonov 110b8fa6195SDmitri Tikhonov 111b8fa6195SDmitri Tikhonovstruct lsquic_packet_out * 112b8fa6195SDmitri Tikhonovlsquic_packet_resize_next (struct packet_resize_ctx *prctx) 113b8fa6195SDmitri Tikhonov{ 114b8fa6195SDmitri Tikhonov const unsigned char *data_in; 115b8fa6195SDmitri Tikhonov struct lsquic_packet_out *new; 116b8fa6195SDmitri Tikhonov struct stream_frame stream_frame; 117b8fa6195SDmitri Tikhonov const struct frame_rec *frec; 118b8fa6195SDmitri Tikhonov int s, w, fin, parsed_len; 119b8fa6195SDmitri Tikhonov size_t nbytes; 120b8fa6195SDmitri Tikhonov 121b8fa6195SDmitri Tikhonov if (frec = packet_resize_get_frec(prctx), frec == NULL) 122b8fa6195SDmitri Tikhonov return NULL; 123b8fa6195SDmitri Tikhonov 124b8fa6195SDmitri Tikhonov new = prctx->prc_pri->pri_new_packet(prctx->prc_data); 125b8fa6195SDmitri Tikhonov if (!new) 126b8fa6195SDmitri Tikhonov { 127b8fa6195SDmitri Tikhonov LSQ_DEBUG("cannot allocate new packet"); 128b8fa6195SDmitri Tikhonov goto err; 129b8fa6195SDmitri Tikhonov } 130b8fa6195SDmitri Tikhonov 131b8fa6195SDmitri Tikhonov proc_frec: 132b8fa6195SDmitri Tikhonov if ((1 << frec->fe_frame_type) & (QUIC_FTBIT_STREAM|QUIC_FTBIT_CRYPTO)) 133b8fa6195SDmitri Tikhonov { 134b8fa6195SDmitri Tikhonov if (prctx->prc_flags & PRC_NEW_FREC) 135b8fa6195SDmitri Tikhonov { 136b8fa6195SDmitri Tikhonov data_in = prctx->prc_cur_packet->po_data + frec->fe_off; 137b8fa6195SDmitri Tikhonov parsed_len = (&prctx->prc_conn->cn_pf->pf_parse_stream_frame) 138b8fa6195SDmitri Tikhonov [frec->fe_frame_type == QUIC_FRAME_CRYPTO] 139b8fa6195SDmitri Tikhonov (data_in, frec->fe_len, &stream_frame); 140b8fa6195SDmitri Tikhonov if (parsed_len < 0) 141b8fa6195SDmitri Tikhonov { 142b8fa6195SDmitri Tikhonov LSQ_WARN("cannot parse %s frame", 143b8fa6195SDmitri Tikhonov frame_type_2_str[frec->fe_frame_type]); 144b8fa6195SDmitri Tikhonov goto err; 145b8fa6195SDmitri Tikhonov } 146b8fa6195SDmitri Tikhonov if ((unsigned) parsed_len != frec->fe_len) 147b8fa6195SDmitri Tikhonov { 148b8fa6195SDmitri Tikhonov LSQ_WARN("parsed %s frame size does not match frame record", 149b8fa6195SDmitri Tikhonov frame_type_2_str[frec->fe_frame_type]); 150b8fa6195SDmitri Tikhonov goto err; 151b8fa6195SDmitri Tikhonov } 152b8fa6195SDmitri Tikhonov prctx->prc_data_frame = stream_frame.data_frame; 153b8fa6195SDmitri Tikhonov prctx->prc_flags &= ~PRC_NEW_FREC; 154b8fa6195SDmitri Tikhonov LSQ_DEBUG("parsed %s frame record for stream %"PRIu64 155b8fa6195SDmitri Tikhonov "; off: %"PRIu64"; size: %"PRIu16"; fin: %d", 156b8fa6195SDmitri Tikhonov frame_type_2_str[frec->fe_frame_type], 157b8fa6195SDmitri Tikhonov frec->fe_stream->id, 158b8fa6195SDmitri Tikhonov stream_frame.data_frame.df_offset, 159b8fa6195SDmitri Tikhonov stream_frame.data_frame.df_size, 160b8fa6195SDmitri Tikhonov stream_frame.data_frame.df_fin); 161b8fa6195SDmitri Tikhonov } 162b8fa6195SDmitri Tikhonov fin = prctx->prc_data_frame.df_fin 163b8fa6195SDmitri Tikhonov && prctx->prc_data_frame.df_read_off == prctx->prc_data_frame.df_size; 164b8fa6195SDmitri Tikhonov nbytes = prctx->prc_data_frame.df_size - prctx->prc_data_frame.df_read_off; 165b8fa6195SDmitri Tikhonov w = (&prctx->prc_conn->cn_pf->pf_gen_stream_frame) 166b8fa6195SDmitri Tikhonov [frec->fe_frame_type == QUIC_FRAME_CRYPTO]( 167b8fa6195SDmitri Tikhonov new->po_data + new->po_data_sz, lsquic_packet_out_avail(new), 168b8fa6195SDmitri Tikhonov frec->fe_stream->id, 169b8fa6195SDmitri Tikhonov prctx->prc_data_frame.df_offset + prctx->prc_data_frame.df_read_off, 170b8fa6195SDmitri Tikhonov fin, nbytes, packet_resize_gsf_read, prctx); 171b8fa6195SDmitri Tikhonov if (w < 0) 172b8fa6195SDmitri Tikhonov { 173b8fa6195SDmitri Tikhonov /* We rely on stream-generating function returning an error instead 174b8fa6195SDmitri Tikhonov * of pre-calculating required size and checking. 175b8fa6195SDmitri Tikhonov */ 176b8fa6195SDmitri Tikhonov LSQ_DEBUG("cannot fit another %s frame, new packet done", 177b8fa6195SDmitri Tikhonov frame_type_2_str[frec->fe_frame_type]); 178b8fa6195SDmitri Tikhonov goto done; 179b8fa6195SDmitri Tikhonov } 180b8fa6195SDmitri Tikhonov if (0 != lsquic_packet_out_add_stream(new, &prctx->prc_enpub->enp_mm, 181b8fa6195SDmitri Tikhonov frec->fe_stream, frec->fe_frame_type, 182b8fa6195SDmitri Tikhonov new->po_data_sz, w)) 183b8fa6195SDmitri Tikhonov { 184b8fa6195SDmitri Tikhonov LSQ_WARN("cannot add stream frame record to new packet"); 185b8fa6195SDmitri Tikhonov goto err; 186b8fa6195SDmitri Tikhonov } 187b8fa6195SDmitri Tikhonov new->po_data_sz += w; 188b8fa6195SDmitri Tikhonov new->po_frame_types |= 1 << frec->fe_frame_type; 189b8fa6195SDmitri Tikhonov if (0 == lsquic_packet_out_avail(new)) 190b8fa6195SDmitri Tikhonov new->po_flags |= PO_STREAM_END; 191b8fa6195SDmitri Tikhonov if (prctx->prc_data_frame.df_size == prctx->prc_data_frame.df_read_off) 192b8fa6195SDmitri Tikhonov { 193b8fa6195SDmitri Tikhonov LSQ_DEBUG("finished using %s frame record", 194b8fa6195SDmitri Tikhonov frame_type_2_str[frec->fe_frame_type]); 195b8fa6195SDmitri Tikhonov --frec->fe_stream->n_unacked; 196b8fa6195SDmitri Tikhonov frec = prctx->prc_cur_frec = NULL; 197b8fa6195SDmitri Tikhonov if (lsquic_packet_out_avail(new) > 0) 198b8fa6195SDmitri Tikhonov if (frec = packet_resize_get_frec(prctx), frec != NULL) 199b8fa6195SDmitri Tikhonov goto proc_frec; 200b8fa6195SDmitri Tikhonov } 201b8fa6195SDmitri Tikhonov } 202b8fa6195SDmitri Tikhonov else if (prctx->prc_cur_frec->fe_len <= lsquic_packet_out_avail(new)) 203b8fa6195SDmitri Tikhonov { 20449f1f4f6SDmitri Tikhonov if ((1 << frec->fe_frame_type) & BQUIC_FRAME_REGEN_MASK) 205b8fa6195SDmitri Tikhonov { 206b8fa6195SDmitri Tikhonov if (new->po_regen_sz == new->po_data_sz) 207b8fa6195SDmitri Tikhonov new->po_regen_sz += frec->fe_len; 208b8fa6195SDmitri Tikhonov else 209b8fa6195SDmitri Tikhonov { 210b8fa6195SDmitri Tikhonov LSQ_DEBUG("got non-contiguous regen frame %s, packet done", 211b8fa6195SDmitri Tikhonov frame_type_2_str[frec->fe_frame_type]); 212b8fa6195SDmitri Tikhonov goto done; 213b8fa6195SDmitri Tikhonov } 214b8fa6195SDmitri Tikhonov } 215b8fa6195SDmitri Tikhonov memcpy(new->po_data + new->po_data_sz, 216b8fa6195SDmitri Tikhonov prctx->prc_cur_packet->po_data + frec->fe_off, frec->fe_len); 217b8fa6195SDmitri Tikhonov if (frec->fe_frame_type == QUIC_FRAME_RST_STREAM) 218b8fa6195SDmitri Tikhonov s = lsquic_packet_out_add_stream(new, &prctx->prc_enpub->enp_mm, 219b8fa6195SDmitri Tikhonov frec->fe_stream, frec->fe_frame_type, 220b8fa6195SDmitri Tikhonov new->po_data_sz, frec->fe_len); 221b8fa6195SDmitri Tikhonov else 222b8fa6195SDmitri Tikhonov s = lsquic_packet_out_add_frame(new, &prctx->prc_enpub->enp_mm, 223b8fa6195SDmitri Tikhonov frec->fe_u.data, frec->fe_frame_type, 224b8fa6195SDmitri Tikhonov new->po_data_sz, frec->fe_len); 225b8fa6195SDmitri Tikhonov if (s != 0) 226b8fa6195SDmitri Tikhonov { 227b8fa6195SDmitri Tikhonov LSQ_WARN("cannot add %s frame record to new packet", 228b8fa6195SDmitri Tikhonov frame_type_2_str[frec->fe_frame_type]); 229b8fa6195SDmitri Tikhonov goto err; 230b8fa6195SDmitri Tikhonov } 231b8fa6195SDmitri Tikhonov new->po_data_sz += frec->fe_len; 232b8fa6195SDmitri Tikhonov new->po_frame_types |= 1 << frec->fe_frame_type; 233b8fa6195SDmitri Tikhonov LSQ_DEBUG("copy %hu-byte %s frame into new packet", frec->fe_len, 234b8fa6195SDmitri Tikhonov frame_type_2_str[frec->fe_frame_type]); 235b8fa6195SDmitri Tikhonov if (frec->fe_frame_type == QUIC_FRAME_RST_STREAM) 236b8fa6195SDmitri Tikhonov --frec->fe_stream->n_unacked; 237b8fa6195SDmitri Tikhonov frec = prctx->prc_cur_frec = NULL; 238b8fa6195SDmitri Tikhonov if (lsquic_packet_out_avail(new) > 0) 239b8fa6195SDmitri Tikhonov if (frec = packet_resize_get_frec(prctx), frec != NULL) 240b8fa6195SDmitri Tikhonov goto proc_frec; 241b8fa6195SDmitri Tikhonov } 242b8fa6195SDmitri Tikhonov 243b8fa6195SDmitri Tikhonov done: 244b8fa6195SDmitri Tikhonov if (0 == new->po_data_sz) 245b8fa6195SDmitri Tikhonov { 246b8fa6195SDmitri Tikhonov LSQ_WARN("frame too large"); 247b8fa6195SDmitri Tikhonov goto err; 248b8fa6195SDmitri Tikhonov } 249b8fa6195SDmitri Tikhonov 250b8fa6195SDmitri Tikhonov return new; 251b8fa6195SDmitri Tikhonov 252b8fa6195SDmitri Tikhonov err: 253b8fa6195SDmitri Tikhonov if (new) 254b8fa6195SDmitri Tikhonov lsquic_packet_out_destroy(new, prctx->prc_enpub, 255b8fa6195SDmitri Tikhonov new->po_path->np_peer_ctx); 256b8fa6195SDmitri Tikhonov prctx->prc_flags |= PRC_ERROR; 257b8fa6195SDmitri Tikhonov return NULL; 258b8fa6195SDmitri Tikhonov} 259