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