lsquic_packet_out.c revision 50aadb33
1/* Copyright (c) 2017 LiteSpeed Technologies Inc. See LICENSE. */ 2/* 3 * lsquic_packet_out.c 4 */ 5 6#include <assert.h> 7#include <errno.h> 8#include <stdlib.h> 9#include <string.h> 10#include <sys/queue.h> 11 12#include "lsquic.h" 13#include "lsquic_int_types.h" 14#include "lsquic_malo.h" 15#include "lsquic_mm.h" 16#include "lsquic_engine_public.h" 17#include "lsquic_packet_common.h" 18#include "lsquic_packet_in.h" 19#include "lsquic_packet_out.h" 20#include "lsquic_parse.h" 21#include "lsquic_sfcw.h" 22#include "lsquic_stream.h" 23#include "lsquic_logger.h" 24 25typedef char _stream_rec_arr_is_at_most_64bytes[ 26 (sizeof(struct stream_rec_arr) <= 64) - 1]; 27 28 29struct stream_rec * 30posi_first (struct packet_out_srec_iter *posi, 31 lsquic_packet_out_t *packet_out) 32{ 33 posi->packet_out = packet_out; 34 posi->past_srec = 0; 35 return posi_next(posi); 36} 37 38 39struct stream_rec * 40posi_next (struct packet_out_srec_iter *posi) 41{ 42 if (posi->past_srec) 43 { 44 while (posi->cur_srec_arr) 45 { 46 for (; posi->srec_idx < sizeof(posi->cur_srec_arr->srecs) / sizeof(posi->cur_srec_arr->srecs[0]); 47 ++posi->srec_idx) 48 { 49 if (posi->cur_srec_arr->srecs[ posi->srec_idx ].sr_frame_types) 50 return &posi->cur_srec_arr->srecs[ posi->srec_idx++ ]; 51 } 52 posi->cur_srec_arr = STAILQ_NEXT(posi->cur_srec_arr, next_stream_rec_arr); 53 posi->srec_idx = 0; 54 } 55 return NULL; 56 } 57 else 58 { 59 ++posi->past_srec; 60 posi->cur_srec_arr = STAILQ_FIRST(&posi->packet_out->po_srec_arrs); 61 posi->srec_idx = 0; 62 if (posi->packet_out->po_srec.sr_frame_types) 63 return &posi->packet_out->po_srec; 64 return posi_next(posi); 65 } 66} 67 68 69/* Assumption: there can only be one STREAM and only one RST_STREAM frame 70 * for a particular stream per packet. The latter is true because a stream 71 * will only send out one of them. The former is true due the way packets 72 * are filled: stream will write out STREAM frame as large as it can. 73 * 74 * Assumption: frames are added to the packet_out in order of their placement 75 * in packet_out->po_data. There is an assertion in this function that guards 76 * for this. 77 */ 78int 79lsquic_packet_out_add_stream (lsquic_packet_out_t *packet_out, 80 struct lsquic_mm *mm, 81 struct lsquic_stream *new_stream, 82 enum QUIC_FRAME_TYPE frame_type, 83 unsigned short off) 84{ 85 struct packet_out_srec_iter posi; 86 struct stream_rec_arr *srec_arr; 87 struct stream_rec *srec; 88 89 for (srec = posi_first(&posi, packet_out); srec; srec = posi_next(&posi)) 90 if (srec->sr_stream == new_stream) 91 { 92 switch (frame_type) 93 { 94 case QUIC_FRAME_STREAM: 95 assert(!(srec->sr_frame_types & (1 << QUIC_FRAME_STREAM))); 96 srec->sr_frame_types |= (1 << QUIC_FRAME_STREAM); 97 srec->sr_off = off; 98 break; 99 default: 100 assert(QUIC_FRAME_RST_STREAM == frame_type); 101 assert(!(srec->sr_frame_types & (1 << QUIC_FRAME_RST_STREAM))); 102 srec->sr_frame_types |= (1 << QUIC_FRAME_RST_STREAM); 103 break; 104 } 105 return 0; /* Update existing record */ 106 } 107 else if (srec->sr_frame_types & (1 << QUIC_FRAME_STREAM) & (1 << frame_type)) 108 assert(srec->sr_off < off); /* Check that STREAM frames are added in order */ 109 110 ++new_stream->n_unacked; 111 112 if (!srec_taken(&packet_out->po_srec)) 113 { 114 packet_out->po_srec.sr_frame_types = (1 << frame_type); 115 packet_out->po_srec.sr_stream = new_stream; 116 packet_out->po_srec.sr_off = off; 117 return 0; /* Insert in first slot */ 118 } 119 120 STAILQ_FOREACH(srec_arr, &packet_out->po_srec_arrs, next_stream_rec_arr) 121 { 122 unsigned i; 123 for (i = 0; i < sizeof(srec_arr->srecs) / sizeof(srec_arr->srecs[0]); ++i) 124 if (!srec_taken(&srec_arr->srecs[i])) 125 { 126 srec_arr->srecs[i].sr_frame_types = (1 << frame_type); 127 srec_arr->srecs[i].sr_stream = new_stream; 128 srec_arr->srecs[i].sr_off = off; 129 return 0; /* Insert in existing srec */ 130 } 131 } 132 133 srec_arr = lsquic_malo_get(mm->malo.stream_rec_arr); 134 if (!srec_arr) 135 return -1; 136 137 memset(srec_arr, 0, sizeof(*srec_arr)); 138 srec_arr->srecs[0].sr_frame_types = (1 << frame_type); 139 srec_arr->srecs[0].sr_stream = new_stream; 140 srec_arr->srecs[0].sr_off = off; 141 STAILQ_INSERT_TAIL(&packet_out->po_srec_arrs, srec_arr, next_stream_rec_arr); 142 return 0; /* Insert in new srec */ 143} 144 145 146lsquic_packet_out_t * 147lsquic_packet_out_new (struct lsquic_mm *mm, struct malo *malo, int use_cid, 148 unsigned short max_size, enum lsquic_packno_bits bits, 149 const lsquic_ver_tag_t *ver_tag, const unsigned char *nonce) 150{ 151 lsquic_packet_out_t *packet_out; 152 enum packet_out_flags flags; 153 unsigned short header_size; 154 155 flags = bits << POBIT_SHIFT; 156 if (ver_tag) 157 flags |= PO_VERSION; 158 if (nonce) 159 flags |= PO_NONCE; 160 if (use_cid) 161 flags |= PO_CONN_ID; 162 163 header_size = lsquic_po_header_length(flags); 164 if (header_size + QUIC_PACKET_HASH_SZ >= max_size) 165 { 166 errno = EINVAL; 167 return NULL; 168 } 169 170 packet_out = lsquic_mm_get_packet_out(mm, malo, max_size - header_size 171 - QUIC_PACKET_HASH_SZ); 172 if (!packet_out) 173 return NULL; 174 175 packet_out->po_flags = PO_WRITEABLE | flags; 176 if (ver_tag) 177 packet_out->po_ver_tag = *ver_tag; 178 if (nonce) 179 { 180 /* Nonces are allocated for a very small number of packets. This 181 * memory is too expensive to carry in every packet. 182 */ 183 packet_out->po_nonce = malloc(32); 184 if (!packet_out->po_nonce) 185 { 186 lsquic_mm_put_packet_out(mm, packet_out); 187 return NULL; 188 } 189 memcpy(packet_out->po_nonce, nonce, 32); 190 } 191 192 return packet_out; 193} 194 195 196void 197lsquic_packet_out_destroy (lsquic_packet_out_t *packet_out, 198 struct lsquic_engine_public *enpub) 199{ 200 struct stream_rec_arr *srec_arr; 201 while ((srec_arr = STAILQ_FIRST(&packet_out->po_srec_arrs))) 202 { 203 STAILQ_REMOVE_HEAD(&packet_out->po_srec_arrs, next_stream_rec_arr); 204 lsquic_malo_put(srec_arr); 205 } 206 if (packet_out->po_flags & PO_ENCRYPTED) 207 enpub->enp_pmi->pmi_release(enpub->enp_pmi_ctx, 208 packet_out->po_enc_data); 209 if (packet_out->po_nonce) 210 free(packet_out->po_nonce); 211 lsquic_mm_put_packet_out(&enpub->enp_mm, packet_out); 212} 213 214 215/* If `stream_id' is zero, stream frames from all reset streams are elided. 216 * Otherwise, elision is limited to the specified stream. 217 */ 218void 219lsquic_packet_out_elide_reset_stream_frames (lsquic_packet_out_t *packet_out, 220 const struct parse_funcs *pf, 221 uint32_t stream_id) 222{ 223 struct packet_out_srec_iter posi; 224 struct stream_rec *srec; 225 struct stream_frame frame; 226 unsigned short adj = 0; 227 int n_stream_frames = 0, n_elided = 0; 228 int victim; 229 230 for (srec = posi_first(&posi, packet_out); srec; srec = posi_next(&posi)) 231 { 232 if (srec->sr_frame_types & (1 << QUIC_FRAME_STREAM)) 233 { 234 ++n_stream_frames; 235 236 /* Offsets of all STREAM frames should be adjusted */ 237 srec->sr_off -= adj; 238 239 if (stream_id) 240 { 241 victim = srec->sr_stream->id == stream_id; 242 if (victim) 243 { 244 assert(lsquic_stream_is_reset(srec->sr_stream)); 245 } 246 } 247 else 248 victim = lsquic_stream_is_reset(srec->sr_stream); 249 250 if (victim) 251 { 252 ++n_elided; 253 254 const int len = 255 pf->pf_parse_stream_frame(packet_out->po_data + srec->sr_off, 256 packet_out->po_data_sz - srec->sr_off, &frame); 257 if (len < 0) 258 { /* This is pretty severe: we should be able to parse our own 259 * frames. Should this abort the connection? 260 */ 261 LSQ_ERROR("can't parse our own stream frame"); 262 return; 263 } 264 assert(frame.stream_id == srec->sr_stream->id); 265 266 /* Move the data and adjust sizes */ 267 adj += len; 268 memmove(packet_out->po_data + srec->sr_off, 269 packet_out->po_data + srec->sr_off + len, 270 packet_out->po_data_sz - srec->sr_off - len); 271 packet_out->po_data_sz -= len; 272 273 /* See what we can do with the stream */ 274 srec->sr_frame_types &= ~(1 << QUIC_FRAME_STREAM); 275 if (!srec_taken(srec)) 276 lsquic_stream_acked(srec->sr_stream); 277 } 278 } 279 } 280 281 assert(n_stream_frames); 282 if (n_elided == n_stream_frames) 283 packet_out->po_frame_types &= ~(1 << QUIC_FRAME_STREAM); 284} 285 286 287void 288lsquic_packet_out_chop_regen (lsquic_packet_out_t *packet_out) 289{ 290 struct packet_out_srec_iter posi; 291 struct stream_rec *srec; 292 unsigned delta; 293 294 delta = packet_out->po_regen_sz; 295 packet_out->po_data_sz -= delta; 296 memmove(packet_out->po_data, packet_out->po_data + delta, 297 packet_out->po_data_sz); 298 packet_out->po_regen_sz = 0; 299 300 for (srec = posi_first(&posi, packet_out); srec; srec = posi_next(&posi)) 301 if (srec->sr_frame_types & (1 << QUIC_FRAME_STREAM)) 302 srec->sr_off -= delta; 303} 304