lsquic_parse_Q046.c revision 4429f8ea
1/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE. */ 2/* 3 * lsquic_parse_Q046.c -- Parsing functions specific to GQUIC Q046 4 */ 5 6#include <assert.h> 7#include <errno.h> 8#include <inttypes.h> 9#include <string.h> 10#include <sys/queue.h> 11#ifndef WIN32 12#include <sys/types.h> 13#else 14#include <vc_compat.h> 15#endif 16 17#include "lsquic_types.h" 18#include "lsquic_int_types.h" 19#include "lsquic_packet_common.h" 20#include "lsquic_packet_in.h" 21#include "lsquic_packet_out.h" 22#include "lsquic_parse.h" 23#include "lsquic_parse_common.h" 24#include "lsquic_version.h" 25#include "lsquic.h" 26#include "lsquic_parse_gquic_be.h" 27#include "lsquic_byteswap.h" 28#include "lsquic_hash.h" 29#include "lsquic_conn.h" 30 31#define LSQUIC_LOGGER_MODULE LSQLM_PARSE 32#include "lsquic_logger.h" 33 34 35static unsigned 36gquic_Q046_packno_bits2len (enum packno_bits bits) 37{ 38 return bits + 1; 39} 40 41#define iquic_packno_bits2len gquic_Q046_packno_bits2len 42 43 44static enum packno_bits 45gquic_Q046_calc_packno_bits (lsquic_packno_t packno, 46 lsquic_packno_t least_unacked, uint64_t n_in_flight) 47{ 48 uint64_t delta; 49 unsigned bits; 50 51 delta = packno - least_unacked; 52 if (n_in_flight > delta) 53 delta = n_in_flight; 54 55 delta *= 4; 56 bits = (delta >= (1ULL << 8)) 57 + (delta >= (1ULL << 16)) 58 + (delta >= (1ULL << 24)) 59 ; 60 61 return bits; 62} 63 64 65static unsigned 66write_packno (unsigned char *p, lsquic_packno_t packno, enum packno_bits bits) 67{ 68 unsigned char *const begin = p; 69 70 switch (bits) 71 { 72 case IQUIC_PACKNO_LEN_4: 73 *p++ = packno >> 24; 74 /* fall-through */ 75 case IQUIC_PACKNO_LEN_3: 76 *p++ = packno >> 16; 77 /* fall-through */ 78 case IQUIC_PACKNO_LEN_2: 79 *p++ = packno >> 8; 80 /* fall-through */ 81 default: 82 *p++ = packno; 83 } 84 85 return p - begin; 86} 87 88 89static int 90gen_short_pkt_header (const struct lsquic_conn *lconn, 91 const struct lsquic_packet_out *packet_out, unsigned char *buf, 92 size_t bufsz) 93{ 94 unsigned packno_len, need; 95 enum packno_bits bits; 96 97 bits = lsquic_packet_out_packno_bits(packet_out); 98 packno_len = iquic_packno_bits2len(bits); 99 100 if (lconn->cn_flags & LSCONN_SERVER) 101 need = 1 + packno_len; 102 else 103 need = 1 + 8 /* CID */ + packno_len; 104 105 if (need > bufsz) 106 return -1; 107 108 *buf++ = 0x40 | bits; 109 110 if (0 == (lconn->cn_flags & LSCONN_SERVER)) 111 { 112 memcpy(buf, lconn->cn_cid.idbuf, 8); 113 buf += 8; 114 } 115 116 (void) write_packno(buf, packet_out->po_packno, bits); 117 118 return need; 119} 120 121 122static size_t 123gquic_Q046_packout_header_size_long (const struct lsquic_conn *lconn, 124 enum packet_out_flags flags) 125{ 126 if ((lconn->cn_flags & LSCONN_SERVER) && (flags & PO_NONCE)) 127 return GQUIC_IETF_LONG_HEADER_SIZE + 32; 128 return GQUIC_IETF_LONG_HEADER_SIZE; 129} 130 131 132/* [draft-ietf-quic-transport-17] Section-17.2 */ 133static const unsigned char header_type_to_bin[] = { 134 [HETY_INITIAL] = 0x0, 135 [HETY_0RTT] = 0x1, 136 [HETY_HANDSHAKE] = 0x2, 137 [HETY_RETRY] = 0x3, 138}; 139 140 141static int 142gen_long_pkt_header (const struct lsquic_conn *lconn, 143 const struct lsquic_packet_out *packet_out, unsigned char *buf, 144 size_t bufsz) 145{ 146 enum packno_bits packno_bits; 147 lsquic_ver_tag_t ver_tag; 148 unsigned char *p; 149 size_t need; 150 151 need = gquic_Q046_packout_header_size_long(lconn, packet_out->po_flags); 152 if (need > bufsz) 153 { 154 errno = EINVAL; 155 return -1; 156 } 157 158 p = buf; 159 packno_bits = IQUIC_PACKNO_LEN_4; 160 *p++ = 0x80 | 0x40 161 | (header_type_to_bin[ packet_out->po_header_type ] << 4) 162 | packno_bits; 163 ver_tag = lsquic_ver2tag(lconn->cn_version); 164 memcpy(p, &ver_tag, sizeof(ver_tag)); 165 p += sizeof(ver_tag); 166 167 if (lconn->cn_flags & LSCONN_SERVER) 168 *p++ = 0x05; 169 else 170 *p++ = 0x50; 171 172 memcpy(p, lconn->cn_cid.idbuf, 8); 173 p += 8; 174 175 p += write_packno(p, packet_out->po_packno, packno_bits); 176 177 if (packet_out->po_nonce) 178 { 179 memcpy(p, packet_out->po_nonce, 32); 180 p += 32; 181 } 182 183 assert(need == (unsigned int)(p - buf)); 184 return p - buf; 185} 186 187 188static int 189gquic_Q046_gen_reg_pkt_header (const struct lsquic_conn *lconn, 190 const struct lsquic_packet_out *packet_out, unsigned char *buf, 191 size_t bufsz, unsigned *packno_off_UNUSED, unsigned *packno_len_UNUSED) 192{ 193 if (0 == (packet_out->po_flags & PO_LONGHEAD)) 194 return gen_short_pkt_header(lconn, packet_out, buf, bufsz); 195 else 196 return gen_long_pkt_header(lconn, packet_out, buf, bufsz); 197} 198 199 200static size_t 201gquic_Q046_packout_header_size_short (const struct lsquic_conn *lconn, 202 enum packet_out_flags flags) 203{ 204 enum packno_bits bits; 205 size_t sz; 206 207 bits = (flags >> POBIT_SHIFT) & 0x3; 208 sz = 1; /* Type */ 209 sz += (lconn->cn_flags & LSCONN_SERVER) ? 0 : 8; 210 sz += iquic_packno_bits2len(bits); 211 212 return sz; 213} 214 215 216static size_t 217gquic_Q046_packout_header_size (const struct lsquic_conn *lconn, 218 enum packet_out_flags flags, size_t dcid_len_unused, 219 enum header_type unused) 220{ 221 if (0 == (flags & PO_LONGHEAD)) 222 return gquic_Q046_packout_header_size_short(lconn, flags); 223 else 224 return gquic_Q046_packout_header_size_long(lconn, flags); 225} 226 227 228static size_t 229gquic_Q046_packout_size (const struct lsquic_conn *lconn, 230 const struct lsquic_packet_out *packet_out) 231{ 232 size_t sz; 233 234 if (0 == (packet_out->po_flags & PO_LONGHEAD)) 235 sz = gquic_Q046_packout_header_size_short(lconn, packet_out->po_flags); 236 else 237 sz = gquic_Q046_packout_header_size_long(lconn, packet_out->po_flags); 238 239 sz += packet_out->po_data_sz; 240 sz += GQUIC_PACKET_HASH_SZ; 241 242 return sz; 243} 244 245 246static void 247gquic_Q046_parse_packet_in_finish (struct lsquic_packet_in *packet_in, 248 struct packin_parse_state *state) 249{ 250 lsquic_packno_t packno; 251 252 if (packet_in->pi_header_type == HETY_NOT_SET 253 /* We can't check in the beginning because we don't know whether 254 * this is Q046 or ID-18. This is a bit hacky. 255 */ 256 && state->pps_p + state->pps_nbytes 257 <= packet_in->pi_data + packet_in->pi_data_sz) 258 { 259 READ_UINT(packno, 64, state->pps_p, state->pps_nbytes); 260 packet_in->pi_packno = packno; 261 packet_in->pi_header_sz += state->pps_nbytes; 262 } 263} 264 265 266static int 267gquic_Q046_gen_crypto_frame (unsigned char *buf, size_t buf_len, 268 lsquic_stream_id_t stream_id, uint64_t offset, int fin, size_t size, 269 gsf_read_f gsf_read, void *stream) 270{ 271 assert(0); 272 return -1; 273} 274 275 276static int 277gquic_Q046_parse_crypto_frame (const unsigned char *buf, size_t rem_packet_sz, 278 struct stream_frame *stream_frame) 279{ 280 assert(0); 281 return -1; 282} 283 284 285/* No simple PRST for Q046 */ 286static ssize_t 287gquic_Q046_generate_simple_prst (const lsquic_cid_t *cidp, unsigned char *buf, 288 size_t buf_sz) 289{ 290 return -1; 291} 292 293 294static unsigned 295gquic_Q046_handshake_done_frame_size (void) 296{ 297 return 0; 298} 299 300 301static int 302gquic_Q046_gen_handshake_done_frame (unsigned char *buf, size_t buf_len) 303{ 304 return -1; 305} 306 307 308static int 309gquic_Q046_parse_handshake_done_frame (const unsigned char *buf, size_t buf_len) 310{ 311 return -1; 312} 313 314 315const struct parse_funcs lsquic_parse_funcs_gquic_Q046 = 316{ 317 .pf_gen_reg_pkt_header = gquic_Q046_gen_reg_pkt_header, 318 .pf_parse_packet_in_finish = gquic_Q046_parse_packet_in_finish, 319 .pf_gen_stream_frame = lsquic_gquic_be_gen_stream_frame, 320 .pf_calc_stream_frame_header_sz = lsquic_calc_stream_frame_header_sz_gquic, 321 .pf_parse_stream_frame = lsquic_gquic_be_parse_stream_frame, 322 .pf_dec_stream_frame_size = lsquic_gquic_be_dec_stream_frame_size, 323 .pf_parse_ack_frame = lsquic_gquic_be_parse_ack_frame, 324 .pf_gen_ack_frame = lsquic_gquic_be_gen_ack_frame, 325 .pf_gen_stop_waiting_frame = lsquic_gquic_be_gen_stop_waiting_frame, 326 .pf_parse_stop_waiting_frame = lsquic_gquic_be_parse_stop_waiting_frame, 327 .pf_skip_stop_waiting_frame = lsquic_gquic_be_skip_stop_waiting_frame, 328 .pf_gen_window_update_frame = lsquic_gquic_be_gen_window_update_frame, 329 .pf_parse_window_update_frame = lsquic_gquic_be_parse_window_update_frame, 330 .pf_gen_blocked_frame = lsquic_gquic_be_gen_blocked_frame, 331 .pf_parse_blocked_frame = lsquic_gquic_be_parse_blocked_frame, 332 .pf_gen_rst_frame = lsquic_gquic_be_gen_rst_frame, 333 .pf_parse_rst_frame = lsquic_gquic_be_parse_rst_frame, 334 .pf_connect_close_frame_size = lsquic_gquic_be_connect_close_frame_size, 335 .pf_gen_connect_close_frame = lsquic_gquic_be_gen_connect_close_frame, 336 .pf_parse_connect_close_frame = lsquic_gquic_be_parse_connect_close_frame, 337 .pf_gen_goaway_frame = lsquic_gquic_be_gen_goaway_frame, 338 .pf_parse_goaway_frame = lsquic_gquic_be_parse_goaway_frame, 339 .pf_gen_ping_frame = lsquic_gquic_be_gen_ping_frame, 340#ifndef NDEBUG 341 .pf_write_float_time16 = lsquic_gquic_be_write_float_time16, 342 .pf_read_float_time16 = lsquic_gquic_be_read_float_time16, 343#endif 344 .pf_generate_simple_prst = gquic_Q046_generate_simple_prst, 345 .pf_parse_frame_type = lsquic_parse_frame_type_gquic_Q035_thru_Q046, 346 .pf_turn_on_fin = lsquic_turn_on_fin_Q035_thru_Q046, 347 .pf_packout_size = gquic_Q046_packout_size, 348 .pf_packout_max_header_size = gquic_Q046_packout_header_size, 349 .pf_calc_packno_bits = gquic_Q046_calc_packno_bits, 350 .pf_packno_bits2len = gquic_Q046_packno_bits2len, 351 .pf_gen_crypto_frame = gquic_Q046_gen_crypto_frame, 352 .pf_parse_crypto_frame = gquic_Q046_parse_crypto_frame, 353 .pf_gen_handshake_done_frame = gquic_Q046_gen_handshake_done_frame, 354 .pf_parse_handshake_done_frame = gquic_Q046_parse_handshake_done_frame, 355 .pf_handshake_done_frame_size = gquic_Q046_handshake_done_frame_size, 356}; 357