Honor NGHTTP2_NV_FLAG_NO_INDEX in deflater and inflater

This commit is contained in:
Tatsuhiro Tsujikawa 2014-04-02 01:25:44 +09:00
parent c55df4a30b
commit 7877b676e3
8 changed files with 200 additions and 90 deletions

View File

@ -352,6 +352,7 @@ int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater)
inflater->index = 0; inflater->index = 0;
inflater->left = 0; inflater->left = 0;
inflater->index_required = 0; inflater->index_required = 0;
inflater->no_index = 0;
inflater->ent_name = NULL; inflater->ent_name = NULL;
return 0; return 0;
} }
@ -543,11 +544,10 @@ static int nghttp2_hd_handle_buffer_error(int rv)
static int emit_clear_refset(nghttp2_bufs *bufs) static int emit_clear_refset(nghttp2_bufs *bufs)
{ {
int rv; int rv;
uint8_t sb[] = {0x80u, 0x80u};
DEBUGF(fprintf(stderr, "deflatehd: emit clear refset\n")); DEBUGF(fprintf(stderr, "deflatehd: emit clear refset\n"));
rv = nghttp2_bufs_add(bufs, sb, sizeof(sb)); rv = nghttp2_bufs_addb(bufs, 0x30u);
if(rv != 0) { if(rv != 0) {
return nghttp2_hd_handle_buffer_error(rv); return nghttp2_hd_handle_buffer_error(rv);
} }
@ -564,7 +564,7 @@ static int emit_table_size(nghttp2_bufs *bufs, size_t table_size)
DEBUGF(fprintf(stderr, "deflatehd: emit table_size=%zu\n", table_size)); DEBUGF(fprintf(stderr, "deflatehd: emit table_size=%zu\n", table_size));
blocklen = 1 + count_encoded_length(table_size, 7); blocklen = count_encoded_length(table_size, 4);
if(sizeof(sb) < blocklen) { if(sizeof(sb) < blocklen) {
return NGHTTP2_ERR_HEADER_COMP; return NGHTTP2_ERR_HEADER_COMP;
@ -572,9 +572,9 @@ static int emit_table_size(nghttp2_bufs *bufs, size_t table_size)
bufp = sb; bufp = sb;
*bufp++ = 0x80u; *bufp = 0x20u;
*bufp = 0;
encode_length(bufp, table_size, 7); encode_length(bufp, table_size, 4);
rv = nghttp2_bufs_add(bufs, sb, blocklen); rv = nghttp2_bufs_add(bufs, sb, blocklen);
if(rv != 0) { if(rv != 0) {
@ -652,8 +652,21 @@ static int emit_string(nghttp2_bufs *bufs,
return nghttp2_hd_handle_buffer_error(rv); return nghttp2_hd_handle_buffer_error(rv);
} }
static uint8_t pack_first_byte(int inc_indexing, int no_index)
{
if(inc_indexing) {
return 0x40u;
}
if(no_index) {
return 0x10u;
}
return 0;
}
static int emit_indname_block(nghttp2_bufs *bufs, size_t index, static int emit_indname_block(nghttp2_bufs *bufs, size_t index,
const uint8_t *value, size_t valuelen, nghttp2_nv *nv,
int inc_indexing) int inc_indexing)
{ {
int rv; int rv;
@ -662,18 +675,28 @@ static int emit_indname_block(nghttp2_bufs *bufs, size_t index,
size_t blocklen; size_t blocklen;
int huffman; int huffman;
uint8_t sb[16]; uint8_t sb[16];
size_t prefixlen;
int no_index;
no_index = (nv->flags & NGHTTP2_NV_FLAG_NO_INDEX) != 0;
if(inc_indexing) {
prefixlen = 6;
} else {
prefixlen = 4;
}
DEBUGF(fprintf(stderr, DEBUGF(fprintf(stderr,
"deflatehd: emit indname index=%zu, valuelen=%zu, " "deflatehd: emit indname index=%zu, valuelen=%u, "
"indexing=%d\n", "indexing=%d, no_index=%d\n",
index, valuelen, inc_indexing)); index, nv->valuelen, inc_indexing, no_index));
encvallen = nghttp2_hd_huff_encode_count(value, valuelen); encvallen = nghttp2_hd_huff_encode_count(nv->value, nv->valuelen);
blocklen = count_encoded_length(index + 1, 6); blocklen = count_encoded_length(index + 1, prefixlen);
huffman = encvallen < valuelen; huffman = encvallen < nv->valuelen;
if(!huffman) { if(!huffman) {
encvallen = valuelen; encvallen = nv->valuelen;
} }
if(sizeof(sb) < blocklen) { if(sizeof(sb) < blocklen) {
@ -682,15 +705,16 @@ static int emit_indname_block(nghttp2_bufs *bufs, size_t index,
bufp = sb; bufp = sb;
*bufp = inc_indexing ? 0 : 0x40u; *bufp = pack_first_byte(inc_indexing, no_index);
bufp += encode_length(bufp, index + 1, 6);
bufp += encode_length(bufp, index + 1, prefixlen);
rv = nghttp2_bufs_add(bufs, sb, blocklen); rv = nghttp2_bufs_add(bufs, sb, blocklen);
if(rv != 0) { if(rv != 0) {
return nghttp2_hd_handle_buffer_error(rv); return nghttp2_hd_handle_buffer_error(rv);
} }
rv = emit_string(bufs, encvallen, huffman, value, valuelen); rv = emit_string(bufs, encvallen, huffman, nv->value, nv->valuelen);
if(rv != 0) { if(rv != 0) {
return rv; return rv;
} }
@ -706,11 +730,14 @@ static int emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,
size_t encvallen; size_t encvallen;
int name_huffman; int name_huffman;
int value_huffman; int value_huffman;
int no_index;
no_index = (nv->flags & NGHTTP2_NV_FLAG_NO_INDEX) != 0;
DEBUGF(fprintf(stderr, DEBUGF(fprintf(stderr,
"deflatehd: emit newname namelen=%u, valuelen=%u, " "deflatehd: emit newname namelen=%u, valuelen=%u, "
"indexing=%d\n", "indexing=%d, no_index=%d\n",
nv->namelen, nv->valuelen, inc_indexing)); nv->namelen, nv->valuelen, inc_indexing, no_index));
encnamelen = nghttp2_hd_huff_encode_count(nv->name, nv->namelen); encnamelen = nghttp2_hd_huff_encode_count(nv->name, nv->namelen);
encvallen = nghttp2_hd_huff_encode_count(nv->value, nv->valuelen); encvallen = nghttp2_hd_huff_encode_count(nv->value, nv->valuelen);
@ -724,7 +751,7 @@ static int emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,
encvallen = nv->valuelen; encvallen = nv->valuelen;
} }
rv = nghttp2_bufs_addb(bufs, inc_indexing ? 0 : 0x40u); rv = nghttp2_bufs_addb(bufs, pack_first_byte(inc_indexing, no_index));
if(rv != 0) { if(rv != 0) {
return nghttp2_hd_handle_buffer_error(rv); return nghttp2_hd_handle_buffer_error(rv);
} }
@ -849,17 +876,20 @@ static search_result search_hd_table(nghttp2_hd_context *context,
uint32_t name_hash = hash(nv->name, nv->namelen); uint32_t name_hash = hash(nv->name, nv->namelen);
uint32_t value_hash = hash(nv->value, nv->valuelen); uint32_t value_hash = hash(nv->value, nv->valuelen);
ssize_t left = -1, right = STATIC_TABLE_LENGTH; ssize_t left = -1, right = STATIC_TABLE_LENGTH;
int use_index = (nv->flags & NGHTTP2_NV_FLAG_NO_INDEX) == 0;
for(i = 0; i < context->hd_table.len; ++i) { if(use_index) {
nghttp2_hd_entry *ent = nghttp2_hd_ringbuf_get(&context->hd_table, i); for(i = 0; i < context->hd_table.len; ++i) {
if(ent->name_hash == name_hash && name_eq(&ent->nv, nv)) { nghttp2_hd_entry *ent = nghttp2_hd_ringbuf_get(&context->hd_table, i);
if(res.index == -1) { if(ent->name_hash == name_hash && name_eq(&ent->nv, nv)) {
res.index = i; if(res.index == -1) {
} res.index = i;
if(ent->value_hash == value_hash && value_eq(&ent->nv, nv)) { }
res.index = i; if(ent->value_hash == value_hash && value_eq(&ent->nv, nv)) {
res.name_value_match = 1; res.index = i;
return res; res.name_value_match = 1;
return res;
}
} }
} }
} }
@ -873,6 +903,7 @@ static search_result search_hd_table(nghttp2_hd_context *context,
right = mid; right = mid;
} }
} }
for(i = right; i < STATIC_TABLE_LENGTH; ++i) { for(i = right; i < STATIC_TABLE_LENGTH; ++i) {
nghttp2_hd_entry *ent = &static_table[i].ent; nghttp2_hd_entry *ent = &static_table[i].ent;
if(ent->name_hash != name_hash) { if(ent->name_hash != name_hash) {
@ -882,7 +913,8 @@ static search_result search_hd_table(nghttp2_hd_context *context,
if(res.index == -1) { if(res.index == -1) {
res.index = context->hd_table.len + static_table[i].index; res.index = context->hd_table.len + static_table[i].index;
} }
if(ent->value_hash == value_hash && value_eq(&ent->nv, nv)) { if(use_index &&
ent->value_hash == value_hash && value_eq(&ent->nv, nv)) {
res.index = context->hd_table.len + static_table[i].index; res.index = context->hd_table.len + static_table[i].index;
res.name_value_match = 1; res.name_value_match = 1;
return res; return res;
@ -985,7 +1017,8 @@ nghttp2_hd_entry* nghttp2_hd_table_get(nghttp2_hd_context *context,
static int hd_deflate_should_indexing(nghttp2_hd_deflater *deflater, static int hd_deflate_should_indexing(nghttp2_hd_deflater *deflater,
const nghttp2_nv *nv) const nghttp2_nv *nv)
{ {
if(entry_room(nv->namelen, nv->valuelen) > if((nv->flags & NGHTTP2_NV_FLAG_NO_INDEX) ||
entry_room(nv->namelen, nv->valuelen) >
deflater->ctx.hd_table_bufsize_max * 3 / 4) { deflater->ctx.hd_table_bufsize_max * 3 / 4) {
return 0; return 0;
} }
@ -1123,7 +1156,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater,
if(index == -1) { if(index == -1) {
rv = emit_newname_block(bufs, nv, incidx); rv = emit_newname_block(bufs, nv, incidx);
} else { } else {
rv = emit_indname_block(bufs, index, nv->value, nv->valuelen, incidx); rv = emit_indname_block(bufs, index, nv, incidx);
} }
if(rv != 0) { if(rv != 0) {
return rv; return rv;
@ -1407,8 +1440,11 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
return NGHTTP2_ERR_NOMEM; return NGHTTP2_ERR_NOMEM;
} }
/* Set NGHTTP2_NV_FLAG_NO_INDEX if never indexing repr is used */ if(inflater->no_index) {
nv.flags = NGHTTP2_NV_FLAG_NONE; nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
} else {
nv.flags = NGHTTP2_NV_FLAG_NONE;
}
if(inflater->index_required) { if(inflater->index_required) {
nghttp2_hd_entry *new_ent; nghttp2_hd_entry *new_ent;
@ -1463,8 +1499,11 @@ static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
return NGHTTP2_ERR_NOMEM; return NGHTTP2_ERR_NOMEM;
} }
/* Set NGHTTP2_NV_FLAG_NO_INDEX if never indexing repr is used */ if(inflater->no_index) {
nv.flags = NGHTTP2_NV_FLAG_NONE; nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
} else {
nv.flags = NGHTTP2_NV_FLAG_NONE;
}
nv.name = inflater->ent_name->nv.name; nv.name = inflater->ent_name->nv.name;
nv.namelen = inflater->ent_name->nv.namelen; nv.namelen = inflater->ent_name->nv.namelen;
@ -1533,17 +1572,26 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
for(; in != last;) { for(; in != last;) {
switch(inflater->state) { switch(inflater->state) {
case NGHTTP2_HD_STATE_OPCODE: case NGHTTP2_HD_STATE_OPCODE:
if(*in == 0x80u) { if((*in & 0xf0u) == 0x20u) {
DEBUGF(fprintf(stderr, "inflatehd: encoding context update\n")); DEBUGF(fprintf(stderr, "inflatehd: header table size change\n"));
inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED; inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
inflater->state = NGHTTP2_HD_STATE_CONTEXT_UPDATE; inflater->state = NGHTTP2_HD_STATE_READ_TABLE_SIZE;
} else if((*in & 0xf0u) == 0x30u) {
if(*in != 0x30u) {
rv = NGHTTP2_ERR_HEADER_COMP;
goto fail;
}
DEBUGF(fprintf(stderr, "inflatehd: clearing reference set\n"));
inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
inflater->state = NGHTTP2_HD_STATE_CLEAR_REFSET;
++in; ++in;
} else if(*in & 0x80u) { } else if(*in & 0x80u) {
DEBUGF(fprintf(stderr, "inflatehd: indexed repr\n")); DEBUGF(fprintf(stderr, "inflatehd: indexed repr\n"));
inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED; inflater->opcode = NGHTTP2_HD_OPCODE_INDEXED;
inflater->state = NGHTTP2_HD_STATE_READ_INDEX; inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
} else { } else {
if(*in == 0x40 || *in == 0) { if(*in == 0x40u || *in == 0 || *in == 0x10u) {
DEBUGF(fprintf(stderr, DEBUGF(fprintf(stderr,
"inflatehd: literal header repr - new name\n")); "inflatehd: literal header repr - new name\n"));
inflater->opcode = NGHTTP2_HD_OPCODE_NEWNAME; inflater->opcode = NGHTTP2_HD_OPCODE_NEWNAME;
@ -1554,34 +1602,26 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
inflater->opcode = NGHTTP2_HD_OPCODE_INDNAME; inflater->opcode = NGHTTP2_HD_OPCODE_INDNAME;
inflater->state = NGHTTP2_HD_STATE_READ_INDEX; inflater->state = NGHTTP2_HD_STATE_READ_INDEX;
} }
inflater->index_required = (*in & 0x40) == 0; inflater->index_required = (*in & 0x40) != 0;
DEBUGF(fprintf(stderr, "inflatehd: indexing required=%d\n", inflater->no_index = (*in & 0x10u) != 0;
inflater->index_required != 0)); DEBUGF(fprintf(stderr,
"inflatehd: indexing required=%d, no_index=%d\n",
inflater->index_required,
inflater->no_index));
if(inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) { if(inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
++in; ++in;
} }
} }
inflater->left = 0; inflater->left = 0;
break; break;
case NGHTTP2_HD_STATE_CONTEXT_UPDATE: case NGHTTP2_HD_STATE_CLEAR_REFSET:
if(*in & 0x80u) { clear_refset(&inflater->ctx);
if(*in != 0x80u) { inflater->state = NGHTTP2_HD_STATE_OPCODE;
rv = NGHTTP2_ERR_HEADER_COMP;
goto fail;
}
++in;
DEBUGF(fprintf(stderr, "inflatehd: clearing reference set\n"));
clear_refset(&inflater->ctx);
inflater->state = NGHTTP2_HD_STATE_OPCODE;
break;
}
/* Header table size change */
DEBUGF(fprintf(stderr, "inflatehd: header table size change\n"));
inflater->state = NGHTTP2_HD_STATE_READ_TABLE_SIZE;
break; break;
case NGHTTP2_HD_STATE_READ_TABLE_SIZE: case NGHTTP2_HD_STATE_READ_TABLE_SIZE:
rfin = 0; rfin = 0;
rv = hd_inflate_read_len(inflater, &rfin, in, last, 7, rv = hd_inflate_read_len(inflater, &rfin, in, last, 4,
inflater->settings_hd_table_bufsize_max); inflater->settings_hd_table_bufsize_max);
if(rv < 0) { if(rv < 0) {
goto fail; goto fail;
@ -1595,11 +1635,19 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
hd_context_shrink_table_size(&inflater->ctx); hd_context_shrink_table_size(&inflater->ctx);
inflater->state = NGHTTP2_HD_STATE_OPCODE; inflater->state = NGHTTP2_HD_STATE_OPCODE;
break; break;
case NGHTTP2_HD_STATE_READ_INDEX: case NGHTTP2_HD_STATE_READ_INDEX: {
size_t prefixlen;
if(inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED) {
prefixlen = 7;
} else if(inflater->index_required) {
prefixlen = 6;
} else {
prefixlen = 4;
}
rfin = 0; rfin = 0;
rv = hd_inflate_read_len(inflater, &rfin, in, last, rv = hd_inflate_read_len(inflater, &rfin, in, last, prefixlen,
inflater->opcode == NGHTTP2_HD_OPCODE_INDEXED ?
7 : 6,
get_max_index(&inflater->ctx) + 1); get_max_index(&inflater->ctx) + 1);
if(rv < 0) { if(rv < 0) {
goto fail; goto fail;
@ -1632,6 +1680,7 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN; inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
} }
break; break;
}
case NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN: case NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN:
hd_inflate_set_huffman_encoded(inflater, in); hd_inflate_set_huffman_encoded(inflater, in);
inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN; inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMELEN;
@ -1871,10 +1920,10 @@ int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater)
} }
int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t index, int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t index,
const uint8_t *value, size_t valuelen, nghttp2_nv *nv, int inc_indexing)
int inc_indexing)
{ {
return emit_indname_block(bufs, index, value, valuelen, inc_indexing);
return emit_indname_block(bufs, index, nv, inc_indexing);
} }
int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv, int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,

View File

@ -103,7 +103,7 @@ typedef enum {
typedef enum { typedef enum {
NGHTTP2_HD_STATE_OPCODE, NGHTTP2_HD_STATE_OPCODE,
NGHTTP2_HD_STATE_CONTEXT_UPDATE, NGHTTP2_HD_STATE_CLEAR_REFSET,
NGHTTP2_HD_STATE_READ_TABLE_SIZE, NGHTTP2_HD_STATE_READ_TABLE_SIZE,
NGHTTP2_HD_STATE_READ_INDEX, NGHTTP2_HD_STATE_READ_INDEX,
NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN, NGHTTP2_HD_STATE_NEWNAME_CHECK_NAMELEN,
@ -177,6 +177,9 @@ typedef struct {
uint8_t huffman_encoded; uint8_t huffman_encoded;
/* nonzero if deflater requires that current entry is indexed */ /* nonzero if deflater requires that current entry is indexed */
uint8_t index_required; uint8_t index_required;
/* nonzero if deflater requires that current entry must not be
indexed */
uint8_t no_index;
} nghttp2_hd_inflater; } nghttp2_hd_inflater;
/* /*
@ -370,8 +373,7 @@ int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater);
/* For unittesting purpose */ /* For unittesting purpose */
int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t index, int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t index,
const uint8_t *value, size_t valuelen, nghttp2_nv *nv, int inc_indexing);
int inc_indexing);
/* For unittesting purpose */ /* For unittesting purpose */
int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv, int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,

View File

@ -274,6 +274,7 @@ int main(int argc, char* argv[])
test_nghttp2_hd_change_table_size) || test_nghttp2_hd_change_table_size) ||
!CU_add_test(pSuite, "hd_deflate_inflate", !CU_add_test(pSuite, "hd_deflate_inflate",
test_nghttp2_hd_deflate_inflate) || test_nghttp2_hd_deflate_inflate) ||
!CU_add_test(pSuite, "hd_no_index", test_nghttp2_hd_no_index) ||
!CU_add_test(pSuite, "gzip_inflate", test_nghttp2_gzip_inflate) || !CU_add_test(pSuite, "gzip_inflate", test_nghttp2_gzip_inflate) ||
!CU_add_test(pSuite, "adjust_local_window_size", !CU_add_test(pSuite, "adjust_local_window_size",
test_nghttp2_adjust_local_window_size) || test_nghttp2_adjust_local_window_size) ||

View File

@ -41,6 +41,8 @@ static nghttp2_nv make_nv(const char *name, const char *value)
nv.value = (uint8_t*)value; nv.value = (uint8_t*)value;
nv.namelen = strlen(name); nv.namelen = strlen(name);
nv.valuelen = strlen(value); nv.valuelen = strlen(value);
nv.flags = NGHTTP2_NV_FLAG_NONE;
return nv; return nv;
} }
@ -223,6 +225,7 @@ void test_nghttp2_frame_pack_headers_frame_too_large(void)
big_hds[i].value[big_vallen] = '\0'; big_hds[i].value[big_vallen] = '\0';
big_hds[i].namelen = strlen((char*)big_hds[i].name); big_hds[i].namelen = strlen((char*)big_hds[i].name);
big_hds[i].valuelen = big_vallen; big_hds[i].valuelen = big_vallen;
big_hds[i].flags = NGHTTP2_NV_FLAG_NONE;
} }
pri_spec.pri_type = NGHTTP2_PRIORITY_TYPE_NONE; pri_spec.pri_type = NGHTTP2_PRIORITY_TYPE_NONE;

View File

@ -329,9 +329,7 @@ void test_nghttp2_hd_inflate_indname_noinc(void)
nghttp2_hd_inflate_init(&inflater); nghttp2_hd_inflate_init(&inflater);
for(i = 0; i < ARRLEN(nv); ++i) { for(i = 0; i < ARRLEN(nv); ++i) {
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 56, CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 56, &nv[i], 0));
nv[i].value, nv[i].valuelen,
0));
blocklen = nghttp2_bufs_len(&bufs); blocklen = nghttp2_bufs_len(&bufs);
@ -363,8 +361,7 @@ void test_nghttp2_hd_inflate_indname_inc(void)
nva_out_init(&out); nva_out_init(&out);
nghttp2_hd_inflate_init(&inflater); nghttp2_hd_inflate_init(&inflater);
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 56, CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 56, &nv, 1));
nv.value, nv.valuelen, 1));
blocklen = nghttp2_bufs_len(&bufs); blocklen = nghttp2_bufs_len(&bufs);
@ -390,6 +387,7 @@ void test_nghttp2_hd_inflate_indname_inc_eviction(void)
ssize_t blocklen; ssize_t blocklen;
uint8_t value[1024]; uint8_t value[1024];
nva_out out; nva_out out;
nghttp2_nv nv;
frame_pack_bufs_init(&bufs); frame_pack_bufs_init(&bufs);
@ -397,14 +395,15 @@ void test_nghttp2_hd_inflate_indname_inc_eviction(void)
nghttp2_hd_inflate_init(&inflater); nghttp2_hd_inflate_init(&inflater);
memset(value, '0', sizeof(value)); memset(value, '0', sizeof(value));
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 13, nv.value = value;
value, sizeof(value), 1)); nv.valuelen = sizeof(value);
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 14,
value, sizeof(value), 1)); nv.flags = NGHTTP2_NV_FLAG_NONE;
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 15,
value, sizeof(value), 1)); CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 13, &nv, 1));
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 16, CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 14, &nv, 1));
value, sizeof(value), 1)); CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 15, &nv, 1));
CU_ASSERT(0 == nghttp2_hd_emit_indname_block(&bufs, 16, &nv, 1));
blocklen = nghttp2_bufs_len(&bufs); blocklen = nghttp2_bufs_len(&bufs);
@ -520,6 +519,8 @@ void test_nghttp2_hd_inflate_clearall_inc(void)
nv.value = value; nv.value = value;
nv.valuelen = sizeof(value); nv.valuelen = sizeof(value);
nv.flags = NGHTTP2_NV_FLAG_NONE;
nghttp2_hd_inflate_init(&inflater); nghttp2_hd_inflate_init(&inflater);
CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&bufs, &nv, 1)); CU_ASSERT(0 == nghttp2_hd_emit_newname_block(&bufs, &nv, 1));
@ -991,3 +992,54 @@ void test_nghttp2_hd_deflate_inflate(void)
nghttp2_hd_inflate_free(&inflater); nghttp2_hd_inflate_free(&inflater);
nghttp2_hd_deflate_free(&deflater); nghttp2_hd_deflate_free(&deflater);
} }
void test_nghttp2_hd_no_index(void)
{
nghttp2_hd_deflater deflater;
nghttp2_hd_inflater inflater;
nghttp2_bufs bufs;
ssize_t blocklen;
nghttp2_nv nva[] = {
MAKE_NV(":method", "GET"),
MAKE_NV(":method", "POST"),
MAKE_NV(":path", "/foo"),
MAKE_NV("version", "HTTP/1.1"),
MAKE_NV(":method", "GET"),
};
size_t i;
nva_out out;
int rv;
/* 1st :method: GET can be indexable, last one is not */
for(i = 1; i < ARRLEN(nva); ++i) {
nva[i].flags = NGHTTP2_NV_FLAG_NO_INDEX;
}
frame_pack_bufs_init(&bufs);
nva_out_init(&out);
nghttp2_hd_deflate_init(&deflater);
nghttp2_hd_inflate_init(&inflater);
rv = nghttp2_hd_deflate_hd(&deflater, &bufs, nva, ARRLEN(nva));
blocklen = nghttp2_bufs_len(&bufs);
CU_ASSERT(0 == rv);
CU_ASSERT(blocklen > 0);
CU_ASSERT(blocklen == inflate_hd(&inflater, &out, &bufs, 0));
CU_ASSERT(ARRLEN(nva) == out.nvlen);
assert_nv_equal(nva, out.nva, ARRLEN(nva));
CU_ASSERT(out.nva[0].flags == NGHTTP2_NV_FLAG_NONE);
for(i = 1; i < ARRLEN(nva); ++i) {
CU_ASSERT(out.nva[i].flags == NGHTTP2_NV_FLAG_NO_INDEX);
}
nva_out_reset(&out);
nghttp2_bufs_free(&bufs);
nghttp2_hd_inflate_free(&inflater);
nghttp2_hd_deflate_free(&deflater);
}

View File

@ -38,5 +38,6 @@ void test_nghttp2_hd_inflate_clearall_inc(void);
void test_nghttp2_hd_inflate_zero_length_huffman(void); void test_nghttp2_hd_inflate_zero_length_huffman(void);
void test_nghttp2_hd_change_table_size(void); void test_nghttp2_hd_change_table_size(void);
void test_nghttp2_hd_deflate_inflate(void); void test_nghttp2_hd_deflate_inflate(void);
void test_nghttp2_hd_no_index(void);
#endif /* NGHTTP2_HD_TEST_H */ #endif /* NGHTTP2_HD_TEST_H */

View File

@ -2347,6 +2347,7 @@ void test_nghttp2_session_send_headers_header_comp_error(void)
memset(nv[i].value, '0'+i, vallen); memset(nv[i].value, '0'+i, vallen);
nv[i].value[vallen] = '\0'; nv[i].value[vallen] = '\0';
nv[i].valuelen = vallen; nv[i].valuelen = vallen;
nv[i].flags = NGHTTP2_NV_FLAG_NONE;
} }
memset(&callbacks, 0, sizeof(nghttp2_session_callbacks)); memset(&callbacks, 0, sizeof(nghttp2_session_callbacks));
@ -4665,6 +4666,7 @@ void test_nghttp2_session_pack_headers_with_padding(void)
nva[i].namelen = 5; nva[i].namelen = 5;
nva[i].value = (uint8_t*)"/"; nva[i].value = (uint8_t*)"/";
nva[i].valuelen = 1; nva[i].valuelen = 1;
nva[i].flags = NGHTTP2_NV_FLAG_NONE;
} }
memset(&callbacks, 0, sizeof(callbacks)); memset(&callbacks, 0, sizeof(callbacks));
@ -4729,6 +4731,7 @@ void test_nghttp2_session_pack_headers_with_padding2(void)
nva[i].namelen = 5; nva[i].namelen = 5;
nva[i].value = (uint8_t*)"/"; nva[i].value = (uint8_t*)"/";
nva[i].valuelen = 1; nva[i].valuelen = 1;
nva[i].flags = NGHTTP2_NV_FLAG_NONE;
} }
memset(&callbacks, 0, sizeof(callbacks)); memset(&callbacks, 0, sizeof(callbacks));
@ -4777,6 +4780,7 @@ void test_nghttp2_session_pack_headers_with_padding3(void)
nva[i].namelen = 5; nva[i].namelen = 5;
nva[i].value = (uint8_t*)"/"; nva[i].value = (uint8_t*)"/";
nva[i].valuelen = 1; nva[i].valuelen = 1;
nva[i].flags = NGHTTP2_NV_FLAG_NONE;
} }
memset(&callbacks, 0, sizeof(callbacks)); memset(&callbacks, 0, sizeof(callbacks));
@ -4817,12 +4821,7 @@ void test_nghttp2_session_pack_headers_with_padding4(void)
accumulator acc; accumulator acc;
my_user_data ud; my_user_data ud;
nghttp2_session_callbacks callbacks; nghttp2_session_callbacks callbacks;
nghttp2_nv nva[1]; nghttp2_nv nv = MAKE_NV(":path", "/");
nva[0].name = (uint8_t*)":path";
nva[0].namelen = 5;
nva[0].value = (uint8_t*)"/";
nva[0].valuelen = 1;
memset(&callbacks, 0, sizeof(callbacks)); memset(&callbacks, 0, sizeof(callbacks));
callbacks.send_callback = accumulator_send_callback; callbacks.send_callback = accumulator_send_callback;
@ -4841,7 +4840,7 @@ void test_nghttp2_session_pack_headers_with_padding4(void)
CU_ASSERT(0 == CU_ASSERT(0 ==
nghttp2_submit_request(session, NULL, nghttp2_submit_request(session, NULL,
nva, ARRLEN(nva), NULL, NULL)); &nv, 1, NULL, NULL));
CU_ASSERT(0 == nghttp2_session_send(session)); CU_ASSERT(0 == nghttp2_session_send(session));
CU_ASSERT(acc.length < NGHTTP2_MAX_PAYLOADLEN); CU_ASSERT(acc.length < NGHTTP2_MAX_PAYLOADLEN);

View File

@ -161,6 +161,9 @@ void add_out(nva_out *out, nghttp2_nv *nv)
} }
onv->namelen = nv->namelen; onv->namelen = nv->namelen;
onv->valuelen = nv->valuelen; onv->valuelen = nv->valuelen;
onv->flags = nv->flags;
++out->nvlen; ++out->nvlen;
} }