Implement header compression draft 01
This commit is contained in:
parent
257bc1c924
commit
45c2245bfb
|
@ -36,14 +36,16 @@ OBJECTS = nghttp2_pq.c nghttp2_map.c nghttp2_queue.c \
|
|||
nghttp2_stream.c nghttp2_outbound_item.c \
|
||||
nghttp2_session.c nghttp2_submit.c \
|
||||
nghttp2_helper.c \
|
||||
nghttp2_npn.c nghttp2_gzip.c
|
||||
nghttp2_npn.c nghttp2_gzip.c \
|
||||
nghttp2_hd.c
|
||||
|
||||
HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \
|
||||
nghttp2_buffer.h nghttp2_frame.h nghttp2_zlib.h \
|
||||
nghttp2_session.h nghttp2_helper.h nghttp2_stream.h nghttp2_int.h \
|
||||
nghttp2_npn.h nghttp2_gzip.h \
|
||||
nghttp2_submit.h nghttp2_outbound_item.h \
|
||||
nghttp2_net.h
|
||||
nghttp2_net.h \
|
||||
nghttp2_hd.h
|
||||
|
||||
libnghttp2_la_SOURCES = $(HFILES) $(OBJECTS)
|
||||
libnghttp2_la_LDFLAGS = -no-undefined \
|
||||
|
|
|
@ -155,6 +155,10 @@ typedef enum {
|
|||
* The length of the frame is too large.
|
||||
*/
|
||||
NGHTTP2_ERR_FRAME_TOO_LARGE = -522,
|
||||
/**
|
||||
* Header block inflate/deflate error.
|
||||
*/
|
||||
NGHTTP2_ERR_HEADER_COMP = -523,
|
||||
/**
|
||||
* The errors < :enum:`NGHTTP2_ERR_FATAL` mean that the library is
|
||||
* under unexpected condition and cannot process any further data
|
||||
|
@ -175,6 +179,31 @@ typedef enum {
|
|||
NGHTTP2_MSG_MORE
|
||||
} nghttp2_io_flag;
|
||||
|
||||
/**
|
||||
* @struct
|
||||
*
|
||||
* The name/value pair, which mainly used to represent header fields.
|
||||
*/
|
||||
typedef struct {
|
||||
/**
|
||||
* The |name| byte string, which is not necessarily NULL terminated.
|
||||
*/
|
||||
uint8_t *name;
|
||||
/**
|
||||
* The |value| byte string, which is not necessarily NULL
|
||||
* terminated.
|
||||
*/
|
||||
uint8_t *value;
|
||||
/**
|
||||
* The length of the |name|.
|
||||
*/
|
||||
uint16_t namelen;
|
||||
/**
|
||||
* The length of the |value|.
|
||||
*/
|
||||
uint16_t valuelen;
|
||||
} nghttp2_nv;
|
||||
|
||||
/**
|
||||
* @enum
|
||||
* The control frame types in HTTP/2.0.
|
||||
|
|
|
@ -839,3 +839,15 @@ int nghttp2_frame_nv_check_null(const char **nv)
|
|||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
int nghttp2_nv_equal(const nghttp2_nv *a, const nghttp2_nv *b)
|
||||
{
|
||||
return a->namelen == b->namelen && a->valuelen == b->valuelen &&
|
||||
memcmp(a->name, b->name, a->namelen) == 0 &&
|
||||
memcmp(a->value, b->value, a->valuelen) == 0;
|
||||
}
|
||||
|
||||
void nghttp2_nv_array_free(nghttp2_nv *nva)
|
||||
{
|
||||
free(nva);
|
||||
}
|
||||
|
|
|
@ -40,6 +40,8 @@
|
|||
#define NGHTTP2_PRI_DEFAULT (1 << 30)
|
||||
#define NGHTTP2_PRI_LOWEST ((1U << 31) - 1)
|
||||
|
||||
#define NGHTTP2_MAX_FRAME_SIZE ((1 << 16) - 1)
|
||||
|
||||
#define NGHTTP2_STREAM_ID_MASK 0x7fffffff
|
||||
#define NGHTTP2_PRIORITY_MASK 0x7fffffff
|
||||
#define NGHTTP2_WINDOW_SIZE_INCREMENT_MASK 0x7fffffff
|
||||
|
@ -571,4 +573,13 @@ ssize_t nghttp2_frame_nv_offset(const uint8_t *head);
|
|||
*/
|
||||
int nghttp2_frame_nv_check_null(const char **nv);
|
||||
|
||||
/*
|
||||
* Returns nonzero if the name/value pair |a| equals to |b|. The name
|
||||
* is compared in case-sensitive, because we ensure that this function
|
||||
* is called after the name is lower-cased.
|
||||
*/
|
||||
int nghttp2_nv_equal(const nghttp2_nv *a, const nghttp2_nv *b);
|
||||
|
||||
void nghttp2_nv_array_free(nghttp2_nv *nva);
|
||||
|
||||
#endif /* NGHTTP2_FRAME_H */
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,236 @@
|
|||
/*
|
||||
* nghttp2 - HTTP/2.0 C Library
|
||||
*
|
||||
* Copyright (c) 2013 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef NGHTTP2_HD_COMP_H
|
||||
#define NGHTTP2_HD_COMP_H
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
# include <config.h>
|
||||
#endif /* HAVE_CONFIG_H */
|
||||
|
||||
#include <nghttp2/nghttp2.h>
|
||||
|
||||
#define NGHTTP2_INITIAL_HD_TABLE_SIZE 128
|
||||
#define NGHTTP2_INITIAL_REFSET_SIZE 128
|
||||
#define NGHTTP2_INITIAL_WS_SIZE 128
|
||||
|
||||
#define NGHTTP2_MAX_HD_TABLE_CAPACITY 4096
|
||||
#define NGHTTP2_HD_ENTRY_OVERHEAD 32
|
||||
|
||||
typedef enum {
|
||||
NGHTTP2_HD_SIDE_CLIENT = 0,
|
||||
NGHTTP2_HD_SIDE_SERVER = 1
|
||||
} nghttp2_hd_side;
|
||||
|
||||
typedef enum {
|
||||
NGHTTP2_HD_FLAG_NONE = 0,
|
||||
/* Indicates name was dynamically allocated and must be freed */
|
||||
NGHTTP2_HD_FLAG_NAME_ALLOC = 1,
|
||||
/* Indicates value was dynamically allocated and must be freed */
|
||||
NGHTTP2_HD_FLAG_VALUE_ALLOC = 1 << 1,
|
||||
} nghttp2_hd_flags;
|
||||
|
||||
typedef struct {
|
||||
nghttp2_nv nv;
|
||||
/* Reference count in workingset */
|
||||
uint8_t ref;
|
||||
uint8_t index;
|
||||
uint8_t flags;
|
||||
} nghttp2_hd_entry;
|
||||
|
||||
typedef enum {
|
||||
NGHTTP2_HD_CAT_NONE,
|
||||
NGHTTP2_HD_CAT_INDEXED,
|
||||
NGHTTP2_HD_CAT_LITERAL_IDXNAME,
|
||||
NGHTTP2_HD_CAT_LITERAL
|
||||
} nghttp2_hd_entry_cat;
|
||||
|
||||
typedef struct nghttp2_hd_ws_entry {
|
||||
nghttp2_hd_entry_cat cat;
|
||||
union {
|
||||
/* For NGHTTP2_HD_CAT_INDEXED */
|
||||
nghttp2_hd_entry *entry;
|
||||
/* For NGHTTP2_HD_CAT_LITERAL */
|
||||
nghttp2_nv nv;
|
||||
/* For NGHTTP2_HD_CAT_LITERAL_IDXNAME */
|
||||
struct {
|
||||
/* The entry in header table the name stored */
|
||||
nghttp2_hd_entry *entry;
|
||||
uint8_t *value;
|
||||
uint16_t valuelen;
|
||||
} entv;
|
||||
};
|
||||
/* TODO Only usable with NGHTTP2_HD_CAT_INDEXED */
|
||||
uint8_t index;
|
||||
uint8_t checked;
|
||||
} nghttp2_hd_ws_entry;
|
||||
|
||||
typedef struct {
|
||||
/* Header table */
|
||||
nghttp2_hd_entry **hd_table;
|
||||
/* Reference set */
|
||||
nghttp2_hd_entry **refset;
|
||||
/* Working set */
|
||||
nghttp2_hd_ws_entry *ws;
|
||||
/* The capacity of the |hd_table| */
|
||||
uint16_t hd_table_capacity;
|
||||
/* the number of entry the |hd_table| contains */
|
||||
uint16_t hd_tablelen;
|
||||
/* The capacity of the |refset| */
|
||||
uint16_t refset_capacity;
|
||||
/* The number of entry the |refset| contains */
|
||||
uint16_t refsetlen;
|
||||
/* The capacity of the |ws| */
|
||||
uint16_t ws_capacity;
|
||||
/* The number of entry the |ws| contains */
|
||||
uint16_t wslen;
|
||||
/* Abstract capacity of hd_table as described in the spec. This is
|
||||
the sum of length of name/value in hd_table +
|
||||
NGHTTP2_HD_ENTRY_OVERHEAD bytes overhead per each entry. */
|
||||
uint16_t capacity;
|
||||
} nghttp2_hd_context;
|
||||
|
||||
/*
|
||||
* Initializes the |ent| members. If NGHTTP2_HD_FLAG_NAME_ALLOC bit
|
||||
* set in the |flags|, the content pointed by the |name| with length
|
||||
* |namelen| is copied. Likewise, if NGHTTP2_HD_FLAG_VALUE_ALLOC bit
|
||||
* set in the |flags|, the content pointed by the |value| with length
|
||||
* |valuelen| is copied.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
int nghttp2_hd_entry_init(nghttp2_hd_entry *ent, uint8_t index, uint8_t flags,
|
||||
uint8_t *name, uint16_t namelen,
|
||||
uint8_t *value, uint16_t valuelen);
|
||||
|
||||
void nghttp2_hd_entry_free(nghttp2_hd_entry *ent);
|
||||
|
||||
/*
|
||||
* Initializes |deflater| for deflating name/values pairs.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
int nghttp2_hd_deflate_init(nghttp2_hd_context *deflater,
|
||||
nghttp2_hd_side side);
|
||||
|
||||
/*
|
||||
* Initializes |inflater| for inflating name/values pairs.
|
||||
*
|
||||
* This function returns 0 if it succeeds, or one of the following
|
||||
* negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
int nghttp2_hd_inflate_init(nghttp2_hd_context *inflater,
|
||||
nghttp2_hd_side side);
|
||||
|
||||
/*
|
||||
* Deallocates any resources allocated for |deflater|.
|
||||
*/
|
||||
void nghttp2_hd_deflate_free(nghttp2_hd_context *deflater);
|
||||
|
||||
/*
|
||||
* Deallocates any resources allocated for |inflater|.
|
||||
*/
|
||||
void nghttp2_hd_inflate_free(nghttp2_hd_context *inflater);
|
||||
|
||||
/*
|
||||
* Deflates the |nv|, which has the |nvlen| name/value pairs, into the
|
||||
* buffer pointed by the |*buf_ptr| with the length |*buflen_ptr|.
|
||||
*
|
||||
* This function expands |*buf_ptr| as necessary to store the
|
||||
* result. When expansion occurred, memory previously pointed by
|
||||
* |*buf_ptr| is freed. |*buf_ptr| and |*buflen_ptr| are updated
|
||||
* accordingly.
|
||||
*
|
||||
* This function returns the number of bytes outputted if it succeeds,
|
||||
* or one of the following negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_context *deflater,
|
||||
uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t nv_offset,
|
||||
nghttp2_nv *nv, size_t nvlen);
|
||||
|
||||
/*
|
||||
* Inflates name/value block stored in |in| with length |inlen|. This
|
||||
* function performs decompression. The |*nv_ptr| points to the final
|
||||
* result on succesful decompression. The caller must free |*nv_ptr|
|
||||
* using nghttp2_nv_free().
|
||||
*
|
||||
* This function returns the number of bytes outputted if it succeeds,
|
||||
* or one of the following negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_context *inflater,
|
||||
nghttp2_nv **nva_ptr,
|
||||
uint8_t *in, size_t inlen);
|
||||
|
||||
|
||||
/*
|
||||
* Signals the end of processing one header block. This function
|
||||
* creates new reference set from working set.
|
||||
*
|
||||
* This function returns 0 if it succeeds. Currently this function
|
||||
* always succeeds.
|
||||
*/
|
||||
int nghttp2_hd_end_headers(nghttp2_hd_context *deflater_or_inflater);
|
||||
|
||||
/* For unittesting purpose */
|
||||
int nghttp2_hd_emit_indname_block(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t *offset_ptr, nghttp2_hd_entry *ent,
|
||||
const uint8_t *value, size_t valuelen,
|
||||
int inc_indexing);
|
||||
|
||||
/* For unittesting purpose */
|
||||
int nghttp2_hd_emit_literal_block(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t *offset_ptr, nghttp2_nv *nv,
|
||||
int inc_indexing);
|
||||
|
||||
/* For unittesting purpose */
|
||||
int nghttp2_hd_emit_subst_indname_block(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t *offset_ptr,
|
||||
nghttp2_hd_entry *ent,
|
||||
const uint8_t *value, size_t valuelen,
|
||||
size_t index);
|
||||
|
||||
/* For unittesting purpose */
|
||||
int nghttp2_hd_emit_subst_literal_block(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t *offset_ptr, nghttp2_nv *nv,
|
||||
size_t index);
|
||||
|
||||
#endif /* NGHTTP2_HD_COMP_H */
|
|
@ -71,6 +71,16 @@ int nghttp2_reserve_buffer(uint8_t **buf_ptr, size_t *buflen_ptr,
|
|||
return 0;
|
||||
}
|
||||
|
||||
void* nghttp2_memdup(const void* src, size_t n)
|
||||
{
|
||||
void* dest = malloc(n);
|
||||
if(dest == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
memcpy(dest, src, n);
|
||||
return dest;
|
||||
}
|
||||
|
||||
const char* nghttp2_strerror(int error_code)
|
||||
{
|
||||
switch(error_code) {
|
||||
|
|
|
@ -77,4 +77,16 @@ uint32_t nghttp2_get_uint32(const uint8_t *data);
|
|||
int nghttp2_reserve_buffer(uint8_t **buf_ptr, size_t *buflen_ptr,
|
||||
size_t min_length);
|
||||
|
||||
/*
|
||||
* Allocates |n| bytes of memory and copy the meory region pointed by
|
||||
* |src| with the length |n| bytes into it. Returns the allocated memory.
|
||||
*
|
||||
* This function returns pointer to allocated memory, or one of the
|
||||
* following negative error codes:
|
||||
*
|
||||
* NGHTTP2_ERR_NOMEM
|
||||
* Out of memory.
|
||||
*/
|
||||
void* nghttp2_memdup(const void* src, size_t n);
|
||||
|
||||
#endif /* NGHTTP2_HELPER_H */
|
||||
|
|
|
@ -33,13 +33,14 @@ OBJECTS = main.c nghttp2_pq_test.c nghttp2_map_test.c nghttp2_queue_test.c \
|
|||
nghttp2_frame_test.c \
|
||||
nghttp2_stream_test.c \
|
||||
nghttp2_session_test.c \
|
||||
nghttp2_hd_test.c \
|
||||
nghttp2_npn_test.c \
|
||||
nghttp2_gzip_test.c
|
||||
|
||||
HFILES = nghttp2_pq_test.h nghttp2_map_test.h nghttp2_queue_test.h \
|
||||
nghttp2_buffer_test.h nghttp2_zlib_test.h nghttp2_session_test.h \
|
||||
nghttp2_frame_test.h nghttp2_stream_test.h nghttp2_npn_test.h \
|
||||
nghttp2_gzip_test.h nghttp2_test_helper.h
|
||||
nghttp2_frame_test.h nghttp2_stream_test.h nghttp2_hd_test.h \
|
||||
nghttp2_npn_test.h nghttp2_gzip_test.h nghttp2_test_helper.h
|
||||
|
||||
main_SOURCES = $(HFILES) $(OBJECTS)
|
||||
|
||||
|
|
16
tests/main.c
16
tests/main.c
|
@ -34,6 +34,7 @@
|
|||
#include "nghttp2_session_test.h"
|
||||
#include "nghttp2_frame_test.h"
|
||||
#include "nghttp2_stream_test.h"
|
||||
#include "nghttp2_hd_test.h"
|
||||
#include "nghttp2_npn_test.h"
|
||||
#include "nghttp2_gzip_test.h"
|
||||
|
||||
|
@ -199,6 +200,21 @@ int main(int argc, char* argv[])
|
|||
/* !CU_add_test(pSuite, "stream_add_pushed_stream", */
|
||||
/* test_nghttp2_stream_add_pushed_stream) || */
|
||||
|
||||
!CU_add_test(pSuite, "hd_deflate", test_nghttp2_hd_deflate) ||
|
||||
!CU_add_test(pSuite, "hd_inflate_indname_inc",
|
||||
test_nghttp2_hd_inflate_indname_inc) ||
|
||||
!CU_add_test(pSuite, "hd_inflate_indname_inc_eviction",
|
||||
test_nghttp2_hd_inflate_indname_inc_eviction) ||
|
||||
!CU_add_test(pSuite, "hd_inflate_newname_inc",
|
||||
test_nghttp2_hd_inflate_newname_inc) ||
|
||||
!CU_add_test(pSuite, "hd_inflate_indname_subst",
|
||||
test_nghttp2_hd_inflate_newname_inc) ||
|
||||
!CU_add_test(pSuite, "hd_inflate_indname_subst_eviction",
|
||||
test_nghttp2_hd_inflate_indname_subst_eviction) ||
|
||||
!CU_add_test(pSuite, "hd_inflate_indname_subst_eviction_neg",
|
||||
test_nghttp2_hd_inflate_indname_subst_eviction_neg) ||
|
||||
!CU_add_test(pSuite, "hd_inflate_newname_subst",
|
||||
test_nghttp2_hd_inflate_newname_subst) ||
|
||||
!CU_add_test(pSuite, "gzip_inflate", test_nghttp2_gzip_inflate)
|
||||
) {
|
||||
CU_cleanup_registry();
|
||||
|
|
|
@ -0,0 +1,285 @@
|
|||
/*
|
||||
* nghttp2 - HTTP/2.0 C Library
|
||||
*
|
||||
* Copyright (c) 2013 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#include "nghttp2_hd_test.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
|
||||
#include <CUnit/CUnit.h>
|
||||
|
||||
#include "nghttp2_hd.h"
|
||||
#include "nghttp2_frame.h"
|
||||
|
||||
#define MAKE_NV(NAME, VALUE) \
|
||||
{ (uint8_t*)NAME, (uint8_t*)VALUE, strlen(NAME), strlen(VALUE) }
|
||||
|
||||
static void assert_nv_equal(nghttp2_nv *a, nghttp2_nv *b, size_t len)
|
||||
{
|
||||
size_t i;
|
||||
for(i = 0; i < len; ++i, ++a, ++b) {
|
||||
CU_ASSERT(nghttp2_nv_equal(a, b));
|
||||
}
|
||||
}
|
||||
|
||||
void test_nghttp2_hd_deflate(void)
|
||||
{
|
||||
nghttp2_hd_context deflater, inflater;
|
||||
nghttp2_nv nva1[] = {MAKE_NV(":path", "/my-example/index.html"),
|
||||
MAKE_NV(":scheme", "https"),
|
||||
MAKE_NV("hello", "world")};
|
||||
nghttp2_nv nva2[] = {MAKE_NV(":path", "/script.js"),
|
||||
MAKE_NV(":scheme", "https")};
|
||||
nghttp2_nv nvtemp;
|
||||
size_t nv_offset = 12;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
nghttp2_nv *resnva;
|
||||
ssize_t blocklen;
|
||||
|
||||
CU_ASSERT(0 == nghttp2_hd_deflate_init(&deflater, NGHTTP2_HD_SIDE_CLIENT));
|
||||
CU_ASSERT(0 == nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_SERVER));
|
||||
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, nv_offset, nva1,
|
||||
sizeof(nva1)/sizeof(nghttp2_nv));
|
||||
CU_ASSERT((1+1+22)+(1)+(1+1+5+1+5) == blocklen);
|
||||
nghttp2_hd_end_headers(&deflater);
|
||||
|
||||
CU_ASSERT(3 == nghttp2_hd_inflate_hd(&inflater, &resnva, buf + nv_offset,
|
||||
blocklen));
|
||||
|
||||
assert_nv_equal(nva1, resnva, 3);
|
||||
|
||||
nghttp2_nv_array_free(resnva);
|
||||
nghttp2_hd_end_headers(&inflater);
|
||||
|
||||
CU_ASSERT(1 == inflater.refsetlen);
|
||||
|
||||
/* Second headers */
|
||||
blocklen = nghttp2_hd_deflate_hd(&deflater, &buf, &buflen, nv_offset, nva2,
|
||||
sizeof(nva2)/sizeof(nghttp2_nv));
|
||||
CU_ASSERT((1+1+10) == blocklen);
|
||||
nghttp2_hd_end_headers(&deflater);
|
||||
|
||||
CU_ASSERT(2 == nghttp2_hd_inflate_hd(&inflater, &resnva, buf + nv_offset,
|
||||
blocklen));
|
||||
|
||||
/* First and second header fields are interchanged their positions. */
|
||||
nvtemp = nva2[0];
|
||||
nva2[0] = nva2[1];
|
||||
nva2[1] = nvtemp;
|
||||
assert_nv_equal(nva2, resnva, 2);
|
||||
|
||||
nghttp2_nv_array_free(resnva);
|
||||
nghttp2_hd_end_headers(&inflater);
|
||||
|
||||
free(buf);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
nghttp2_hd_deflate_free(&deflater);
|
||||
}
|
||||
|
||||
void test_nghttp2_hd_inflate_indname_inc(void)
|
||||
{
|
||||
nghttp2_hd_context inflater;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
size_t offset = 0;
|
||||
nghttp2_nv nv = MAKE_NV("user-agent", "nghttp2");
|
||||
nghttp2_nv *resnva;
|
||||
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_SERVER);
|
||||
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, &buflen, &offset,
|
||||
inflater.hd_table[12],
|
||||
nv.value, nv.valuelen,
|
||||
1));
|
||||
CU_ASSERT(1 == nghttp2_hd_inflate_hd(&inflater, &resnva, buf, offset));
|
||||
assert_nv_equal(&nv, resnva, 1);
|
||||
CU_ASSERT(39 == inflater.hd_tablelen);
|
||||
assert_nv_equal(&nv, &inflater.hd_table[inflater.hd_tablelen-1]->nv, 1);
|
||||
|
||||
nghttp2_nv_array_free(resnva);
|
||||
free(buf);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
}
|
||||
|
||||
void test_nghttp2_hd_inflate_indname_inc_eviction(void)
|
||||
{
|
||||
nghttp2_hd_context inflater;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
size_t offset = 0;
|
||||
/* Default header table capacity is 1592. Adding 2547 bytes,
|
||||
including overhead, to the table evicts first entry.
|
||||
use name ":host" which index 2 and value length 2510. */
|
||||
uint8_t value[2510];
|
||||
nghttp2_nv *resnva;
|
||||
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_SERVER);
|
||||
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&buf, &buflen, &offset,
|
||||
inflater.hd_table[2],
|
||||
value, sizeof(value), 1));
|
||||
CU_ASSERT(1 == nghttp2_hd_inflate_hd(&inflater, &resnva, buf, offset));
|
||||
CU_ASSERT(5 == resnva[0].namelen);
|
||||
CU_ASSERT(0 == memcmp(":host", resnva[0].name, resnva[0].namelen));
|
||||
CU_ASSERT(sizeof(value) == resnva[0].valuelen);
|
||||
|
||||
nghttp2_nv_array_free(resnva);
|
||||
nghttp2_hd_end_headers(&inflater);
|
||||
|
||||
CU_ASSERT(38 == inflater.hd_tablelen);
|
||||
CU_ASSERT(37 == inflater.refset[0]->index);
|
||||
|
||||
free(buf);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
}
|
||||
|
||||
void test_nghttp2_hd_inflate_newname_inc(void)
|
||||
{
|
||||
nghttp2_hd_context inflater;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
size_t offset = 0;
|
||||
nghttp2_nv nv = MAKE_NV("x-rel", "nghttp2");
|
||||
nghttp2_nv *resnva;
|
||||
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_SERVER);
|
||||
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_literal_block(&buf, &buflen, &offset,
|
||||
&nv, 1));
|
||||
CU_ASSERT(1 == nghttp2_hd_inflate_hd(&inflater, &resnva, buf, offset));
|
||||
assert_nv_equal(&nv, resnva, 1);
|
||||
CU_ASSERT(39 == inflater.hd_tablelen);
|
||||
assert_nv_equal(&nv, &inflater.hd_table[inflater.hd_tablelen-1]->nv, 1);
|
||||
|
||||
nghttp2_nv_array_free(resnva);
|
||||
free(buf);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
}
|
||||
|
||||
void test_nghttp2_hd_inflate_indname_subst(void)
|
||||
{
|
||||
nghttp2_hd_context inflater;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
size_t offset = 0;
|
||||
nghttp2_nv nv = MAKE_NV("user-agent", "nghttp2");
|
||||
nghttp2_nv *resnva;
|
||||
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_SERVER);
|
||||
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_subst_indname_block(&buf, &buflen, &offset,
|
||||
inflater.hd_table[12],
|
||||
nv.value, nv.valuelen,
|
||||
12));
|
||||
CU_ASSERT(1 == nghttp2_hd_inflate_hd(&inflater, &resnva, buf, offset));
|
||||
assert_nv_equal(&nv, resnva, 1);
|
||||
CU_ASSERT(38 == inflater.hd_tablelen);
|
||||
assert_nv_equal(&nv, &inflater.hd_table[12]->nv, 1);
|
||||
|
||||
nghttp2_nv_array_free(resnva);
|
||||
free(buf);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
}
|
||||
|
||||
void test_nghttp2_hd_inflate_indname_subst_eviction(void)
|
||||
{
|
||||
nghttp2_hd_context inflater;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
size_t offset = 0;
|
||||
/* Default header table capacity is 1592. Adding 2547 bytes,
|
||||
including overhead, to the table evicts first entry.
|
||||
use name ":host" which index 2 and value length 2510. */
|
||||
uint8_t value[2510];
|
||||
nghttp2_nv *resnva;
|
||||
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_SERVER);
|
||||
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_subst_indname_block(&buf, &buflen, &offset,
|
||||
inflater.hd_table[2],
|
||||
value, sizeof(value), 2));
|
||||
CU_ASSERT(1 == nghttp2_hd_inflate_hd(&inflater, &resnva, buf, offset));
|
||||
CU_ASSERT(5 == resnva[0].namelen);
|
||||
CU_ASSERT(0 == memcmp(":host", resnva[0].name, resnva[0].namelen));
|
||||
CU_ASSERT(sizeof(value) == resnva[0].valuelen);
|
||||
|
||||
nghttp2_nv_array_free(resnva);
|
||||
nghttp2_hd_end_headers(&inflater);
|
||||
|
||||
CU_ASSERT(37 == inflater.hd_tablelen);
|
||||
CU_ASSERT(1 == inflater.refset[0]->index);
|
||||
|
||||
free(buf);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
}
|
||||
|
||||
void test_nghttp2_hd_inflate_indname_subst_eviction_neg(void)
|
||||
{
|
||||
nghttp2_hd_context inflater;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
size_t offset = 0;
|
||||
/* Default header table capacity is 1592. Adding 2548 bytes,
|
||||
including overhead, to the table evicts first entry.
|
||||
use name ":host" which index 2 and value length 2511. */
|
||||
uint8_t value[2511];
|
||||
nghttp2_nv *resnva;
|
||||
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_SERVER);
|
||||
/* Try to substitute index 0, but it will be evicted */
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_subst_indname_block(&buf, &buflen, &offset,
|
||||
inflater.hd_table[2],
|
||||
value, sizeof(value), 0));
|
||||
CU_ASSERT(1 == nghttp2_hd_inflate_hd(&inflater, &resnva, buf, offset));
|
||||
CU_ASSERT(5 == resnva[0].namelen);
|
||||
CU_ASSERT(0 == memcmp(":host", resnva[0].name, resnva[0].namelen));
|
||||
CU_ASSERT(sizeof(value) == resnva[0].valuelen);
|
||||
|
||||
nghttp2_nv_array_free(resnva);
|
||||
nghttp2_hd_end_headers(&inflater);
|
||||
|
||||
CU_ASSERT(37 == inflater.hd_tablelen);
|
||||
CU_ASSERT(0 == inflater.refset[0]->index);
|
||||
|
||||
free(buf);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
}
|
||||
|
||||
void test_nghttp2_hd_inflate_newname_subst(void)
|
||||
{
|
||||
nghttp2_hd_context inflater;
|
||||
uint8_t *buf = NULL;
|
||||
size_t buflen = 0;
|
||||
size_t offset = 0;
|
||||
nghttp2_nv nv = MAKE_NV("x-rel", "nghttp2");
|
||||
nghttp2_nv *resnva;
|
||||
nghttp2_hd_inflate_init(&inflater, NGHTTP2_HD_SIDE_SERVER);
|
||||
|
||||
CU_ASSERT(0 == nghttp2_hd_emit_subst_literal_block(&buf, &buflen, &offset,
|
||||
&nv, 1));
|
||||
CU_ASSERT(1 == nghttp2_hd_inflate_hd(&inflater, &resnva, buf, offset));
|
||||
assert_nv_equal(&nv, resnva, 1);
|
||||
CU_ASSERT(38 == inflater.hd_tablelen);
|
||||
assert_nv_equal(&nv, &inflater.hd_table[1]->nv, 1);
|
||||
|
||||
nghttp2_nv_array_free(resnva);
|
||||
free(buf);
|
||||
nghttp2_hd_inflate_free(&inflater);
|
||||
}
|
|
@ -0,0 +1,37 @@
|
|||
/*
|
||||
* nghttp2 - HTTP/2.0 C Library
|
||||
*
|
||||
* Copyright (c) 2013 Tatsuhiro Tsujikawa
|
||||
*
|
||||
* Permission is hereby granted, free of charge, to any person obtaining
|
||||
* a copy of this software and associated documentation files (the
|
||||
* "Software"), to deal in the Software without restriction, including
|
||||
* without limitation the rights to use, copy, modify, merge, publish,
|
||||
* distribute, sublicense, and/or sell copies of the Software, and to
|
||||
* permit persons to whom the Software is furnished to do so, subject to
|
||||
* the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be
|
||||
* included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
||||
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
||||
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
||||
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
||||
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
||||
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
#ifndef NGHTTP2_HD_TEST_H
|
||||
#define NGHTTP2_HD_TEST_H
|
||||
|
||||
void test_nghttp2_hd_deflate(void);
|
||||
void test_nghttp2_hd_inflate_indname_inc(void);
|
||||
void test_nghttp2_hd_inflate_indname_inc_eviction(void);
|
||||
void test_nghttp2_hd_inflate_newname_inc(void);
|
||||
void test_nghttp2_hd_inflate_indname_subst(void);
|
||||
void test_nghttp2_hd_inflate_indname_subst_eviction(void);
|
||||
void test_nghttp2_hd_inflate_indname_subst_eviction_neg(void);
|
||||
void test_nghttp2_hd_inflate_newname_subst(void);
|
||||
|
||||
#endif /* NGHTTP2_HD_TEST_H */
|
Loading…
Reference in New Issue