n_http2 regression: frame codec, SETTINGS, and HPACK (RFC 7541 vectors).
n_http2 regression: frame codec, SETTINGS, and HPACK (RFC 7541 vectors).
#include <getopt.h>
#include <stdlib.h>
#include <string.h>
unsigned char buf[64];
size_t consumed = 0, w;
memcpy(buf + w, "hello", 5);
buf[5] = (unsigned char)(buf[5] | 0x80);
}
unsigned char buf[16];
size_t consumed = 0;
buf[0] = 0xFF;
buf[1] = 0xFF;
buf[2] = 0xFF;
}
unsigned char pay[12];
size_t count = 0;
pay[0] = 0x00;
pay[2] = 0x00;
pay[3] = 0x00;
pay[4] = 0x00;
pay[5] = 100;
pay[6] = 0x00;
pay[8] = 0x00;
pay[9] = 0x00;
pay[10] = 0xFF;
pay[11] = 0xFF;
}
}
size_t i;
for (i = 0; i < n; i++)
if (h[i].name && strcmp(h[i].name, name) == 0)
return NULL;
}
char big[301];
unsigned char buf[1024];
size_t w, count = 0;
memset(big, 'x', 300);
big[300] = '\0';
in[0].
name = (
char*)
":method";
in[0].
value = (
char*)
"GET";
in[1].
name = (
char*)
":path";
in[1].
value = (
char*)
"/a/b?c=d";
in[2].
name = (
char*)
"x-custom";
in[2].
value = (
char*)
"hello world";
in[3].
name = (
char*)
"x-big";
}
static const unsigned char r1[] = {0x82, 0x86, 0x84, 0x41, 0x0f, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d};
static const unsigned char r2[] = {0x82, 0x86, 0x84, 0xbe, 0x58, 0x08, 0x6e, 0x6f, 0x2d, 0x63, 0x61, 0x63, 0x68, 0x65};
static const unsigned char r3[] = {0x82, 0x87, 0x85, 0xbf, 0x40, 0x0a, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x6b, 0x65, 0x79, 0x0c, 0x63, 0x75, 0x73, 0x74, 0x6f, 0x6d, 0x2d, 0x76, 0x61, 0x6c, 0x75, 0x65};
size_t count = 0;
if (!
find_hdr(out, count,
":authority") || strcmp(
find_hdr(out, count,
":authority"),
"www.example.com") != 0)
failures++;
if (!
find_hdr(out, count,
":authority") || strcmp(
find_hdr(out, count,
":authority"),
"www.example.com") != 0)
failures++;
if (!
find_hdr(out, count,
"cache-control") || strcmp(
find_hdr(out, count,
"cache-control"),
"no-cache") != 0)
failures++;
}
static const unsigned char req[] = {0x82, 0x86, 0x84, 0x41, 0x8c, 0xf1, 0xe3, 0xc2, 0xe5, 0xf2, 0x3a, 0x6b, 0xa0, 0xab, 0x90, 0xf4, 0xff};
static const unsigned char resp[] = {
0x48, 0x82, 0x64, 0x02, 0x58, 0x85, 0xae, 0xc3, 0x77, 0x1a, 0x4b, 0x61, 0x96, 0xd0, 0x7a, 0xbe,
0x94, 0x10, 0x54, 0xd4, 0x44, 0xa8, 0x20, 0x05, 0x95, 0x04, 0x0b, 0x81, 0x66, 0xe0, 0x82, 0xa6,
0x2d, 0x1b, 0xff, 0x6e, 0x91, 0x9d, 0x29, 0xad, 0x17, 0x18, 0x63, 0xc7, 0x8f, 0x0b, 0x97, 0xc8,
0xe9, 0xae, 0x82, 0xae, 0x43, 0xd3};
size_t count = 0;
if (!
find_hdr(out, count,
":authority") || strcmp(
find_hdr(out, count,
":authority"),
"www.example.com") != 0)
failures++;
if (!
find_hdr(out, count,
"cache-control") || strcmp(
find_hdr(out, count,
"cache-control"),
"private") != 0)
failures++;
if (!
find_hdr(out, count,
"date") || strcmp(
find_hdr(out, count,
"date"),
"Mon, 21 Oct 2013 20:13:21 GMT") != 0)
failures++;
if (!
find_hdr(out, count,
"location") || strcmp(
find_hdr(out, count,
"location"),
"https://www.example.com") != 0)
failures++;
}
static const unsigned char r1[] = {0x82, 0x86, 0x84, 0x41, 0x0f, 0x77, 0x77, 0x77, 0x2e, 0x65, 0x78, 0x61, 0x6d, 0x70, 0x6c, 0x65, 0x2e, 0x63, 0x6f, 0x6d};
size_t count = 123;
}
static const unsigned char bad_index[] = {0x80};
static const unsigned char truncated[] = {0x40, 0x05, 0x61};
size_t count = 0;
}
int opt = 0;
while ((opt = getopt(argc, argv, "hvV:")) != EOF) {
switch (opt) {
case 'V':
if (!strncmp("LOG_NULL", optarg, 8))
else if (!strncmp("LOG_NOTICE", optarg, 10))
else if (!strncmp("LOG_INFO", optarg, 8))
else if (!strncmp("LOG_ERR", optarg, 7))
else if (!strncmp("LOG_DEBUG", optarg, 9))
break;
case 'v':
fprintf(stderr, "ex_http2\n");
exit(1);
default:
break;
}
}
}
int main(
int argc,
char** argv) {
return 1;
}
return 0;
}
void process_args(int argc, char **argv)
static void test_hpack_rfc_huffman(void)
static void test_hpack_roundtrip(void)
static void test_roundtrip(void)
static void test_settings(void)
static const char * find_hdr(const N_H2_HEADER *h, size_t n, const char *name)
static void test_preface(void)
static void test_boundaries(void)
static void test_hpack_guards(void)
static void test_hpack_overflow(void)
static void test_hpack_rfc_requests(void)
#define n_log(__LEVEL__,...)
Logging function wrapper to get line and func.
#define LOG_DEBUG
debug-level messages
#define LOG_ERR
error conditions
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL )
#define LOG_NOTICE
normal but significant condition
#define LOG_NULL
no log output
#define LOG_INFO
informational
int n_http2_hpack_decode(N_H2_HPACK *ctx, const unsigned char *block, size_t len, N_H2_HEADER *out, size_t max_out, size_t *count)
decode an HPACK header block into out[] (owned name/value strings).
size_t n_http2_hpack_encode(const N_H2_HEADER *headers, size_t n, unsigned char *out, size_t out_cap)
encode a header list into a block using literal representations without indexing and without Huffman ...
N_H2_HPACK * n_http2_hpack_new(size_t max_table_size)
create an HPACK codec context with the given dynamic table size limit (0 uses N_H2_HPACK_DEFAULT_TABL...
void n_http2_hpack_free(N_H2_HPACK **pctx)
free an HPACK codec context and NULL the caller's pointer
void n_http2_hpack_headers_free(N_H2_HEADER *headers, size_t n)
free the owned name/value strings of a decoded header array (does not free the array itself)
int n_http2_settings_parse(const unsigned char *payload, size_t len, N_H2_SETTING *out, size_t max, size_t *count)
parse a SETTINGS frame payload (6-byte id/value entries) into out.
int n_http2_frame_parse(const unsigned char *buf, size_t len, N_H2_FRAME *frame, size_t *consumed)
parse one HTTP/2 frame from a byte buffer (stateless).
size_t n_http2_frame_build_header(unsigned char *out, size_t out_cap, uint32_t length, int type, int flags, uint32_t stream_id)
write a 9-byte HTTP/2 frame header into out.
HPACK codec context: the dynamic table (index 0 = most recently added)
HTTP/2 (RFC 7540) wire framing plus HPACK header compression (RFC 7541)
char * value
header field value (owned after decode)
#define N_H2_PREFACE
the client connection preface sent before any HTTP/2 frame (RFC 7540 3.5)
#define N_H2_FLAG_END_HEADERS
HEADERS/PUSH_PROMISE/CONTINUATION: header block complete.
#define N_H2_FRAME_HEADER_LEN
length of the fixed frame header in bytes
char * name
header field name (owned after decode)
#define N_H2_SETTINGS_INITIAL_WINDOW_SIZE
#define N_H2_WINDOW_UPDATE
WINDOW_UPDATE.
uint32_t length
payload length (24-bit)
const unsigned char * payload
pointer into the input buffer (may be NULL when length is 0)
int type
frame type (N_H2_*)
uint32_t stream_id
stream identifier (31-bit; the reserved bit is cleared)
#define N_H2_HEADERS
HEADERS.
#define N_H2_FLAG_END_STREAM
DATA/HEADERS: last frame of the stream.
#define N_H2_SETTINGS_MAX_CONCURRENT_STREAMS
a parsed HTTP/2 frame; payload aliases the input buffer
one HPACK header field; after a decode both strings are owned (heap)
one SETTINGS parameter (identifier and value)