mirror of
https://gitea.invidious.io/iv-org/litespeed-quic.git
synced 2024-08-15 00:53:43 +00:00
bfc7bfd842
- [API Change] lsquic_engine_connect() returns pointer to the connection object. - [API Change] Add lsquic_conn_get_engine() to get engine object from connection object. - [API Change] Add lsquic_conn_status() to query connection status. - [API Change] Add add lsquic_conn_set_ctx(). - [API Change] Add new timestamp format, e.g. 2017-03-21 13:43:46.671345 - [OPTIMIZATION] Process handshake STREAM frames as soon as packet arrives. - [OPTIMIZATION] Do not compile expensive send controller sanity check by default. - [OPTIMIZATION] Add fast path to gquic_be_gen_reg_pkt_header. - [OPTIMIZATION] Only make squeeze function call if necessary. - [OPTIMIZATION] Speed up Q039 ACK frame parsing. - [OPTIMIZATION] Fit most used elements of packet_out into first 64 bytes. - [OPTIMIZATION] Keep track of scheduled bytes instead of calculating. - [OPTIMIZATION] Prefetch next unacked packet when processing ACK. - [OPTIMIZATION] Leverage fact that ACK ranges and unacked list are. ordered. - [OPTIMIZATION] Reduce function pointer use for STREAM frame generation - Fix: reset incoming streams that arrive after we send GOAWAY. - Fix: delay client on_new_conn() call until connection is fully set up. - Fixes to buffered packets logic: splitting, STREAM frame elision. - Fix: do not dispatch on_write callback if no packets are available. - Fix WINDOW_UPDATE send and resend logic. - Fix STREAM frame extension code. - Fix: Drop unflushed data when stream is reset. - Switch to tracking CWND using bytes rather than packets. - Fix TCP friendly adjustment in cubic. - Fix: do not generate invalid STOP_WAITING frames during high packet loss. - Pacer fixes.
685 lines
25 KiB
C
685 lines
25 KiB
C
/* Copyright (c) 2017 LiteSpeed Technologies Inc. See LICENSE. */
|
|
#include <assert.h>
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <string.h>
|
|
#include <sys/time.h>
|
|
|
|
#include "lsquic_types.h"
|
|
#include "lsquic_alarmset.h"
|
|
#include "lsquic_parse.h"
|
|
#include "lsquic_packet_common.h"
|
|
#include "lsquic_packet_in.h"
|
|
#include "lsquic.h"
|
|
|
|
struct test {
|
|
const char *name;
|
|
int lineno;
|
|
const struct parse_funcs *
|
|
pf;
|
|
const unsigned char
|
|
buf[0x100]; /* Large enough for our needs */
|
|
size_t buf_sz; /* # of stream frame bytes in `buf' */
|
|
size_t rem_packet_sz; /* # of bytes remaining in the packet,
|
|
* starting at the beginning of the
|
|
* stream frame.
|
|
*/
|
|
stream_frame_t frame; /* Expected values */
|
|
int should_succeed;
|
|
};
|
|
|
|
static const struct test tests[] = {
|
|
|
|
/*
|
|
* Litte-endian tests;
|
|
*/
|
|
{ "Balls to the wall: every possible bit is set",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_037),
|
|
/* 1 f d ooo ss 1fdoooss */
|
|
/* TYPE FIN DLEN OLEN SLEN */
|
|
{ 0x80 | 0x40 | 0x20 | 0x1C | 0x3,
|
|
0x10, 0x02, 0x00, 0x00, /* Stream ID */
|
|
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, /* Offset */
|
|
0xC4, 0x01, /* Data length */
|
|
},
|
|
1 + 2 + 8 + 4,
|
|
0x200,
|
|
{ .data_frame.df_offset = 0x0807060504030201UL,
|
|
.stream_id = 0x210,
|
|
.data_frame.df_size = 0x1C4,
|
|
.data_frame.df_fin = 1,
|
|
},
|
|
1,
|
|
},
|
|
|
|
{ "Balls to the wall #2: every possible bit is set, except FIN",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_037),
|
|
/* 1 f d ooo ss 1fdoooss */
|
|
/* TYPE FIN DLEN OLEN SLEN */
|
|
{ 0x80 | 0x00 | 0x20 | 0x1C | 0x3,
|
|
0x10, 0x02, 0x00, 0x00, /* Stream ID */
|
|
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, /* Offset */
|
|
0xC4, 0x01, /* Data length */
|
|
},
|
|
1 + 2 + 8 + 4,
|
|
0x200,
|
|
{ .data_frame.df_offset = 0x0807060504030201UL,
|
|
.stream_id = 0x210,
|
|
.data_frame.df_size = 0x1C4,
|
|
.data_frame.df_fin = 0,
|
|
},
|
|
1,
|
|
},
|
|
|
|
{ "Data length is zero",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_037),
|
|
/* 1 f d ooo ss 1fdoooss */
|
|
/* TYPE FIN DLEN OLEN SLEN */
|
|
{ 0x80 | 0x40 | 0x00 | 0x1C | 0x3,
|
|
0x10, 0x02, 0x00, 0x00, /* Stream ID */
|
|
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, /* Offset */
|
|
0xC4, 0x01, /* Data length */
|
|
},
|
|
1 + 0 + 8 + 4,
|
|
0x200,
|
|
{ .data_frame.df_offset = 0x0807060504030201UL,
|
|
.stream_id = 0x210,
|
|
.data_frame.df_size = 0x200 - (1 + 8 + 4),
|
|
.data_frame.df_fin = 1,
|
|
},
|
|
1,
|
|
},
|
|
|
|
{ "Stream ID length is 1",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_037),
|
|
/* 1 f d ooo ss 1fdoooss */
|
|
/* TYPE FIN DLEN OLEN SLEN */
|
|
{ 0x80 | 0x40 | 0x20 | 0x1C | 0x0,
|
|
0xF0, /* Stream ID */
|
|
0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, /* Offset */
|
|
0xC4, 0x01, /* Data length */
|
|
},
|
|
1 + 2 + 8 + 1,
|
|
0x200,
|
|
{ .data_frame.df_offset = 0x0807060504030201UL,
|
|
.stream_id = 0xF0,
|
|
.data_frame.df_size = 0x1C4,
|
|
.data_frame.df_fin = 1,
|
|
},
|
|
1,
|
|
},
|
|
|
|
{ "All bits are zero save offset length",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_037),
|
|
/* 1 f d ooo ss 1fdoooss */
|
|
/* TYPE FIN DLEN OLEN SLEN */
|
|
{ 0x80 | 0x00 | 0x00 | 0x04 | 0x0,
|
|
0xF0, /* Stream ID */
|
|
0x55, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, /* Offset */
|
|
0xC4, 0x01, /* Data length */
|
|
},
|
|
1 + 0 + 2 + 1,
|
|
0x200,
|
|
{ .data_frame.df_offset = 0x255,
|
|
.stream_id = 0xF0,
|
|
.data_frame.df_size = 0x200 - 4,
|
|
.data_frame.df_fin = 0,
|
|
},
|
|
1,
|
|
},
|
|
|
|
{ "Sanity check: either FIN must be set or data length is not zero #1",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_037),
|
|
/* 1 f d ooo ss 1fdoooss */
|
|
/* TYPE FIN DLEN OLEN SLEN */
|
|
{ 0x80 | 0x00 | 0x00 | 0x04 | 0x0,
|
|
0xF0, /* Stream ID */
|
|
0x55, 0x02, /* Offset */
|
|
},
|
|
1 + 0 + 2 + 1,
|
|
4, /* Same as buffer size: in the absense of explicit data
|
|
* length in the header, this would mean that data
|
|
* length is zero.
|
|
*/
|
|
{ .data_frame.df_offset = 0x255,
|
|
.stream_id = 0xF0,
|
|
.data_frame.df_size = 0x200 - 4,
|
|
.data_frame.df_fin = 0,
|
|
},
|
|
0,
|
|
},
|
|
|
|
{ "Sanity check: either FIN must be set or data length is not zero #2",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_037),
|
|
/* 1 f d ooo ss 1fdoooss */
|
|
/* TYPE FIN DLEN OLEN SLEN */
|
|
{ 0x80 | 0x00 | 0x20 | 0x04 | 0x0,
|
|
0xF0, /* Stream ID */
|
|
0x55, 0x02, /* Offset */
|
|
0x00, 0x00,
|
|
},
|
|
1 + 2 + 2 + 1,
|
|
200,
|
|
{ .data_frame.df_offset = 0x255,
|
|
.stream_id = 0xF0,
|
|
.data_frame.df_size = 0x200 - 4,
|
|
.data_frame.df_fin = 0,
|
|
},
|
|
0,
|
|
},
|
|
|
|
{ "Sanity check: either FIN must be set or data length is not zero #3",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_037),
|
|
/* 1 f d ooo ss 1fdoooss */
|
|
/* TYPE FIN DLEN OLEN SLEN */
|
|
{ 0x80 | 0x40 | 0x20 | 0x04 | 0x0,
|
|
0xF0, /* Stream ID */
|
|
0x55, 0x02, /* Offset */
|
|
0x00, 0x00,
|
|
},
|
|
1 + 2 + 2 + 1,
|
|
200,
|
|
{ .data_frame.df_offset = 0x255,
|
|
.stream_id = 0xF0,
|
|
.data_frame.df_size = 0x0,
|
|
.data_frame.df_fin = 1,
|
|
},
|
|
1,
|
|
},
|
|
|
|
{ "Check data bounds #1",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_037),
|
|
/* 1 f d ooo ss 1fdoooss */
|
|
/* TYPE FIN DLEN OLEN SLEN */
|
|
{ 0x80 | 0x00 | 0x20 | 0x04 | 0x0,
|
|
0xF0, /* Stream ID */
|
|
0x55, 0x02, /* Offset */
|
|
0xFA, 0x01, /* Data length */
|
|
},
|
|
1 + 2 + 2 + 1,
|
|
0x200,
|
|
{ .data_frame.df_offset = 0x255,
|
|
.stream_id = 0xF0,
|
|
.data_frame.df_size = 0x1FA,
|
|
.data_frame.df_fin = 0,
|
|
},
|
|
1,
|
|
},
|
|
|
|
{ "Check data bounds #2",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_037),
|
|
/* 1 f d ooo ss 1fdoooss */
|
|
/* TYPE FIN DLEN OLEN SLEN */
|
|
{ 0x80 | 0x00 | 0x20 | 0x04 | 0x0,
|
|
0xF0, /* Stream ID */
|
|
0x55, 0x02, /* Offset */
|
|
0xFB, 0x01, /* <--- One byte too many */
|
|
},
|
|
1 + 2 + 2 + 1,
|
|
0x200,
|
|
{ .data_frame.df_offset = 0x255,
|
|
.stream_id = 0xF0,
|
|
.data_frame.df_size = 0x1FA,
|
|
.data_frame.df_fin = 0,
|
|
},
|
|
0,
|
|
},
|
|
|
|
/*
|
|
* Big-endian tests
|
|
*/
|
|
{ "Balls to the wall: every possible bit is set",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_039),
|
|
/* 1 f d ooo ss 1fdoooss */
|
|
/* TYPE FIN DLEN OLEN SLEN */
|
|
{ 0x80 | 0x40 | 0x20 | 0x1C | 0x3,
|
|
0x00, 0x00, 0x02, 0x10, /* Stream ID */
|
|
0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, /* Offset */
|
|
0x01, 0xC4, /* Data length */
|
|
},
|
|
1 + 2 + 8 + 4,
|
|
0x200,
|
|
{ .data_frame.df_offset = 0x0807060504030201UL,
|
|
.stream_id = 0x210,
|
|
.data_frame.df_size = 0x1C4,
|
|
.data_frame.df_fin = 1,
|
|
},
|
|
1,
|
|
},
|
|
|
|
{ "Balls to the wall #2: every possible bit is set, except FIN",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_039),
|
|
/* 1 f d ooo ss 1fdoooss */
|
|
/* TYPE FIN DLEN OLEN SLEN */
|
|
{ 0x80 | 0x00 | 0x20 | 0x1C | 0x3,
|
|
0x00, 0x00, 0x02, 0x10, /* Stream ID */
|
|
0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, /* Offset */
|
|
0x01, 0xC4, /* Data length */
|
|
},
|
|
1 + 2 + 8 + 4,
|
|
0x200,
|
|
{ .data_frame.df_offset = 0x0807060504030201UL,
|
|
.stream_id = 0x210,
|
|
.data_frame.df_size = 0x1C4,
|
|
.data_frame.df_fin = 0,
|
|
},
|
|
1,
|
|
},
|
|
|
|
{ "Data length is zero",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_039),
|
|
/* 1 f d ooo ss 1fdoooss */
|
|
/* TYPE FIN DLEN OLEN SLEN */
|
|
{ 0x80 | 0x40 | 0x00 | 0x1C | 0x3,
|
|
0x00, 0x00, 0x02, 0x10, /* Stream ID */
|
|
0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, /* Offset */
|
|
0xC4, 0x01, /* Data length: note this does not matter */
|
|
},
|
|
1 + 0 + 8 + 4,
|
|
0x200,
|
|
{ .data_frame.df_offset = 0x0807060504030201UL,
|
|
.stream_id = 0x210,
|
|
.data_frame.df_size = 0x200 - (1 + 8 + 4),
|
|
.data_frame.df_fin = 1,
|
|
},
|
|
1,
|
|
},
|
|
|
|
{ "Stream ID length is 1",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_039),
|
|
/* 1 f d ooo ss 1fdoooss */
|
|
/* TYPE FIN DLEN OLEN SLEN */
|
|
{ 0x80 | 0x40 | 0x20 | 0x1C | 0x0,
|
|
0xF0, /* Stream ID */
|
|
0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, /* Offset */
|
|
0x01, 0xC4, /* Data length */
|
|
},
|
|
1 + 2 + 8 + 1,
|
|
0x200,
|
|
{ .data_frame.df_offset = 0x0807060504030201UL,
|
|
.stream_id = 0xF0,
|
|
.data_frame.df_size = 0x1C4,
|
|
.data_frame.df_fin = 1,
|
|
},
|
|
1,
|
|
},
|
|
|
|
{ "All bits are zero save offset length",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_039),
|
|
/* 1 f d ooo ss 1fdoooss */
|
|
/* TYPE FIN DLEN OLEN SLEN */
|
|
{ 0x80 | 0x00 | 0x00 | 0x04 | 0x0,
|
|
0xF0, /* Stream ID */
|
|
0x02, 0x55, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, /* Offset */
|
|
0xC4, 0x01, /* Data length */
|
|
},
|
|
1 + 0 + 2 + 1,
|
|
0x200,
|
|
{ .data_frame.df_offset = 0x255,
|
|
.stream_id = 0xF0,
|
|
.data_frame.df_size = 0x200 - 4,
|
|
.data_frame.df_fin = 0,
|
|
},
|
|
1,
|
|
},
|
|
|
|
{ "Sanity check: either FIN must be set or data length is not zero #1",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_039),
|
|
/* 1 f d ooo ss 1fdoooss */
|
|
/* TYPE FIN DLEN OLEN SLEN */
|
|
{ 0x80 | 0x00 | 0x00 | 0x04 | 0x0,
|
|
0xF0, /* Stream ID */
|
|
0x02, 0x55, /* Offset */
|
|
},
|
|
1 + 0 + 2 + 1,
|
|
4, /* Same as buffer size: in the absense of explicit data
|
|
* length in the header, this would mean that data
|
|
* length is zero.
|
|
*/
|
|
{ .data_frame.df_offset = 0x255,
|
|
.stream_id = 0xF0,
|
|
.data_frame.df_size = 0x200 - 4,
|
|
.data_frame.df_fin = 0,
|
|
},
|
|
0,
|
|
},
|
|
|
|
{ "Sanity check: either FIN must be set or data length is not zero #2",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_039),
|
|
/* 1 f d ooo ss 1fdoooss */
|
|
/* TYPE FIN DLEN OLEN SLEN */
|
|
{ 0x80 | 0x00 | 0x20 | 0x04 | 0x0,
|
|
0xF0, /* Stream ID */
|
|
0x02, 0x55, /* Offset */
|
|
0x00, 0x00,
|
|
},
|
|
1 + 2 + 2 + 1,
|
|
200,
|
|
{ .data_frame.df_offset = 0x255,
|
|
.stream_id = 0xF0,
|
|
.data_frame.df_size = 0x200 - 4,
|
|
.data_frame.df_fin = 0,
|
|
},
|
|
0,
|
|
},
|
|
|
|
{ "Sanity check: either FIN must be set or data length is not zero #3",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_039),
|
|
/* 1 f d ooo ss 1fdoooss */
|
|
/* TYPE FIN DLEN OLEN SLEN */
|
|
{ 0x80 | 0x40 | 0x20 | 0x04 | 0x0,
|
|
0xF0, /* Stream ID */
|
|
0x02, 0x55, /* Offset */
|
|
0x00, 0x00,
|
|
},
|
|
1 + 2 + 2 + 1,
|
|
200,
|
|
{ .data_frame.df_offset = 0x255,
|
|
.stream_id = 0xF0,
|
|
.data_frame.df_size = 0x0,
|
|
.data_frame.df_fin = 1,
|
|
},
|
|
1,
|
|
},
|
|
|
|
{ "Check data bounds #1",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_039),
|
|
/* 1 f d ooo ss 1fdoooss */
|
|
/* TYPE FIN DLEN OLEN SLEN */
|
|
{ 0x80 | 0x00 | 0x20 | 0x04 | 0x0,
|
|
0xF0, /* Stream ID */
|
|
0x02, 0x55, /* Offset */
|
|
0x01, 0xFA, /* Data length */
|
|
},
|
|
1 + 2 + 2 + 1,
|
|
0x200,
|
|
{ .data_frame.df_offset = 0x255,
|
|
.stream_id = 0xF0,
|
|
.data_frame.df_size = 0x1FA,
|
|
.data_frame.df_fin = 0,
|
|
},
|
|
1,
|
|
},
|
|
|
|
{ "Check data bounds #2",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_039),
|
|
/* 1 f d ooo ss 1fdoooss */
|
|
/* TYPE FIN DLEN OLEN SLEN */
|
|
{ 0x80 | 0x00 | 0x20 | 0x04 | 0x0,
|
|
0xF0, /* Stream ID */
|
|
0x02, 0x55, /* Offset */
|
|
0x01, 0xFB, /* <--- One byte too many */
|
|
},
|
|
1 + 2 + 2 + 1,
|
|
0x200,
|
|
{ .data_frame.df_offset = 0x255,
|
|
.stream_id = 0xF0,
|
|
.data_frame.df_size = 0x1FA,
|
|
.data_frame.df_fin = 0,
|
|
},
|
|
0,
|
|
},
|
|
|
|
/*
|
|
* GQUIC IETF tests
|
|
*/
|
|
{ "Balls to the wall: every possible bit is set",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_041),
|
|
/* 11 F SS OO D 11FSSOOD */
|
|
/* TYPE FIN SLEN OLEN DLEN */
|
|
{ 0xC0 | 1 << 5 | 3 << 3 | 3 << 1 | 1,
|
|
0x00, 0x00, 0x02, 0x10, /* Stream ID */
|
|
0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, /* Offset */
|
|
0x01, 0xC4, /* Data length */
|
|
},
|
|
1 + 4 + 8 + 2,
|
|
0x200,
|
|
{ .data_frame.df_offset = 0x0807060504030201UL,
|
|
.stream_id = 0x210,
|
|
.data_frame.df_size = 0x1C4,
|
|
.data_frame.df_fin = 1,
|
|
},
|
|
1,
|
|
},
|
|
|
|
{ "Balls to the wall #2: every possible bit is set, except FIN",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_041),
|
|
/* 11 F SS OO D 11FSSOOD */
|
|
/* TYPE FIN SLEN OLEN DLEN */
|
|
{ 0xC0 | 0 << 5 | 3 << 3 | 3 << 1 | 1,
|
|
0x00, 0x00, 0x02, 0x10, /* Stream ID */
|
|
0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, /* Offset */
|
|
0x01, 0xC4, /* Data length */
|
|
},
|
|
1 + 4 + 8 + 2,
|
|
0x200,
|
|
{ .data_frame.df_offset = 0x0807060504030201UL,
|
|
.stream_id = 0x210,
|
|
.data_frame.df_size = 0x1C4,
|
|
.data_frame.df_fin = 0,
|
|
},
|
|
1,
|
|
},
|
|
|
|
{ "Data length is zero",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_041),
|
|
/* 11 F SS OO D 11FSSOOD */
|
|
/* TYPE FIN SLEN OLEN DLEN */
|
|
{ 0xC0 | 1 << 5 | 3 << 3 | 3 << 1 | 0,
|
|
0x00, 0x00, 0x02, 0x10, /* Stream ID */
|
|
0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, /* Offset */
|
|
0xC4, 0x01, /* Data length: note this does not matter */
|
|
},
|
|
1 + 4 + 8 + 0,
|
|
0x200,
|
|
{ .data_frame.df_offset = 0x0807060504030201UL,
|
|
.stream_id = 0x210,
|
|
.data_frame.df_size = 0x200 - (1 + 8 + 4),
|
|
.data_frame.df_fin = 1,
|
|
},
|
|
1,
|
|
},
|
|
|
|
{ "Stream ID length is 1",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_041),
|
|
/* 11 F SS OO D 11FSSOOD */
|
|
/* TYPE FIN SLEN OLEN DLEN */
|
|
{ 0xC0 | 1 << 5 | 0 << 3 | 3 << 1 | 1,
|
|
0xF0, /* Stream ID */
|
|
0x08, 0x07, 0x06, 0x05, 0x04, 0x03, 0x02, 0x01, /* Offset */
|
|
0x01, 0xC4, /* Data length */
|
|
},
|
|
1 + 1 + 8 + 2,
|
|
0x200,
|
|
{ .data_frame.df_offset = 0x0807060504030201UL,
|
|
.stream_id = 0xF0,
|
|
.data_frame.df_size = 0x1C4,
|
|
.data_frame.df_fin = 1,
|
|
},
|
|
1,
|
|
},
|
|
|
|
{ "All bits are zero save offset length",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_041),
|
|
/* 11 F SS OO D 11FSSOOD */
|
|
/* TYPE FIN SLEN OLEN DLEN */
|
|
{ 0xC0 | 0 << 5 | 0 << 3 | 1 << 1 | 0,
|
|
0xF0, /* Stream ID */
|
|
0x02, 0x55, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, /* Offset */
|
|
0xC4, 0x01, /* Data length */
|
|
},
|
|
1 + 1 + 2 + 0,
|
|
0x200,
|
|
{ .data_frame.df_offset = 0x255,
|
|
.stream_id = 0xF0,
|
|
.data_frame.df_size = 0x200 - 4,
|
|
.data_frame.df_fin = 0,
|
|
},
|
|
1,
|
|
},
|
|
|
|
{ "Sanity check: either FIN must be set or data length is not zero #1",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_041),
|
|
/* 11 F SS OO D 11FSSOOD */
|
|
/* TYPE FIN SLEN OLEN DLEN */
|
|
{ 0xC0 | 0 << 5 | 0 << 3 | 1 << 1 | 0,
|
|
0xF0, /* Stream ID */
|
|
0x02, 0x55, /* Offset */
|
|
},
|
|
1 + 1 + 2 + 0,
|
|
4, /* Same as buffer size: in the absense of explicit data
|
|
* length in the header, this would mean that data
|
|
* length is zero.
|
|
*/
|
|
{ .data_frame.df_offset = 0x255,
|
|
.stream_id = 0xF0,
|
|
.data_frame.df_size = 0x200 - 4,
|
|
.data_frame.df_fin = 0,
|
|
},
|
|
0,
|
|
},
|
|
|
|
{ "Sanity check: either FIN must be set or data length is not zero #2",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_041),
|
|
/* 11 F SS OO D 11FSSOOD */
|
|
/* TYPE FIN SLEN OLEN DLEN */
|
|
{ 0xC0 | 0 << 5 | 0 << 3 | 1 << 1 | 1,
|
|
0xF0, /* Stream ID */
|
|
0x02, 0x55, /* Offset */
|
|
0x00, 0x00,
|
|
},
|
|
1 + 1 + 2 + 2,
|
|
200,
|
|
{ .data_frame.df_offset = 0x255,
|
|
.stream_id = 0xF0,
|
|
.data_frame.df_size = 0x200 - 4,
|
|
.data_frame.df_fin = 0,
|
|
},
|
|
0,
|
|
},
|
|
|
|
{ "Sanity check: either FIN must be set or data length is not zero #3",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_041),
|
|
/* 11 F SS OO D 11FSSOOD */
|
|
/* TYPE FIN SLEN OLEN DLEN */
|
|
{ 0xC0 | 1 << 5 | 0 << 3 | 1 << 1 | 1,
|
|
0xF0, /* Stream ID */
|
|
0x02, 0x55, /* Offset */
|
|
0x00, 0x00,
|
|
},
|
|
1 + 1 + 2 + 2,
|
|
200,
|
|
{ .data_frame.df_offset = 0x255,
|
|
.stream_id = 0xF0,
|
|
.data_frame.df_size = 0x0,
|
|
.data_frame.df_fin = 1,
|
|
},
|
|
1,
|
|
},
|
|
|
|
{ "Check data bounds #1",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_041),
|
|
/* 11 F SS OO D 11FSSOOD */
|
|
/* TYPE FIN SLEN OLEN DLEN */
|
|
{ 0xC0 | 0 << 5 | 0 << 3 | 1 << 1 | 1,
|
|
0xF0, /* Stream ID */
|
|
0x02, 0x55, /* Offset */
|
|
0x01, 0xFA, /* Data length */
|
|
},
|
|
1 + 1 + 2 + 2,
|
|
0x200,
|
|
{ .data_frame.df_offset = 0x255,
|
|
.stream_id = 0xF0,
|
|
.data_frame.df_size = 0x1FA,
|
|
.data_frame.df_fin = 0,
|
|
},
|
|
1,
|
|
},
|
|
|
|
{ "Check data bounds #2",
|
|
__LINE__,
|
|
select_pf_by_ver(LSQVER_041),
|
|
/* 11 F SS OO D 11FSSOOD */
|
|
/* TYPE FIN SLEN OLEN DLEN */
|
|
{ 0xC0 | 0 << 5 | 0 << 3 | 1 << 1 | 1,
|
|
0xF0, /* Stream ID */
|
|
0x02, 0x55, /* Offset */
|
|
0x01, 0xFB, /* <--- One byte too many */
|
|
},
|
|
1 + 1 + 2 + 2,
|
|
0x200,
|
|
{ .data_frame.df_offset = 0x255,
|
|
.stream_id = 0xF0,
|
|
.data_frame.df_size = 0x1FA,
|
|
.data_frame.df_fin = 0,
|
|
},
|
|
0,
|
|
},
|
|
|
|
};
|
|
|
|
|
|
static void
|
|
run_test (const struct test *test)
|
|
{
|
|
stream_frame_t frame;
|
|
memset(&frame, 0x7A, sizeof(frame));
|
|
|
|
int len = test->pf->pf_parse_stream_frame(test->buf, test->rem_packet_sz, &frame);
|
|
|
|
if (test->should_succeed) {
|
|
/* Check parser operation */
|
|
assert(("Parsed correct number of bytes", (size_t) len == test->buf_sz + test->frame.data_frame.df_size));
|
|
assert(("Stream ID is correct", frame.stream_id == test->frame.stream_id));
|
|
assert(("Data length is correct", frame.data_frame.df_size == test->frame.data_frame.df_size));
|
|
assert(("Offset is correct", frame.data_frame.df_offset == test->frame.data_frame.df_offset));
|
|
assert(("FIN is correct", frame.data_frame.df_fin == test->frame.data_frame.df_fin));
|
|
|
|
/* Check that initialization of other fields occurred correctly: */
|
|
assert(0 == frame.packet_in);
|
|
assert(0 == frame.data_frame.df_read_off);
|
|
}
|
|
else
|
|
{
|
|
assert(("This test should fail", len < 0));
|
|
}
|
|
}
|
|
|
|
|
|
int
|
|
main (void)
|
|
{
|
|
unsigned i;
|
|
for (i = 0; i < sizeof(tests) / sizeof(tests[0]); ++i)
|
|
run_test(&tests[i]);
|
|
return 0;
|
|
}
|