lsquic_parse_Q046.c revision c7d81ce1
1/* Copyright (c) 2017 - 2019 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_packet_common.h" 19#include "lsquic_packet_in.h" 20#include "lsquic_packet_out.h" 21#include "lsquic_parse.h" 22#include "lsquic_parse_common.h" 23#include "lsquic_version.h" 24#include "lsquic.h" 25#include "lsquic_parse_gquic_be.h" 26#include "lsquic_byteswap.h" 27#include "lsquic_conn.h" 28 29#define LSQUIC_LOGGER_MODULE LSQLM_PARSE 30#include "lsquic_logger.h" 31 32 33 34 35static unsigned 36gquic_Q046_packno_bits2len (enum packno_bits bits) 37{ 38 return bits + 1; 39} 40 41 42#define iquic_packno_bits2len gquic_Q046_packno_bits2len 43 44 45static enum packno_bits 46gquic_Q046_calc_packno_bits (lsquic_packno_t packno, 47 lsquic_packno_t least_unacked, uint64_t n_in_flight) 48{ 49 uint64_t delta; 50 unsigned bits; 51 52 delta = packno - least_unacked; 53 if (n_in_flight > delta) 54 delta = n_in_flight; 55 56 delta *= 4; 57 bits = (delta >= (1ULL << 8)) 58 + (delta >= (1ULL << 16)) 59 + (delta >= (1ULL << 24)) 60 ; 61 62 return bits; 63} 64 65 66static unsigned 67write_packno (unsigned char *p, lsquic_packno_t packno, enum packno_bits bits) 68{ 69 unsigned char *const begin = p; 70 71 switch (bits) 72 { 73 case IQUIC_PACKNO_LEN_4: 74 *p++ = packno >> 24; 75 case IQUIC_PACKNO_LEN_3: 76 *p++ = packno >> 16; 77 case IQUIC_PACKNO_LEN_2: 78 *p++ = packno >> 8; 79 default: 80 *p++ = packno; 81 } 82 83 return p - begin; 84} 85 86 87static int 88gen_short_pkt_header (const struct lsquic_conn *lconn, 89 const struct lsquic_packet_out *packet_out, unsigned char *buf, 90 size_t bufsz) 91{ 92 unsigned packno_len, need; 93 enum packno_bits bits; 94 95 bits = lsquic_packet_out_packno_bits(packet_out); 96 packno_len = iquic_packno_bits2len(bits); 97 98 need = 1 + 8 /* CID */ + packno_len; 99 100 if (need > bufsz) 101 return -1; 102 103 *buf++ = 0x40 | bits; 104 105 memcpy(buf, &lconn->cn_cid, 8); 106 buf += 8; 107 108 (void) write_packno(buf, packet_out->po_packno, bits); 109 110 return need; 111} 112 113 114static size_t 115gquic_Q046_packout_header_size_long (const struct lsquic_conn *lconn, 116 enum packet_out_flags flags) 117{ 118 return GQUIC_IETF_LONG_HEADER_SIZE; 119} 120 121 122/* [draft-ietf-quic-transport-17] Section-17.2 */ 123static const unsigned char header_type_to_bin[] = { 124 [HETY_INITIAL] = 0x0, 125 [HETY_0RTT] = 0x1, 126 [HETY_HANDSHAKE] = 0x2, 127 [HETY_RETRY] = 0x3, 128}; 129 130 131static int 132gen_long_pkt_header (const struct lsquic_conn *lconn, 133 const struct lsquic_packet_out *packet_out, unsigned char *buf, 134 size_t bufsz) 135{ 136 enum packno_bits packno_bits; 137 lsquic_ver_tag_t ver_tag; 138 unsigned char *p; 139 size_t need; 140 141 need = gquic_Q046_packout_header_size_long(lconn, packet_out->po_flags); 142 if (need > bufsz) 143 { 144 errno = EINVAL; 145 return -1; 146 } 147 148 p = buf; 149 packno_bits = IQUIC_PACKNO_LEN_4; 150 *p++ = 0x80 | 0x40 151 | (header_type_to_bin[ packet_out->po_header_type ] << 4) 152 | packno_bits; 153 ver_tag = lsquic_ver2tag(lconn->cn_version); 154 memcpy(p, &ver_tag, sizeof(ver_tag)); 155 p += sizeof(ver_tag); 156 157 *p++ = 0x50; 158 159 memcpy(p, &lconn->cn_cid, 8); 160 p += 8; 161 162 p += write_packno(p, packet_out->po_packno, packno_bits); 163 164 165 assert(need == (unsigned int)(p - buf)); 166 return p - buf; 167} 168 169 170static int 171gquic_Q046_gen_reg_pkt_header (const struct lsquic_conn *lconn, 172 const struct lsquic_packet_out *packet_out, unsigned char *buf, 173 size_t bufsz) 174{ 175 if (0 == (packet_out->po_flags & PO_LONGHEAD)) 176 return gen_short_pkt_header(lconn, packet_out, buf, bufsz); 177 else 178 return gen_long_pkt_header(lconn, packet_out, buf, bufsz); 179} 180 181 182static size_t 183gquic_Q046_packout_header_size_short (const struct lsquic_conn *lconn, 184 enum packet_out_flags flags) 185{ 186 enum packno_bits bits; 187 size_t sz; 188 189 bits = (flags >> POBIT_SHIFT) & 0x3; 190 sz = 1; /* Type */ 191 sz += 8; /* CID */ 192 sz += iquic_packno_bits2len(bits); 193 194 return sz; 195} 196 197 198static size_t 199gquic_Q046_packout_header_size (const struct lsquic_conn *lconn, 200 enum packet_out_flags flags) 201{ 202 if (0 == (flags & PO_LONGHEAD)) 203 return gquic_Q046_packout_header_size_short(lconn, flags); 204 else 205 return gquic_Q046_packout_header_size_long(lconn, flags); 206} 207 208 209static size_t 210gquic_Q046_packout_size (const struct lsquic_conn *lconn, 211 const struct lsquic_packet_out *packet_out) 212{ 213 size_t sz; 214 215 if (0 == (packet_out->po_flags & PO_LONGHEAD)) 216 sz = gquic_Q046_packout_header_size_short(lconn, packet_out->po_flags); 217 else 218 sz = gquic_Q046_packout_header_size_long(lconn, packet_out->po_flags); 219 220 sz += packet_out->po_data_sz; 221 sz += QUIC_PACKET_HASH_SZ; 222 223 return sz; 224} 225 226 227const struct parse_funcs lsquic_parse_funcs_gquic_Q046 = 228{ 229 .pf_gen_reg_pkt_header = gquic_Q046_gen_reg_pkt_header, 230 .pf_parse_packet_in_finish = gquic_be_parse_packet_in_finish, 231 .pf_gen_stream_frame = gquic_be_gen_stream_frame, 232 .pf_calc_stream_frame_header_sz = calc_stream_frame_header_sz_gquic, 233 .pf_parse_stream_frame = gquic_be_parse_stream_frame, 234 .pf_parse_ack_frame = gquic_be_parse_ack_frame, 235 .pf_gen_ack_frame = gquic_be_gen_ack_frame, 236 .pf_gen_stop_waiting_frame = gquic_be_gen_stop_waiting_frame, 237 .pf_parse_stop_waiting_frame = gquic_be_parse_stop_waiting_frame, 238 .pf_skip_stop_waiting_frame = gquic_be_skip_stop_waiting_frame, 239 .pf_gen_window_update_frame = gquic_be_gen_window_update_frame, 240 .pf_parse_window_update_frame = gquic_be_parse_window_update_frame, 241 .pf_gen_blocked_frame = gquic_be_gen_blocked_frame, 242 .pf_parse_blocked_frame = gquic_be_parse_blocked_frame, 243 .pf_gen_rst_frame = gquic_be_gen_rst_frame, 244 .pf_parse_rst_frame = gquic_be_parse_rst_frame, 245 .pf_gen_connect_close_frame = gquic_be_gen_connect_close_frame, 246 .pf_parse_connect_close_frame = gquic_be_parse_connect_close_frame, 247 .pf_gen_goaway_frame = gquic_be_gen_goaway_frame, 248 .pf_parse_goaway_frame = gquic_be_parse_goaway_frame, 249 .pf_gen_ping_frame = gquic_be_gen_ping_frame, 250#ifndef NDEBUG 251 .pf_write_float_time16 = gquic_be_write_float_time16, 252 .pf_read_float_time16 = gquic_be_read_float_time16, 253#endif 254 .pf_parse_frame_type = parse_frame_type_gquic_Q035_thru_Q039, 255 .pf_turn_on_fin = lsquic_turn_on_fin_Q035_thru_Q039, 256 .pf_packout_size = gquic_Q046_packout_size, 257 .pf_packout_header_size = gquic_Q046_packout_header_size, 258 .pf_calc_packno_bits = gquic_Q046_calc_packno_bits, 259 .pf_packno_bits2len = gquic_Q046_packno_bits2len, 260}; 261