/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE. */ /* * lsquic_parse_Q050.c -- Parsing functions specific to GQUIC Q050 */ #include #include #include #include #include #ifndef WIN32 #include #else #include #endif #include "lsquic_types.h" #include "lsquic_int_types.h" #include "lsquic_packet_common.h" #include "lsquic_packet_in.h" #include "lsquic_packet_out.h" #include "lsquic_parse.h" #include "lsquic_parse_common.h" #include "lsquic_version.h" #include "lsquic.h" #include "lsquic_parse_gquic_be.h" #include "lsquic_parse_ietf.h" #include "lsquic_byteswap.h" #include "lsquic_hash.h" #include "lsquic_conn.h" #include "lsquic_varint.h" #include "lsquic_enc_sess.h" #define LSQUIC_LOGGER_MODULE LSQLM_PARSE #include "lsquic_logger.h" /* [draft-ietf-quic-transport-24] Section-17.2 */ static const enum header_type bits2ht[4] = { [0] = HETY_INITIAL, [1] = HETY_0RTT, [2] = HETY_HANDSHAKE, [3] = HETY_RETRY, }; int lsquic_Q050_parse_packet_in_long_begin (struct lsquic_packet_in *packet_in, size_t length, int is_server, unsigned cid_len, struct packin_parse_state *state) { const unsigned char *p = packet_in->pi_data; const unsigned char *const end = p + length; lsquic_ver_tag_t tag; enum header_type header_type; unsigned dcil, scil, odcil; int verneg, r; unsigned char first_byte; uint64_t payload_len, token_len; if (length < 6) return -1; first_byte = *p++; memcpy(&tag, p, 4); p += 4; verneg = 0 == tag; if (!verneg) header_type = bits2ht[ (first_byte >> 4) & 3 ]; else header_type = HETY_VERNEG; packet_in->pi_header_type = header_type; dcil = *p++; if (p + dcil >= end || dcil > MAX_CID_LEN) return -1; if (dcil) { memcpy(packet_in->pi_dcid.idbuf, p, dcil); packet_in->pi_flags |= PI_CONN_ID; p += dcil; packet_in->pi_dcid.len = dcil; } scil = *p++; if (p + scil > end || scil > MAX_CID_LEN) return -1; if (scil) { memcpy(packet_in->pi_dcid.idbuf, p, scil); packet_in->pi_flags |= PI_CONN_ID; p += scil; packet_in->pi_dcid.len = scil; } if (is_server) { if (scil) return -1; } else if (dcil) return -1; switch (header_type) { case HETY_INITIAL: r = vint_read(p, end, &token_len); if (r < 0) return -1; if (token_len && !is_server) { /* From [draft-ietf-quic-transport-14]: * * Token Length: A variable-length integer specifying the * length of the Token field, in bytes. This value is zero * if no token is present. Initial packets sent by the * server MUST set the Token Length field to zero; clients * that receive an Initial packet with a non-zero Token * Length field MUST either discard the packet or generate * a connection error of type PROTOCOL_VIOLATION. */ return -1; } p += r; if (token_len) { if (token_len >= 1ull << (sizeof(packet_in->pi_token_size) * 8)) return -1; if (p + token_len > end) return -1; packet_in->pi_token = p - packet_in->pi_data; packet_in->pi_token_size = token_len; p += token_len; } /* fall-through */ case HETY_HANDSHAKE: case HETY_0RTT: if (p >= end) return -1; r = vint_read(p, end, &payload_len); if (r < 0) return -1; p += r; if (p - packet_in->pi_data + payload_len > length) return -1; length = p - packet_in->pi_data + payload_len; if (end - p < 4) return -1; state->pps_p = p - r; state->pps_nbytes = r; packet_in->pi_quic_ver = 1; break; case HETY_RETRY: if (p >= end) return -1; odcil = *p++; if (p + odcil > end || odcil > MAX_CID_LEN) return -1; packet_in->pi_odcid_len = odcil; packet_in->pi_odcid = p - packet_in->pi_data; p += odcil; packet_in->pi_token = p - packet_in->pi_data; packet_in->pi_token_size = end - p; p = end; length = end - packet_in->pi_data; state->pps_p = NULL; state->pps_nbytes = 0; packet_in->pi_quic_ver = 1; break; default: assert(header_type == HETY_VERNEG); if (p >= end || (3 & (uintptr_t) (end - p))) return -1; packet_in->pi_quic_ver = p - packet_in->pi_data; p = end; state->pps_p = NULL; state->pps_nbytes = 0; break; } packet_in->pi_header_sz = p - packet_in->pi_data; packet_in->pi_data_sz = length; packet_in->pi_nonce = 0; packet_in->pi_refcnt = 0; packet_in->pi_frame_types = 0; memset(&packet_in->pi_next, 0, sizeof(packet_in->pi_next)); packet_in->pi_refcnt = 0; packet_in->pi_received = 0; /* Packet number is set to an invalid value. The packet number must * be decrypted, which happens later. */ packet_in->pi_packno = 1ULL << 62; return 0; } static unsigned gquic_Q050_packno_bits2len (enum packno_bits bits) { return bits + 1; } #define iquic_packno_bits2len gquic_Q050_packno_bits2len static enum packno_bits gquic_Q050_calc_packno_bits (lsquic_packno_t packno, lsquic_packno_t least_unacked, uint64_t n_in_flight) { uint64_t delta; unsigned bits; delta = packno - least_unacked; if (n_in_flight > delta) delta = n_in_flight; delta *= 4; bits = (delta >= (1ULL << 8)) + (delta >= (1ULL << 16)) + (delta >= (1ULL << 24)) ; return bits; } static unsigned write_packno (unsigned char *p, lsquic_packno_t packno, enum packno_bits bits) { unsigned char *const begin = p; switch (bits) { case IQUIC_PACKNO_LEN_4: *p++ = packno >> 24; /* fall-through */ case IQUIC_PACKNO_LEN_3: *p++ = packno >> 16; /* fall-through */ case IQUIC_PACKNO_LEN_2: *p++ = packno >> 8; /* fall-through */ default: *p++ = packno; } return p - begin; } static int gen_short_pkt_header (const struct lsquic_conn *lconn, const struct lsquic_packet_out *packet_out, unsigned char *buf, size_t bufsz) { unsigned packno_len, need; enum packno_bits bits; bits = lsquic_packet_out_packno_bits(packet_out); packno_len = iquic_packno_bits2len(bits); if (lconn->cn_flags & LSCONN_SERVER) need = 1 + packno_len; else need = 1 + 8 /* CID */ + packno_len; if (need > bufsz) return -1; *buf++ = 0x40 | bits; if (0 == (lconn->cn_flags & LSCONN_SERVER)) { memcpy(buf, lconn->cn_cid.idbuf, 8); buf += 8; } (void) write_packno(buf, packet_out->po_packno, bits); return need; } static size_t gquic_Q050_packout_header_size_long_by_flags (const struct lsquic_conn *lconn, enum packet_out_flags flags) { size_t sz; enum packno_bits packno_bits; packno_bits = (flags >> POBIT_SHIFT) & 0x3; sz = 1 /* Type */ + 4 /* Version */ + 1 /* DCIL */ + 1 /* SCIL */ + lconn->cn_cid.len + 1 /* Token length: only use for Initial packets, while token is never * set in this version. */ + (flags & PO_NONCE ? DNONC_LENGTH : 0) + 2 /* Always use two bytes to encode payload length */ + iquic_packno_bits2len(packno_bits) ; return sz; } /* [draft-ietf-quic-transport-17] Section-17.2 */ static const unsigned char header_type_to_bin[] = { [HETY_INITIAL] = 0x0, [HETY_0RTT] = 0x1, [HETY_HANDSHAKE] = 0x2, [HETY_RETRY] = 0x3, }; static size_t gquic_Q050_packout_header_size_long_by_packet (const struct lsquic_conn *lconn, const struct lsquic_packet_out *packet_out) { size_t sz; enum packno_bits packno_bits; packno_bits = lsquic_packet_out_packno_bits(packet_out); sz = 1 /* Type */ + 4 /* Version */ + 1 /* DCIL */ + 1 /* SCIL */ + lconn->cn_cid.len /* Token is never sent, but token length byte is used */ + (packet_out->po_header_type == HETY_INITIAL) + 2 /* Always use two bytes to encode payload length */ + iquic_packno_bits2len(packno_bits) + (packet_out->po_nonce ? DNONC_LENGTH : 0) ; return sz; } static void gquic_Q050_packno_info (const struct lsquic_conn *lconn, const struct lsquic_packet_out *packet_out, unsigned *packno_off, unsigned *packno_len) { unsigned token_len; /* Need intermediate value to quiet compiler warning */ if (packet_out->po_header_type == HETY_NOT_SET) *packno_off = 1 + (lconn->cn_flags & LSCONN_SERVER ? 0 : 8); else *packno_off = 1 + 4 + 1 + 1 + lconn->cn_cid.len + (packet_out->po_header_type == HETY_INITIAL ? (token_len = packet_out->po_token_len, (1 << vint_val2bits(token_len)) + token_len) : 0) + 2; *packno_len = iquic_packno_bits2len( lsquic_packet_out_packno_bits(packet_out)); } static int gquic_Q050_gen_long_pkt_header (const struct lsquic_conn *lconn, const struct lsquic_packet_out *packet_out, unsigned char *buf, size_t bufsz) { enum packno_bits packno_bits; lsquic_ver_tag_t ver_tag; unsigned token_len, payload_len, bits; unsigned char *p; size_t need; need = gquic_Q050_packout_header_size_long_by_packet(lconn, packet_out); if (need > bufsz) { errno = EINVAL; return -1; } packno_bits = lsquic_packet_out_packno_bits(packet_out); p = buf; *p++ = 0x80 | 0x40 | (header_type_to_bin[ packet_out->po_header_type ] << 4) | packno_bits; ver_tag = lsquic_ver2tag(lconn->cn_version); memcpy(p, &ver_tag, sizeof(ver_tag)); p += sizeof(ver_tag); if (lconn->cn_flags & LSCONN_SERVER) { *p++ = 0; *p++ = lconn->cn_cid.len; memcpy(p, lconn->cn_cid.idbuf, lconn->cn_cid.len); p += lconn->cn_cid.len; } else { *p++ = lconn->cn_cid.len; memcpy(p, lconn->cn_cid.idbuf, lconn->cn_cid.len); p += lconn->cn_cid.len; *p++ = 0; } if (HETY_INITIAL == packet_out->po_header_type) { token_len = packet_out->po_token_len; bits = vint_val2bits(token_len); vint_write(p, token_len, bits, 1 << bits); p += 1 << bits; memcpy(p, packet_out->po_token, token_len); p += token_len; } payload_len = packet_out->po_data_sz + lconn->cn_esf_c->esf_tag_len + iquic_packno_bits2len(packno_bits); if (packet_out->po_nonce) payload_len += DNONC_LENGTH; bits = 1; /* Always use two bytes to encode payload length */ vint_write(p, payload_len, bits, 1 << bits); p += 1 << bits; p += write_packno(p, packet_out->po_packno, packno_bits); if (packet_out->po_nonce) { memcpy(p, packet_out->po_nonce, DNONC_LENGTH); p += DNONC_LENGTH; } assert(need == (size_t) (p - buf)); return p - buf; } static int gquic_Q050_gen_reg_pkt_header (const struct lsquic_conn *lconn, const struct lsquic_packet_out *packet_out, unsigned char *buf, size_t bufsz) { if (0 == (packet_out->po_flags & PO_LONGHEAD)) return gen_short_pkt_header(lconn, packet_out, buf, bufsz); else return gquic_Q050_gen_long_pkt_header(lconn, packet_out, buf, bufsz); } static size_t gquic_Q050_packout_header_size_short (const struct lsquic_conn *lconn, enum packet_out_flags flags) { enum packno_bits bits; size_t sz; bits = (flags >> POBIT_SHIFT) & 0x3; sz = 1; /* Type */ sz += (lconn->cn_flags & LSCONN_SERVER) ? 0 : 8; sz += iquic_packno_bits2len(bits); return sz; } static size_t gquic_Q050_packout_max_header_size (const struct lsquic_conn *lconn, enum packet_out_flags flags, size_t dcid_len_unused) { if (lconn->cn_flags & LSCONN_SERVER) { if (0 == (flags & PO_LONGHEAD)) return gquic_Q050_packout_header_size_short(lconn, flags); else return gquic_Q050_packout_header_size_long_by_flags(lconn, flags); } else { if (lconn->cn_flags & LSCONN_HANDSHAKE_DONE) return gquic_Q050_packout_header_size_short(lconn, flags); else return gquic_Q050_packout_header_size_long_by_flags(lconn, flags); } } static size_t gquic_Q050_packout_size (const struct lsquic_conn *lconn, const struct lsquic_packet_out *packet_out) { size_t sz; if ((lconn->cn_flags & LSCONN_HANDSHAKE_DONE) && packet_out->po_header_type == HETY_NOT_SET) sz = gquic_Q050_packout_header_size_short(lconn, packet_out->po_flags); else sz = gquic_Q050_packout_header_size_long_by_packet(lconn, packet_out); sz += packet_out->po_data_sz; sz += lconn->cn_esf_c->esf_tag_len; return sz; } static void gquic_Q050_parse_packet_in_finish (struct lsquic_packet_in *packet_in, struct packin_parse_state *state) { } /* Same as Q046 plus CRYPTO frame at slot 8 */ static const enum quic_frame_type byte2frame_type_Q050[0x100] = { [0x00] = QUIC_FRAME_PADDING, [0x01] = QUIC_FRAME_RST_STREAM, [0x02] = QUIC_FRAME_CONNECTION_CLOSE, [0x03] = QUIC_FRAME_GOAWAY, [0x04] = QUIC_FRAME_WINDOW_UPDATE, [0x05] = QUIC_FRAME_BLOCKED, [0x06] = QUIC_FRAME_STOP_WAITING, [0x07] = QUIC_FRAME_PING, [0x08] = QUIC_FRAME_CRYPTO, [0x09] = QUIC_FRAME_INVALID, [0x0A] = QUIC_FRAME_INVALID, [0x0B] = QUIC_FRAME_INVALID, [0x0C] = QUIC_FRAME_INVALID, [0x0D] = QUIC_FRAME_INVALID, [0x0E] = QUIC_FRAME_INVALID, [0x0F] = QUIC_FRAME_INVALID, [0x10] = QUIC_FRAME_INVALID, [0x11] = QUIC_FRAME_INVALID, [0x12] = QUIC_FRAME_INVALID, [0x13] = QUIC_FRAME_INVALID, [0x14] = QUIC_FRAME_INVALID, [0x15] = QUIC_FRAME_INVALID, [0x16] = QUIC_FRAME_INVALID, [0x17] = QUIC_FRAME_INVALID, [0x18] = QUIC_FRAME_INVALID, [0x19] = QUIC_FRAME_INVALID, [0x1A] = QUIC_FRAME_INVALID, [0x1B] = QUIC_FRAME_INVALID, [0x1C] = QUIC_FRAME_INVALID, [0x1D] = QUIC_FRAME_INVALID, [0x1E] = QUIC_FRAME_INVALID, [0x1F] = QUIC_FRAME_INVALID, [0x20] = QUIC_FRAME_INVALID, [0x21] = QUIC_FRAME_INVALID, [0x22] = QUIC_FRAME_INVALID, [0x23] = QUIC_FRAME_INVALID, [0x24] = QUIC_FRAME_INVALID, [0x25] = QUIC_FRAME_INVALID, [0x26] = QUIC_FRAME_INVALID, [0x27] = QUIC_FRAME_INVALID, [0x28] = QUIC_FRAME_INVALID, [0x29] = QUIC_FRAME_INVALID, [0x2A] = QUIC_FRAME_INVALID, [0x2B] = QUIC_FRAME_INVALID, [0x2C] = QUIC_FRAME_INVALID, [0x2D] = QUIC_FRAME_INVALID, [0x2E] = QUIC_FRAME_INVALID, [0x2F] = QUIC_FRAME_INVALID, [0x30] = QUIC_FRAME_INVALID, [0x31] = QUIC_FRAME_INVALID, [0x32] = QUIC_FRAME_INVALID, [0x33] = QUIC_FRAME_INVALID, [0x34] = QUIC_FRAME_INVALID, [0x35] = QUIC_FRAME_INVALID, [0x36] = QUIC_FRAME_INVALID, [0x37] = QUIC_FRAME_INVALID, [0x38] = QUIC_FRAME_INVALID, [0x39] = QUIC_FRAME_INVALID, [0x3A] = QUIC_FRAME_INVALID, [0x3B] = QUIC_FRAME_INVALID, [0x3C] = QUIC_FRAME_INVALID, [0x3D] = QUIC_FRAME_INVALID, [0x3E] = QUIC_FRAME_INVALID, [0x3F] = QUIC_FRAME_INVALID, [0x40] = QUIC_FRAME_ACK, [0x41] = QUIC_FRAME_ACK, [0x42] = QUIC_FRAME_ACK, [0x43] = QUIC_FRAME_ACK, [0x44] = QUIC_FRAME_ACK, [0x45] = QUIC_FRAME_ACK, [0x46] = QUIC_FRAME_ACK, [0x47] = QUIC_FRAME_ACK, [0x48] = QUIC_FRAME_ACK, [0x49] = QUIC_FRAME_ACK, [0x4A] = QUIC_FRAME_ACK, [0x4B] = QUIC_FRAME_ACK, [0x4C] = QUIC_FRAME_ACK, [0x4D] = QUIC_FRAME_ACK, [0x4E] = QUIC_FRAME_ACK, [0x4F] = QUIC_FRAME_ACK, [0x50] = QUIC_FRAME_ACK, [0x51] = QUIC_FRAME_ACK, [0x52] = QUIC_FRAME_ACK, [0x53] = QUIC_FRAME_ACK, [0x54] = QUIC_FRAME_ACK, [0x55] = QUIC_FRAME_ACK, [0x56] = QUIC_FRAME_ACK, [0x57] = QUIC_FRAME_ACK, [0x58] = QUIC_FRAME_ACK, [0x59] = QUIC_FRAME_ACK, [0x5A] = QUIC_FRAME_ACK, [0x5B] = QUIC_FRAME_ACK, [0x5C] = QUIC_FRAME_ACK, [0x5D] = QUIC_FRAME_ACK, [0x5E] = QUIC_FRAME_ACK, [0x5F] = QUIC_FRAME_ACK, [0x60] = QUIC_FRAME_ACK, [0x61] = QUIC_FRAME_ACK, [0x62] = QUIC_FRAME_ACK, [0x63] = QUIC_FRAME_ACK, [0x64] = QUIC_FRAME_ACK, [0x65] = QUIC_FRAME_ACK, [0x66] = QUIC_FRAME_ACK, [0x67] = QUIC_FRAME_ACK, [0x68] = QUIC_FRAME_ACK, [0x69] = QUIC_FRAME_ACK, [0x6A] = QUIC_FRAME_ACK, [0x6B] = QUIC_FRAME_ACK, [0x6C] = QUIC_FRAME_ACK, [0x6D] = QUIC_FRAME_ACK, [0x6E] = QUIC_FRAME_ACK, [0x6F] = QUIC_FRAME_ACK, [0x70] = QUIC_FRAME_ACK, [0x71] = QUIC_FRAME_ACK, [0x72] = QUIC_FRAME_ACK, [0x73] = QUIC_FRAME_ACK, [0x74] = QUIC_FRAME_ACK, [0x75] = QUIC_FRAME_ACK, [0x76] = QUIC_FRAME_ACK, [0x77] = QUIC_FRAME_ACK, [0x78] = QUIC_FRAME_ACK, [0x79] = QUIC_FRAME_ACK, [0x7A] = QUIC_FRAME_ACK, [0x7B] = QUIC_FRAME_ACK, [0x7C] = QUIC_FRAME_ACK, [0x7D] = QUIC_FRAME_ACK, [0x7E] = QUIC_FRAME_ACK, [0x7F] = QUIC_FRAME_ACK, [0x80] = QUIC_FRAME_STREAM, [0x81] = QUIC_FRAME_STREAM, [0x82] = QUIC_FRAME_STREAM, [0x83] = QUIC_FRAME_STREAM, [0x84] = QUIC_FRAME_STREAM, [0x85] = QUIC_FRAME_STREAM, [0x86] = QUIC_FRAME_STREAM, [0x87] = QUIC_FRAME_STREAM, [0x88] = QUIC_FRAME_STREAM, [0x89] = QUIC_FRAME_STREAM, [0x8A] = QUIC_FRAME_STREAM, [0x8B] = QUIC_FRAME_STREAM, [0x8C] = QUIC_FRAME_STREAM, [0x8D] = QUIC_FRAME_STREAM, [0x8E] = QUIC_FRAME_STREAM, [0x8F] = QUIC_FRAME_STREAM, [0x90] = QUIC_FRAME_STREAM, [0x91] = QUIC_FRAME_STREAM, [0x92] = QUIC_FRAME_STREAM, [0x93] = QUIC_FRAME_STREAM, [0x94] = QUIC_FRAME_STREAM, [0x95] = QUIC_FRAME_STREAM, [0x96] = QUIC_FRAME_STREAM, [0x97] = QUIC_FRAME_STREAM, [0x98] = QUIC_FRAME_STREAM, [0x99] = QUIC_FRAME_STREAM, [0x9A] = QUIC_FRAME_STREAM, [0x9B] = QUIC_FRAME_STREAM, [0x9C] = QUIC_FRAME_STREAM, [0x9D] = QUIC_FRAME_STREAM, [0x9E] = QUIC_FRAME_STREAM, [0x9F] = QUIC_FRAME_STREAM, [0xA0] = QUIC_FRAME_STREAM, [0xA1] = QUIC_FRAME_STREAM, [0xA2] = QUIC_FRAME_STREAM, [0xA3] = QUIC_FRAME_STREAM, [0xA4] = QUIC_FRAME_STREAM, [0xA5] = QUIC_FRAME_STREAM, [0xA6] = QUIC_FRAME_STREAM, [0xA7] = QUIC_FRAME_STREAM, [0xA8] = QUIC_FRAME_STREAM, [0xA9] = QUIC_FRAME_STREAM, [0xAA] = QUIC_FRAME_STREAM, [0xAB] = QUIC_FRAME_STREAM, [0xAC] = QUIC_FRAME_STREAM, [0xAD] = QUIC_FRAME_STREAM, [0xAE] = QUIC_FRAME_STREAM, [0xAF] = QUIC_FRAME_STREAM, [0xB0] = QUIC_FRAME_STREAM, [0xB1] = QUIC_FRAME_STREAM, [0xB2] = QUIC_FRAME_STREAM, [0xB3] = QUIC_FRAME_STREAM, [0xB4] = QUIC_FRAME_STREAM, [0xB5] = QUIC_FRAME_STREAM, [0xB6] = QUIC_FRAME_STREAM, [0xB7] = QUIC_FRAME_STREAM, [0xB8] = QUIC_FRAME_STREAM, [0xB9] = QUIC_FRAME_STREAM, [0xBA] = QUIC_FRAME_STREAM, [0xBB] = QUIC_FRAME_STREAM, [0xBC] = QUIC_FRAME_STREAM, [0xBD] = QUIC_FRAME_STREAM, [0xBE] = QUIC_FRAME_STREAM, [0xBF] = QUIC_FRAME_STREAM, [0xC0] = QUIC_FRAME_STREAM, [0xC1] = QUIC_FRAME_STREAM, [0xC2] = QUIC_FRAME_STREAM, [0xC3] = QUIC_FRAME_STREAM, [0xC4] = QUIC_FRAME_STREAM, [0xC5] = QUIC_FRAME_STREAM, [0xC6] = QUIC_FRAME_STREAM, [0xC7] = QUIC_FRAME_STREAM, [0xC8] = QUIC_FRAME_STREAM, [0xC9] = QUIC_FRAME_STREAM, [0xCA] = QUIC_FRAME_STREAM, [0xCB] = QUIC_FRAME_STREAM, [0xCC] = QUIC_FRAME_STREAM, [0xCD] = QUIC_FRAME_STREAM, [0xCE] = QUIC_FRAME_STREAM, [0xCF] = QUIC_FRAME_STREAM, [0xD0] = QUIC_FRAME_STREAM, [0xD1] = QUIC_FRAME_STREAM, [0xD2] = QUIC_FRAME_STREAM, [0xD3] = QUIC_FRAME_STREAM, [0xD4] = QUIC_FRAME_STREAM, [0xD5] = QUIC_FRAME_STREAM, [0xD6] = QUIC_FRAME_STREAM, [0xD7] = QUIC_FRAME_STREAM, [0xD8] = QUIC_FRAME_STREAM, [0xD9] = QUIC_FRAME_STREAM, [0xDA] = QUIC_FRAME_STREAM, [0xDB] = QUIC_FRAME_STREAM, [0xDC] = QUIC_FRAME_STREAM, [0xDD] = QUIC_FRAME_STREAM, [0xDE] = QUIC_FRAME_STREAM, [0xDF] = QUIC_FRAME_STREAM, [0xE0] = QUIC_FRAME_STREAM, [0xE1] = QUIC_FRAME_STREAM, [0xE2] = QUIC_FRAME_STREAM, [0xE3] = QUIC_FRAME_STREAM, [0xE4] = QUIC_FRAME_STREAM, [0xE5] = QUIC_FRAME_STREAM, [0xE6] = QUIC_FRAME_STREAM, [0xE7] = QUIC_FRAME_STREAM, [0xE8] = QUIC_FRAME_STREAM, [0xE9] = QUIC_FRAME_STREAM, [0xEA] = QUIC_FRAME_STREAM, [0xEB] = QUIC_FRAME_STREAM, [0xEC] = QUIC_FRAME_STREAM, [0xED] = QUIC_FRAME_STREAM, [0xEE] = QUIC_FRAME_STREAM, [0xEF] = QUIC_FRAME_STREAM, [0xF0] = QUIC_FRAME_STREAM, [0xF1] = QUIC_FRAME_STREAM, [0xF2] = QUIC_FRAME_STREAM, [0xF3] = QUIC_FRAME_STREAM, [0xF4] = QUIC_FRAME_STREAM, [0xF5] = QUIC_FRAME_STREAM, [0xF6] = QUIC_FRAME_STREAM, [0xF7] = QUIC_FRAME_STREAM, [0xF8] = QUIC_FRAME_STREAM, [0xF9] = QUIC_FRAME_STREAM, [0xFA] = QUIC_FRAME_STREAM, [0xFB] = QUIC_FRAME_STREAM, [0xFC] = QUIC_FRAME_STREAM, [0xFD] = QUIC_FRAME_STREAM, [0xFE] = QUIC_FRAME_STREAM, [0xFF] = QUIC_FRAME_STREAM, }; static enum quic_frame_type gquic_Q050_parse_frame_type (const unsigned char *buf, size_t len) { if (len > 0) return byte2frame_type_Q050[buf[0]]; else return QUIC_FRAME_INVALID; } static int gquic_Q050_gen_crypto_frame (unsigned char *buf, size_t buf_len, uint64_t offset, size_t size, gcf_read_f gcf_read, void *stream) { return lsquic_ietf_v1_gen_crypto_frame(buf, 0x8, buf_len, offset, size, gcf_read, stream); } static int gquic_Q050_parse_crypto_frame (const unsigned char *buf, size_t rem_packet_sz, struct stream_frame *stream_frame) { if (rem_packet_sz > 0) { assert(0x08 == buf[0]); return lsquic_ietf_v1_parse_crypto_frame(buf, rem_packet_sz, stream_frame); } else return -1; } static size_t gquic_Q050_calc_crypto_frame_header_sz (uint64_t offset, unsigned data_sz) { return 1 /* Frame type */ + (1 << vint_val2bits(offset)) + (1 << vint_val2bits(data_sz)) ; } /* No simple PRST for Q050 */ static ssize_t gquic_Q050_generate_simple_prst (const lsquic_cid_t *cidp, unsigned char *buf, size_t buf_sz) { return -1; } static unsigned gquic_Q050_handshake_done_frame_size (void) { return 0; } static int gquic_Q050_gen_handshake_done_frame (unsigned char *buf, size_t buf_len) { return -1; } static int gquic_Q050_parse_handshake_done_frame (const unsigned char *buf, size_t buf_len) { return -1; } const struct parse_funcs lsquic_parse_funcs_gquic_Q050 = { .pf_gen_reg_pkt_header = gquic_Q050_gen_reg_pkt_header, .pf_parse_packet_in_finish = gquic_Q050_parse_packet_in_finish, .pf_gen_stream_frame = lsquic_gquic_be_gen_stream_frame, .pf_calc_stream_frame_header_sz = lsquic_calc_stream_frame_header_sz_gquic, .pf_parse_stream_frame = lsquic_gquic_be_parse_stream_frame, .pf_parse_ack_frame = lsquic_gquic_be_parse_ack_frame, .pf_gen_ack_frame = lsquic_gquic_be_gen_ack_frame, .pf_gen_stop_waiting_frame = lsquic_gquic_be_gen_stop_waiting_frame, .pf_parse_stop_waiting_frame = lsquic_gquic_be_parse_stop_waiting_frame, .pf_skip_stop_waiting_frame = lsquic_gquic_be_skip_stop_waiting_frame, .pf_gen_window_update_frame = lsquic_gquic_be_gen_window_update_frame, .pf_parse_window_update_frame = lsquic_gquic_be_parse_window_update_frame, .pf_gen_blocked_frame = lsquic_gquic_be_gen_blocked_frame, .pf_parse_blocked_frame = lsquic_gquic_be_parse_blocked_frame, .pf_gen_rst_frame = lsquic_gquic_be_gen_rst_frame, .pf_parse_rst_frame = lsquic_gquic_be_parse_rst_frame, .pf_connect_close_frame_size = lsquic_gquic_be_connect_close_frame_size, .pf_gen_connect_close_frame = lsquic_gquic_be_gen_connect_close_frame, .pf_parse_connect_close_frame = lsquic_gquic_be_parse_connect_close_frame, .pf_gen_goaway_frame = lsquic_gquic_be_gen_goaway_frame, .pf_parse_goaway_frame = lsquic_gquic_be_parse_goaway_frame, .pf_gen_ping_frame = lsquic_gquic_be_gen_ping_frame, #ifndef NDEBUG .pf_write_float_time16 = lsquic_gquic_be_write_float_time16, .pf_read_float_time16 = lsquic_gquic_be_read_float_time16, #endif .pf_generate_simple_prst = gquic_Q050_generate_simple_prst, .pf_parse_frame_type = gquic_Q050_parse_frame_type, .pf_turn_on_fin = lsquic_turn_on_fin_Q035_thru_Q046, .pf_packout_size = gquic_Q050_packout_size, .pf_packout_max_header_size = gquic_Q050_packout_max_header_size, .pf_calc_packno_bits = gquic_Q050_calc_packno_bits, .pf_packno_bits2len = gquic_Q050_packno_bits2len, .pf_gen_crypto_frame = gquic_Q050_gen_crypto_frame, .pf_parse_crypto_frame = gquic_Q050_parse_crypto_frame, .pf_packno_info = gquic_Q050_packno_info, .pf_calc_crypto_frame_header_sz = gquic_Q050_calc_crypto_frame_header_sz, .pf_gen_handshake_done_frame = gquic_Q050_gen_handshake_done_frame, .pf_parse_handshake_done_frame = gquic_Q050_parse_handshake_done_frame, .pf_handshake_done_frame_size = gquic_Q050_handshake_done_frame_size, };