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