diff --git a/src/liblsquic/lsquic_parse.h b/src/liblsquic/lsquic_parse.h index 77ddf24..b609892 100644 --- a/src/liblsquic/lsquic_parse.h +++ b/src/liblsquic/lsquic_parse.h @@ -161,7 +161,6 @@ struct parse_funcs extern const struct parse_funcs lsquic_parse_funcs_gquic_le; /* Q039 and later are big-endian: */ extern const struct parse_funcs lsquic_parse_funcs_gquic_Q039; -extern const struct parse_funcs lsquic_parse_funcs_gquic_Q041; #define select_pf_by_ver(ver) ( \ ((1 << (ver)) & (1 << LSQVER_035)) \ @@ -176,9 +175,6 @@ parse_packet_in_begin (struct lsquic_packet_in *, size_t length, enum QUIC_FRAME_TYPE parse_frame_type_gquic_Q035_thru_Q039 (unsigned char first_byte); -enum QUIC_FRAME_TYPE -parse_frame_type_gquic_Q041 (unsigned char first_byte); - unsigned parse_stream_frame_header_sz_gquic (unsigned char type); diff --git a/src/liblsquic/lsquic_parse_gquic_Q041.c b/src/liblsquic/lsquic_parse_gquic_Q041.c deleted file mode 100644 index 44bdb07..0000000 --- a/src/liblsquic/lsquic_parse_gquic_Q041.c +++ /dev/null @@ -1,558 +0,0 @@ -/* Copyright (c) 2017 - 2018 LiteSpeed Technologies Inc. See LICENSE. */ -#include -#include -#include -#include -#include -#include -#ifndef WIN32 -#include -#else -#include -#endif - -#include "lsquic_types.h" -#include "lsquic_alarmset.h" -#include "lsquic_packet_common.h" -#include "lsquic_packet_in.h" -#include "lsquic_parse.h" -#include "lsquic_rechist.h" -#include "lsquic_sfcw.h" -#include "lsquic_stream.h" -#include "lsquic_mm.h" -#include "lsquic_malo.h" -#include "lsquic_version.h" -#include "lsquic.h" -#include "lsquic_parse_gquic_be.h" - -#define LSQUIC_LOGGER_MODULE LSQLM_PARSE -#include "lsquic_logger.h" - - -int -gquic_ietf_gen_rst_frame (unsigned char *buf, size_t buf_len, - uint32_t stream_id, uint64_t offset, uint32_t error_code) -{ - unsigned char *p = buf; - if (buf_len < QUIC_RST_STREAM_SZ) - return -1; - - *p = 0x01; - ++p; -#if __BYTE_ORDER == __LITTLE_ENDIAN - stream_id = bswap_32(stream_id); -#endif - memcpy(p, &stream_id, 4); - p += 4; -#if __BYTE_ORDER == __LITTLE_ENDIAN - error_code = bswap_32(error_code); -#endif - memcpy(p, &error_code, 4); - p += 4; -#if __BYTE_ORDER == __LITTLE_ENDIAN - offset = bswap_64(offset); -#endif - memcpy(p, &offset, 8); - p += 8; - return p - buf; -} - - -int -gquic_ietf_parse_rst_frame (const unsigned char *buf, size_t buf_len, - uint32_t *stream_id, uint64_t *offset, uint32_t *error_code) -{ - if (buf_len < QUIC_RST_STREAM_SZ) - return -1; - - READ_UINT(*stream_id, 32, buf + 1, 4); - READ_UINT(*error_code, 32, buf + 1 + 4, 4); - READ_UINT(*offset, 64, buf + 1 + 4 + 4, 8); - return QUIC_RST_STREAM_SZ; -} - - -unsigned -gquic_ietf_parse_stream_frame_header_sz (unsigned char type) -{ - const unsigned data_len = (type & 1) << 1; - const unsigned stream_id_len = ((type >> 3) & 3) + 1; - const unsigned offset_len = (((type >> 1) & 3) << 1) + - ((3 == ((type >> 1) & 3)) << 1); - return 1 + data_len + offset_len + stream_id_len; -} - - -static void -gquic_ietf_turn_on_fin (unsigned char *stream_header) -{ - /* 11FSSOOD */ - *stream_header |= 0x20; -} - - -int -gquic_ietf_parse_stream_frame (const unsigned char *buf, size_t rem_packet_sz, - stream_frame_t *stream_frame) -{ - /* 11FSSOOD */ - const unsigned char *p = buf; - const unsigned char *const pend = p + rem_packet_sz; - - CHECK_SPACE(1, p, pend); - const char type = *p++; - - const unsigned data_len = (type & 1) << 1; - const unsigned stream_id_len = ((type >> 3) & 3) + 1; - const unsigned offset_len = (((type >> 1) & 3) << 1) + - ((3 == ((type >> 1) & 3)) << 1); - const unsigned need = data_len + offset_len + stream_id_len; - CHECK_SPACE(need, p, pend); - - memset(stream_frame, 0, sizeof(*stream_frame)); - - stream_frame->data_frame.df_fin = !!(type & 0x20); - - READ_UINT(stream_frame->stream_id, 32, p, stream_id_len); - p += stream_id_len; - - READ_UINT(stream_frame->data_frame.df_offset, 64, p, offset_len); - p += offset_len; - - if (data_len) - { - READ_UINT(stream_frame->data_frame.df_size, 16, p, data_len); - p += data_len; - CHECK_SPACE(stream_frame->data_frame.df_size, p, pend); - stream_frame->data_frame.df_data = p; - p += stream_frame->data_frame.df_size; - } - else - { - stream_frame->data_frame.df_size = pend - p; - stream_frame->data_frame.df_data = p; - p = pend; - } - - /* From the spec: "A stream frame must always have either non-zero - * data length or the FIN bit set.' - */ - if (!(stream_frame->data_frame.df_size || - stream_frame->data_frame.df_fin)) - return -1; - - assert(p <= pend); - - return p - (unsigned char *) buf; -} - - -static size_t -gquic_ietf_calc_stream_frame_header_sz (uint32_t stream_id, uint64_t offset) -{ - return - /* Type */ - 1 - /* SS: Stream ID length: 1, 2, 3, or 4 bytes */ - + (stream_id > 0x0000FF) - + (stream_id > 0x00FFFF) - + (stream_id > 0xFFFFFF) - + 1 - /* OO: Offset length: 0, 2, 4, or 8 bytes */ - + ((offset >= (1ULL << 32)) << 2) - + ((offset >= (1ULL << 16)) << 1) - + ((offset > 1) << 1) - ; -} - - -int -gquic_ietf_gen_stream_frame (unsigned char *buf, size_t buf_len, uint32_t stream_id, - uint64_t offset, int fin, size_t size, - gsf_read_f gsf_read, void *stream) -{ - /* 11FSSOOD */ - unsigned slen, olen, dlen; - unsigned char *p = buf + 1; - - /* SS: Stream ID length: 1, 2, 3, or 4 bytes */ - slen = (stream_id > 0x0000FF) - + (stream_id > 0x00FFFF) - + (stream_id > 0xFFFFFF) - + 1; - - /* OO: Offset length: 0, 2, 4, or 8 bytes */ - olen = ((offset >= (1ULL << 32)) << 2) - + ((offset >= (1ULL << 16)) << 1) - + ((offset > 1) << 1) - ; - - if (!fin) - { - unsigned n_avail; - uint16_t nr; - - n_avail = buf_len - (p + slen + olen - buf); - - /* If we cannot fill remaining buffer, we need to include data - * length. - */ - dlen = (size < n_avail) << 1; - n_avail -= dlen; - - CHECK_SPACE(1 + olen + slen + dlen + - + 1 /* We need to write at least 1 byte */, buf, buf + buf_len); - -#if __BYTE_ORDER == __LITTLE_ENDIAN - stream_id = bswap_32(stream_id); -#endif - memcpy(p, (unsigned char *) &stream_id + 4 - slen, slen); - p += slen; - -#if __BYTE_ORDER == __LITTLE_ENDIAN - offset = bswap_64(offset); -#endif - memcpy(p, (unsigned char *) &offset + 8 - olen, olen); - p += olen; - - /* Read as much as we can */ - nr = gsf_read(stream, p + dlen, n_avail, &fin); - assert(nr != 0); - - if (dlen) - { - uint16_t nr_copy = nr; -#if __BYTE_ORDER == __LITTLE_ENDIAN - nr_copy = bswap_16(nr_copy); -#endif - memcpy(p, &nr_copy, 2); - } - - p += dlen + nr; - } - else - { - dlen = 2; - CHECK_SPACE(1 + slen + olen + 2, buf, buf + buf_len); -#if __BYTE_ORDER == __LITTLE_ENDIAN - stream_id = bswap_32(stream_id); -#endif - memcpy(p, (unsigned char *) &stream_id + 4 - slen, slen); - p += slen; -#if __BYTE_ORDER == __LITTLE_ENDIAN - offset = bswap_64(offset); -#endif - memcpy(p, (unsigned char *) &offset + 8 - olen, olen); - p += olen; - memset(p, 0, 2); - p += 2; - } - - /* Convert slen to bit representation: 0 - 3: */ - slen -= 1; - assert(slen <= 3); - - /* Convert olen to bit representation: 0 - 3: */ - olen >>= 1; - olen -= olen == 4; - assert(olen <= 3); - - buf[0] = 0xC0 - | (fin << 5) - | (slen << 3) - | (olen << 1) - | !!dlen - ; - return p - buf; -} - - -int -gquic_ietf_parse_ack_frame (const unsigned char *buf, size_t buf_len, - ack_info_t *ack) -{ - /* 101NLLMM */ - - lsquic_packno_t tmp_packno; - const unsigned char type = buf[0]; - const unsigned char *p = buf + 1; - const unsigned char *const pend = buf + buf_len; - uint8_t n_blocks, n_ts; - - assert((type & 0xE0) == 0xA0); /* We're passed correct frame type */ - - const int ack_block_len = twobit_to_1248(type & 3); /* MM */ - const int largest_obs_len = twobit_to_1248((type >> 2) & 3); /* LL */ - - if (type & 0x10) { /* N */ - CHECK_SPACE(2, p , pend); - n_blocks = *p++; - } - else - { - CHECK_SPACE(1, p , pend); - n_blocks = 0; - } - n_ts = *p++; - - const unsigned timestamps_size = - (n_ts > 0) * (1 + 4) + /* Delta LA, First Timestamp */ - (n_ts > 1) * (n_ts - 1) * (1 + 2); /* Delta LA, Time Since Previous */ - - CHECK_SPACE( - largest_obs_len + /* Largest Acknowledged */ - 2 + /* ACK delay */ - ack_block_len + /* First ACK block length */ - n_blocks * (1 + ack_block_len) + /* ACK blocks */ - timestamps_size - ,p , pend); - - READ_UINT(ack->ranges[0].high, 64, p, largest_obs_len); - p += largest_obs_len; - - ack->lack_delta = gquic_be_read_float_time16(p); - p += 2; - - READ_UINT(tmp_packno, 64, p, ack_block_len); - ack->ranges[0].low = ack->ranges[0].high - tmp_packno + 1; - p += ack_block_len; - - if (n_blocks) - { - unsigned i, n, gap; - for (i = 0, n = 1, gap = 0; i < n_blocks; ++i) - { - uint64_t length; - gap += *p; - READ_UINT(length, 64, p + 1, ack_block_len); - p += 1 + ack_block_len; - if (length) - { - ack->ranges[n].high = ack->ranges[n - 1].low - gap - 1; - ack->ranges[n].low = ack->ranges[n].high - length + 1; - ++n; - gap = 0; - } - } - ack->n_ranges = n; - } - else - ack->n_ranges = 1; - - ack->n_timestamps = n_ts; - if (n_ts) - { -#if LSQUIC_PARSE_ACK_TIMESTAMPS - /* TODO */ -#else - /* Just skip them for now */ - p += timestamps_size; -#endif - } - - assert(p <= pend); - - return p - (unsigned char *) buf; -} - - -/* This function makes an assumption that there is at least one range */ -int -gquic_ietf_gen_ack_frame (unsigned char *outbuf, size_t outbuf_sz, - gaf_rechist_first_f rechist_first, gaf_rechist_next_f rechist_next, - gaf_rechist_largest_recv_f rechist_largest_recv, - void *rechist, lsquic_time_t now, int *has_missing, - lsquic_packno_t *largest_received) -{ - lsquic_time_t time_diff; - lsquic_packno_t tmp_packno; - const struct lsquic_packno_range *const first = rechist_first(rechist); - if (!first) - { - errno = EINVAL; - return -1; - } - - /* Copy values from the first range, because the memory the pointer - * points to may change: - */ - const lsquic_packno_t first_low = first->low, first_high = first->high; - - unsigned char *p = outbuf; - unsigned char *const type = p; - unsigned char *const end = p + outbuf_sz; - unsigned char *n_ranges_p; - -#define AVAIL() (end - p) - -#define CHECKOUT(sz) do { \ - if ((intptr_t) (sz) > AVAIL()) { \ - errno = ENOBUFS; \ - return -1; \ - } \ -} while (0) - - CHECKOUT(1); - ++p; - - /* 101NLLMM */ - *type = 0xA0; - - unsigned largest_acked_len, ack_block_len, bits; - - /* Calculate largest ACKed len and set `LL' bits: */ - const lsquic_packno_t maxno = first_high; - bits = (maxno >= (1ULL << 8)) - + (maxno >= (1ULL << 16)) - + (maxno >= (1ULL << 32)); - largest_acked_len = twobit_to_1248(bits); - *type |= bits << 2; - - /* Calculate largest ACK block length and set `MM' bits: */ - unsigned n_ranges = 0; - lsquic_packno_t maxdiff = 0; - const struct lsquic_packno_range *range; - for (range = rechist_first(rechist); range; range = rechist_next(rechist)) - { - ++n_ranges; - const lsquic_packno_t diff = range->high - range->low + 1; - if (diff > maxdiff) - maxdiff = diff; - } - bits = (maxdiff >= (1ULL << 8)) - + (maxdiff >= (1ULL << 16)) - + (maxdiff >= (1ULL << 32)); - ack_block_len = twobit_to_1248(bits); - *type |= bits; - - if (n_ranges > 1) - { - CHECKOUT(2); - *type |= 0x10; /* N */ - n_ranges_p = p++; /* Set Num Blocks later */ - } - else - { - CHECKOUT(1); - n_ranges_p = NULL; - } - *p++ = 0; /* Do not provide any timestamps. TODO perhaps? */ - - CHECKOUT(largest_acked_len); - tmp_packno = maxno; -#if __BYTE_ORDER == __LITTLE_ENDIAN - tmp_packno = bswap_64(maxno); -#endif - memcpy(p, (unsigned char *) &tmp_packno + 8 - largest_acked_len, - largest_acked_len); - p += largest_acked_len; - - CHECKOUT(2); - time_diff = now - rechist_largest_recv(rechist); - gquic_be_write_float_time16(time_diff, p); - LSQ_DEBUG("%s: diff: %"PRIu64"; encoded: 0x%04X", __func__, time_diff, - *(uint16_t*)p); - p += 2; - - *has_missing = n_ranges > 1; - if (n_ranges > 1) - { - /* We need to write out at least one range */ - CHECKOUT(2 * (1 + ack_block_len)); - lsquic_packno_t diff = maxno - first_low + 1; -#if __BYTE_ORDER == __LITTLE_ENDIAN - diff = bswap_64(diff); -#endif - memcpy(p, (unsigned char *) &diff + 8 - ack_block_len, - ack_block_len); - p += ack_block_len; - /* Write out ack blocks until one of the following occurs: - * 1. We run out of intervals. - * 2. We run out of room. - * 3. We run out of highest possible number of ACK blocks (0xFF). - */ - range = rechist_first(rechist); - lsquic_packno_t gap = 0; - n_ranges = 0; - do { - if (0 == gap) - { - const lsquic_packno_t prev_low = range->low; - range = rechist_next(rechist); - if (!range) - break; - gap = prev_low - range->high - 1; - } - if (gap >= 0x100) - { - *p = 0xFF; - gap -= 0xFF; - memset(p + 1, 0, ack_block_len); - } - else - { - *p = gap; - gap = 0; - diff = range->high - range->low + 1; -#if __BYTE_ORDER == __LITTLE_ENDIAN - diff = bswap_64(diff); -#endif - memcpy(p + 1, (unsigned char *) &diff + 8 - ack_block_len, - ack_block_len); - } - p += ack_block_len + 1; - ++n_ranges; - } while (n_ranges < 0xFF && - AVAIL() >= (intptr_t) ack_block_len + 1 + 1 /* timestamp byte */); - *n_ranges_p = n_ranges; - } - else - { - CHECKOUT(ack_block_len); - lsquic_packno_t diff = maxno - first_low + 1; -#if __BYTE_ORDER == __LITTLE_ENDIAN - diff = bswap_64(diff); -#endif - memcpy(p, (unsigned char *) &diff + 8 - ack_block_len, ack_block_len); - p += ack_block_len; - } - - *largest_received = maxno; - return p - (unsigned char *) outbuf; - -#undef CHECKOUT -} - - -const struct parse_funcs lsquic_parse_funcs_gquic_Q041 = -{ - .pf_gen_ver_nego_pkt = gquic_be_gen_ver_nego_pkt, - .pf_gen_reg_pkt_header = gquic_be_gen_reg_pkt_header, - .pf_parse_packet_in_finish = gquic_be_parse_packet_in_finish, - .pf_gen_stream_frame = gquic_ietf_gen_stream_frame, - .pf_calc_stream_frame_header_sz = gquic_ietf_calc_stream_frame_header_sz, - .pf_parse_stream_frame_header_sz = gquic_ietf_parse_stream_frame_header_sz, - .pf_parse_stream_frame = gquic_ietf_parse_stream_frame, - .pf_parse_ack_frame = gquic_ietf_parse_ack_frame, - .pf_gen_ack_frame = gquic_ietf_gen_ack_frame, - .pf_gen_stop_waiting_frame = gquic_be_gen_stop_waiting_frame, - .pf_parse_stop_waiting_frame = gquic_be_parse_stop_waiting_frame, - .pf_skip_stop_waiting_frame = gquic_be_skip_stop_waiting_frame, - .pf_gen_window_update_frame = gquic_be_gen_window_update_frame, - .pf_parse_window_update_frame = gquic_be_parse_window_update_frame, - .pf_gen_blocked_frame = gquic_be_gen_blocked_frame, - .pf_parse_blocked_frame = gquic_be_parse_blocked_frame, - .pf_gen_rst_frame = gquic_ietf_gen_rst_frame, - .pf_parse_rst_frame = gquic_ietf_parse_rst_frame, - .pf_gen_connect_close_frame = gquic_be_gen_connect_close_frame, - .pf_parse_connect_close_frame = gquic_be_parse_connect_close_frame, - .pf_gen_goaway_frame = gquic_be_gen_goaway_frame, - .pf_parse_goaway_frame = gquic_be_parse_goaway_frame, - .pf_gen_ping_frame = gquic_be_gen_ping_frame, -#ifndef NDEBUG - .pf_write_float_time16 = gquic_be_write_float_time16, - .pf_read_float_time16 = gquic_be_read_float_time16, -#endif - .pf_parse_frame_type = parse_frame_type_gquic_Q041, - .pf_turn_on_fin = gquic_ietf_turn_on_fin, -};