/* Copyright (c) 2017 - 2020 LiteSpeed Technologies Inc. See LICENSE. */ #ifndef LSQUIC_PACKET_COMMON_H #define LSQUIC_PACKET_COMMON_H 1 /* The list of frames contains frames both in GQUIC and in IETF QUIC. * They are marked as follows: * G Applicable to GQUIC only * I Applicable to IETF QUIC only * B Applicable to both GQUIC and IETF QUIC. */ enum quic_frame_type { QUIC_FRAME_INVALID, QUIC_FRAME_STREAM, /* B */ QUIC_FRAME_ACK, /* B */ QUIC_FRAME_PADDING, /* B */ QUIC_FRAME_RST_STREAM, /* B */ QUIC_FRAME_CONNECTION_CLOSE, /* B */ QUIC_FRAME_GOAWAY, /* G */ QUIC_FRAME_WINDOW_UPDATE, /* G */ QUIC_FRAME_BLOCKED, /* B */ QUIC_FRAME_STOP_WAITING, /* G */ QUIC_FRAME_PING, /* B */ QUIC_FRAME_MAX_DATA, /* I */ QUIC_FRAME_MAX_STREAM_DATA, /* I */ QUIC_FRAME_MAX_STREAMS, /* I */ QUIC_FRAME_STREAM_BLOCKED, /* I */ QUIC_FRAME_STREAMS_BLOCKED, /* I */ QUIC_FRAME_NEW_CONNECTION_ID, /* I */ QUIC_FRAME_STOP_SENDING, /* I */ QUIC_FRAME_PATH_CHALLENGE, /* I */ QUIC_FRAME_PATH_RESPONSE, /* I */ QUIC_FRAME_CRYPTO, /* B */ QUIC_FRAME_RETIRE_CONNECTION_ID,/* I */ QUIC_FRAME_NEW_TOKEN, /* I */ QUIC_FRAME_HANDSHAKE_DONE, /* I */ QUIC_FRAME_ACK_FREQUENCY, /* I */ QUIC_FRAME_TIMESTAMP, /* I */ N_QUIC_FRAMES }; enum quic_ft_bit { QUIC_FTBIT_INVALID = 1 << QUIC_FRAME_INVALID, QUIC_FTBIT_STREAM = 1 << QUIC_FRAME_STREAM, QUIC_FTBIT_ACK = 1 << QUIC_FRAME_ACK, QUIC_FTBIT_PADDING = 1 << QUIC_FRAME_PADDING, QUIC_FTBIT_RST_STREAM = 1 << QUIC_FRAME_RST_STREAM, QUIC_FTBIT_CONNECTION_CLOSE = 1 << QUIC_FRAME_CONNECTION_CLOSE, QUIC_FTBIT_GOAWAY = 1 << QUIC_FRAME_GOAWAY, QUIC_FTBIT_WINDOW_UPDATE = 1 << QUIC_FRAME_WINDOW_UPDATE, QUIC_FTBIT_BLOCKED = 1 << QUIC_FRAME_BLOCKED, QUIC_FTBIT_STOP_WAITING = 1 << QUIC_FRAME_STOP_WAITING, QUIC_FTBIT_PING = 1 << QUIC_FRAME_PING, QUIC_FTBIT_MAX_DATA = 1 << QUIC_FRAME_MAX_DATA, QUIC_FTBIT_MAX_STREAM_DATA = 1 << QUIC_FRAME_MAX_STREAM_DATA, QUIC_FTBIT_MAX_STREAMS = 1 << QUIC_FRAME_MAX_STREAMS, QUIC_FTBIT_STREAM_BLOCKED = 1 << QUIC_FRAME_STREAM_BLOCKED, QUIC_FTBIT_STREAMS_BLOCKED = 1 << QUIC_FRAME_STREAMS_BLOCKED, QUIC_FTBIT_NEW_CONNECTION_ID = 1 << QUIC_FRAME_NEW_CONNECTION_ID, QUIC_FTBIT_STOP_SENDING = 1 << QUIC_FRAME_STOP_SENDING, QUIC_FTBIT_PATH_CHALLENGE = 1 << QUIC_FRAME_PATH_CHALLENGE, QUIC_FTBIT_PATH_RESPONSE = 1 << QUIC_FRAME_PATH_RESPONSE, QUIC_FTBIT_CRYPTO = 1 << QUIC_FRAME_CRYPTO, QUIC_FTBIT_NEW_TOKEN = 1 << QUIC_FRAME_NEW_TOKEN, QUIC_FTBIT_RETIRE_CONNECTION_ID = 1 << QUIC_FRAME_RETIRE_CONNECTION_ID, QUIC_FTBIT_HANDSHAKE_DONE = 1 << QUIC_FRAME_HANDSHAKE_DONE, QUIC_FTBIT_ACK_FREQUENCY = 1 << QUIC_FRAME_ACK_FREQUENCY, QUIC_FTBIT_TIMESTAMP = 1 << QUIC_FRAME_TIMESTAMP, }; static const char * const frame_type_2_str[N_QUIC_FRAMES] = { [QUIC_FRAME_INVALID] = "QUIC_FRAME_INVALID", [QUIC_FRAME_STREAM] = "QUIC_FRAME_STREAM", [QUIC_FRAME_ACK] = "QUIC_FRAME_ACK", [QUIC_FRAME_PADDING] = "QUIC_FRAME_PADDING", [QUIC_FRAME_RST_STREAM] = "QUIC_FRAME_RST_STREAM", [QUIC_FRAME_CONNECTION_CLOSE] = "QUIC_FRAME_CONNECTION_CLOSE", [QUIC_FRAME_GOAWAY] = "QUIC_FRAME_GOAWAY", [QUIC_FRAME_WINDOW_UPDATE] = "QUIC_FRAME_WINDOW_UPDATE", [QUIC_FRAME_BLOCKED] = "QUIC_FRAME_BLOCKED", [QUIC_FRAME_STOP_WAITING] = "QUIC_FRAME_STOP_WAITING", [QUIC_FRAME_PING] = "QUIC_FRAME_PING", [QUIC_FRAME_MAX_DATA] = "QUIC_FRAME_MAX_DATA", [QUIC_FRAME_MAX_STREAM_DATA] = "QUIC_FRAME_MAX_STREAM_DATA", [QUIC_FRAME_MAX_STREAMS] = "QUIC_FRAME_MAX_STREAMS", [QUIC_FRAME_STREAM_BLOCKED] = "QUIC_FRAME_STREAM_BLOCKED", [QUIC_FRAME_STREAMS_BLOCKED] = "QUIC_FRAME_STREAMS_BLOCKED", [QUIC_FRAME_NEW_CONNECTION_ID] = "QUIC_FRAME_NEW_CONNECTION_ID", [QUIC_FRAME_STOP_SENDING] = "QUIC_FRAME_STOP_SENDING", [QUIC_FRAME_PATH_CHALLENGE] = "QUIC_FRAME_PATH_CHALLENGE", [QUIC_FRAME_PATH_RESPONSE] = "QUIC_FRAME_PATH_RESPONSE", [QUIC_FRAME_CRYPTO] = "QUIC_FRAME_CRYPTO", [QUIC_FRAME_NEW_TOKEN] = "QUIC_FRAME_NEW_TOKEN", [QUIC_FRAME_RETIRE_CONNECTION_ID] = "QUIC_FRAME_RETIRE_CONNECTION_ID", [QUIC_FRAME_HANDSHAKE_DONE] = "QUIC_FRAME_HANDSHAKE_DONE", [QUIC_FRAME_ACK_FREQUENCY] = "QUIC_FRAME_ACK_FREQUENCY", [QUIC_FRAME_TIMESTAMP] = "QUIC_FRAME_TIMESTAMP", }; #define QUIC_FRAME_PRELEN (sizeof("QUIC_FRAME_")) #define QUIC_FRAME_SLEN(x) (sizeof(#x) - QUIC_FRAME_PRELEN) #define QUIC_FRAME_NAME(i) (frame_type_2_str[i] + QUIC_FRAME_PRELEN - 1) /* We don't need to include INVALID frame in this list because it is * never a part of any frame list bitmask (e.g. po_frame_types). */ #define lsquic_frame_types_str_sz \ QUIC_FRAME_SLEN(QUIC_FRAME_STREAM) + 1 + \ QUIC_FRAME_SLEN(QUIC_FRAME_ACK) + 1 + \ QUIC_FRAME_SLEN(QUIC_FRAME_PADDING) + 1 + \ QUIC_FRAME_SLEN(QUIC_FRAME_RST_STREAM) + 1 + \ QUIC_FRAME_SLEN(QUIC_FRAME_CONNECTION_CLOSE) + 1 + \ QUIC_FRAME_SLEN(QUIC_FRAME_GOAWAY) + 1 + \ QUIC_FRAME_SLEN(QUIC_FRAME_WINDOW_UPDATE) + 1 + \ QUIC_FRAME_SLEN(QUIC_FRAME_BLOCKED) + 1 + \ QUIC_FRAME_SLEN(QUIC_FRAME_STOP_WAITING) + 1 + \ QUIC_FRAME_SLEN(QUIC_FRAME_PING) + 1 + \ QUIC_FRAME_SLEN(QUIC_FRAME_MAX_DATA) + 1 + \ QUIC_FRAME_SLEN(QUIC_FRAME_MAX_STREAM_DATA) + 1 + \ QUIC_FRAME_SLEN(QUIC_FRAME_MAX_STREAMS) + 1 + \ QUIC_FRAME_SLEN(QUIC_FRAME_STREAM_BLOCKED) + 1 + \ QUIC_FRAME_SLEN(QUIC_FRAME_STREAMS_BLOCKED) + 1 + \ QUIC_FRAME_SLEN(QUIC_FRAME_NEW_CONNECTION_ID) + 1 + \ QUIC_FRAME_SLEN(QUIC_FRAME_STOP_SENDING) + 1 + \ QUIC_FRAME_SLEN(QUIC_FRAME_PATH_CHALLENGE) + 1 + \ QUIC_FRAME_SLEN(QUIC_FRAME_PATH_RESPONSE) + 1 + \ QUIC_FRAME_SLEN(QUIC_FRAME_CRYPTO) + 1 + \ QUIC_FRAME_SLEN(QUIC_FRAME_RETIRE_CONNECTION_ID) \ + 1 + \ QUIC_FRAME_SLEN(QUIC_FRAME_NEW_TOKEN) + 1 + \ QUIC_FRAME_SLEN(QUIC_FRAME_HANDSHAKE_DONE) + 1 + \ QUIC_FRAME_SLEN(QUIC_FRAME_ACK_FREQUENCY) + 1 + \ QUIC_FRAME_SLEN(QUIC_FRAME_TIMESTAMP) + 1 + \ 0 const char * lsquic_frame_types_to_str (char *buf, size_t bufsz, enum quic_ft_bit); /* This value represents a different number of bytes used to encode the packet * length based on whether GQUIC or IQUIC is used. */ enum packno_bits { PACKNO_BITS_0 = 0, PACKNO_BITS_1 = 1, PACKNO_BITS_2 = 2, PACKNO_BITS_3 = 3, }; /* GQUIC maps 0, 1, 2, 3 -> 1, 2, 4, 6 */ enum { GQUIC_PACKNO_LEN_1 = PACKNO_BITS_0, GQUIC_PACKNO_LEN_2 = PACKNO_BITS_1, GQUIC_PACKNO_LEN_4 = PACKNO_BITS_2, GQUIC_PACKNO_LEN_6 = PACKNO_BITS_3, }; /* IQUIC maps 0, 1, 2, 3 -> 1, 2, 3, 4 (as of ID-17) */ enum { IQUIC_PACKNO_LEN_1 = PACKNO_BITS_0, IQUIC_PACKNO_LEN_2 = PACKNO_BITS_1, IQUIC_PACKNO_LEN_3 = PACKNO_BITS_2, IQUIC_PACKNO_LEN_4 = PACKNO_BITS_3, }; enum header_type { HETY_NOT_SET, /* This value must be zero */ HETY_VERNEG, HETY_INITIAL, HETY_RETRY, HETY_HANDSHAKE, HETY_0RTT, }; extern const char *const lsquic_hety2str[]; #define IQUIC_MAX_PACKNO ((1ULL << 62) - 1) #define IQUIC_INVALID_PACKNO (IQUIC_MAX_PACKNO + 1) /* IETF QUIC only: */ #define is_valid_packno(packno) ((packno) <= IQUIC_MAX_PACKNO) enum packnum_space { PNS_INIT, PNS_HSK, PNS_APP, N_PNS }; extern const enum packnum_space lsquic_hety2pns[]; extern const enum packnum_space lsquic_enclev2pns[]; extern const char *const lsquic_pns2str[]; #define ALL_IQUIC_FRAMES ( \ QUIC_FTBIT_STREAM \ | QUIC_FTBIT_ACK \ | QUIC_FTBIT_PADDING \ | QUIC_FTBIT_RST_STREAM \ | QUIC_FTBIT_CONNECTION_CLOSE \ | QUIC_FTBIT_BLOCKED \ | QUIC_FTBIT_PING \ | QUIC_FTBIT_MAX_DATA \ | QUIC_FTBIT_MAX_STREAM_DATA \ | QUIC_FTBIT_MAX_STREAMS \ | QUIC_FTBIT_STREAM_BLOCKED \ | QUIC_FTBIT_STREAMS_BLOCKED \ | QUIC_FTBIT_NEW_CONNECTION_ID \ | QUIC_FTBIT_STOP_SENDING \ | QUIC_FTBIT_PATH_CHALLENGE \ | QUIC_FTBIT_PATH_RESPONSE \ | QUIC_FTBIT_RETIRE_CONNECTION_ID \ | QUIC_FTBIT_NEW_TOKEN \ | QUIC_FTBIT_HANDSHAKE_DONE \ | QUIC_FTBIT_ACK_FREQUENCY \ | QUIC_FTBIT_TIMESTAMP \ | QUIC_FTBIT_CRYPTO ) /* [draft-ietf-quic-transport-24] Section 1.2 */ #define IQUIC_FRAME_ACKABLE_MASK ( \ ALL_IQUIC_FRAMES & ~(QUIC_FTBIT_ACK|QUIC_FTBIT_PADDING\ |QUIC_FTBIT_CONNECTION_CLOSE|QUIC_FTBIT_TIMESTAMP)) /* [draft-ietf-quic-transport-20], Section 13.2 */ /* We bend some rules and retransmit BLOCKED, MAX_DATA, MAX_STREAM_DATA, * MAX_STREAMS, STREAM_BLOCKED, and STREAMS_BLOCKED frames instead of * regenerating them. This keeps the code simple(r). */ #define IQUIC_FRAME_RETX_MASK ( \ ALL_IQUIC_FRAMES & ~(QUIC_FTBIT_PADDING|QUIC_FTBIT_PATH_RESPONSE \ |QUIC_FTBIT_PATH_CHALLENGE|QUIC_FTBIT_ACK|QUIC_FTBIT_TIMESTAMP)) extern const enum quic_ft_bit lsquic_legal_frames_by_level[][4]; #endif