Fix bug common header disappear if it is evicted

This commit is contained in:
Tatsuhiro Tsujikawa 2013-08-23 03:45:26 +09:00
parent 346fafde3f
commit 93e5b9e562
1 changed files with 53 additions and 27 deletions

View File

@ -173,8 +173,15 @@ static int nghttp2_hd_context_init(nghttp2_hd_context *context,
context->hd_table_capacity = NGHTTP2_INITIAL_HD_TABLE_SIZE; context->hd_table_capacity = NGHTTP2_INITIAL_HD_TABLE_SIZE;
context->hd_tablelen = 0; context->hd_tablelen = 0;
context->emit_set = NULL; context->emit_set = malloc(sizeof(nghttp2_hd_entry*)*
context->emit_set_capacity = 0; NGHTTP2_INITIAL_EMIT_SET_SIZE);
if(context->emit_set == NULL) {
free(context->hd_table);
return NGHTTP2_ERR_NOMEM;
}
memset(context->emit_set, 0, sizeof(nghttp2_hd_entry*)*
NGHTTP2_INITIAL_EMIT_SET_SIZE);
context->emit_set_capacity = NGHTTP2_INITIAL_EMIT_SET_SIZE;
context->emit_setlen = 0; context->emit_setlen = 0;
if(side == NGHTTP2_HD_SIDE_CLIENT) { if(side == NGHTTP2_HD_SIDE_CLIENT) {
@ -190,6 +197,7 @@ static int nghttp2_hd_context_init(nghttp2_hd_context *context,
nghttp2_hd_entry_free(context->hd_table[i]); nghttp2_hd_entry_free(context->hd_table[i]);
free(context->hd_table[i]); free(context->hd_table[i]);
} }
free(context->emit_set);
free(context->hd_table); free(context->hd_table);
return NGHTTP2_ERR_NOMEM; return NGHTTP2_ERR_NOMEM;
} }
@ -209,6 +217,11 @@ int nghttp2_hd_deflate_init(nghttp2_hd_context *deflater, nghttp2_hd_side side)
return nghttp2_hd_context_init(deflater, side); return nghttp2_hd_context_init(deflater, side);
} }
int nghttp2_hd_inflate_init(nghttp2_hd_context *inflater, nghttp2_hd_side side)
{
return nghttp2_hd_context_init(inflater, side^1);
}
static void nghttp2_hd_context_free(nghttp2_hd_context *context) static void nghttp2_hd_context_free(nghttp2_hd_context *context)
{ {
size_t i; size_t i;
@ -229,26 +242,6 @@ static void nghttp2_hd_context_free(nghttp2_hd_context *context)
free(context->hd_table); free(context->hd_table);
} }
int nghttp2_hd_inflate_init(nghttp2_hd_context *inflater, nghttp2_hd_side side)
{
int rv;
rv = nghttp2_hd_context_init(inflater, side^1);
if(rv != 0) {
return rv;
}
inflater->emit_set = malloc(sizeof(nghttp2_hd_entry*)*
NGHTTP2_INITIAL_EMIT_SET_SIZE);
if(inflater->emit_set == NULL) {
nghttp2_hd_context_free(inflater);
return NGHTTP2_ERR_NOMEM;
}
memset(inflater->emit_set, 0, sizeof(nghttp2_hd_entry*)*
NGHTTP2_INITIAL_EMIT_SET_SIZE);
inflater->emit_set_capacity = NGHTTP2_INITIAL_EMIT_SET_SIZE;
inflater->emit_setlen = 0;
return 0;
}
void nghttp2_hd_deflate_free(nghttp2_hd_context *deflater) void nghttp2_hd_deflate_free(nghttp2_hd_context *deflater)
{ {
nghttp2_hd_context_free(deflater); nghttp2_hd_context_free(deflater);
@ -713,14 +706,19 @@ ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_context *deflater,
nghttp2_hd_entry *ent; nghttp2_hd_entry *ent;
ent = find_in_hd_table(deflater, &nv[i]); ent = find_in_hd_table(deflater, &nv[i]);
if(ent) { if(ent) {
ent->flags |= NGHTTP2_HD_FLAG_EMIT;
if((ent->flags & NGHTTP2_HD_FLAG_REFSET) == 0) { if((ent->flags & NGHTTP2_HD_FLAG_REFSET) == 0) {
ent->flags |= NGHTTP2_HD_FLAG_REFSET; ent->flags |= NGHTTP2_HD_FLAG_REFSET | NGHTTP2_HD_FLAG_EMIT;
rv = emit_indexed_block(buf_ptr, buflen_ptr, &offset, ent->index); rv = emit_indexed_block(buf_ptr, buflen_ptr, &offset, ent->index);
} else {
/* The common header in reference set could be removed on
eviction. In that case, we have to add it again. The bad
thing is that we could not know it happens here. So defer
its processing after all headers are processed. */
rv = add_emit_set(deflater, ent);
}
if(rv < 0) { if(rv < 0) {
goto fail; goto fail;
} }
}
} else { } else {
uint8_t index = NGHTTP2_HD_INVALID_INDEX; uint8_t index = NGHTTP2_HD_INVALID_INDEX;
int incidx = 0; int incidx = 0;
@ -752,6 +750,34 @@ ssize_t nghttp2_hd_deflate_hd(nghttp2_hd_context *deflater,
} }
} }
for(i = 0; i < deflater->emit_setlen; ++i) {
nghttp2_hd_entry *ent = deflater->emit_set[i];
if((ent->flags & NGHTTP2_HD_FLAG_EMIT) == 0 &&
ent->index == NGHTTP2_HD_INVALID_INDEX) {
/* If common header is removed from the header table, use
incremental indexing. */
uint8_t index = NGHTTP2_HD_INVALID_INDEX;
nghttp2_hd_entry *new_ent;
nghttp2_hd_entry *name_ent = find_name_in_hd_table(deflater, &ent->nv);
if(name_ent) {
index = name_ent->index;
}
new_ent = add_hd_table_incremental(deflater, &ent->nv);
if(!new_ent) {
rv = NGHTTP2_ERR_HEADER_COMP;
goto fail;
}
new_ent->flags |= NGHTTP2_HD_FLAG_EMIT;
if(index == NGHTTP2_HD_INVALID_INDEX) {
rv = emit_newname_block(buf_ptr, buflen_ptr, &offset, &ent->nv, 1);
} else {
rv = emit_indname_block(buf_ptr, buflen_ptr, &offset, index,
ent->nv.value, ent->nv.valuelen, 1);
}
}
ent->flags |= NGHTTP2_HD_FLAG_EMIT;
}
for(i = 0; i < deflater->hd_tablelen; ++i) { for(i = 0; i < deflater->hd_tablelen; ++i) {
nghttp2_hd_entry *ent = deflater->hd_table[i]; nghttp2_hd_entry *ent = deflater->hd_table[i];
if(ent->flags & NGHTTP2_HD_FLAG_REFSET) { if(ent->flags & NGHTTP2_HD_FLAG_REFSET) {