Allocate field name and value in the same buffer if indname to dynamic table

This commit is contained in:
Tatsuhiro Tsujikawa 2015-04-26 18:43:24 +09:00
parent c41f413978
commit 02468b1ca1
3 changed files with 90 additions and 20 deletions

View File

@ -432,6 +432,24 @@ ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out) {
return (ssize_t)len;
}
size_t nghttp2_bufs_remove_copy(nghttp2_bufs *bufs, uint8_t *out) {
size_t len;
nghttp2_buf_chain *chain;
nghttp2_buf *buf;
nghttp2_buf resbuf;
len = nghttp2_bufs_len(bufs);
nghttp2_buf_wrap_init(&resbuf, out, len);
for (chain = bufs->head; chain; chain = chain->next) {
buf = &chain->buf;
resbuf.last = nghttp2_cpymem(resbuf.last, buf->pos, nghttp2_buf_len(buf));
}
return len;
}
void nghttp2_bufs_reset(nghttp2_bufs *bufs) {
nghttp2_buf_chain *chain, *ci;
size_t k;

View File

@ -324,6 +324,17 @@ int nghttp2_bufs_orb_hold(nghttp2_bufs *bufs, uint8_t b);
*/
ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out);
/*
* Copies all data stored in |bufs| to |out|. This function assumes
* that the buffer space pointed by |out| has at least
* nghttp2_bufs(bufs) bytes.
*
* The contents of |bufs| is left unchanged.
*
* This function returns the length of copied data.
*/
size_t nghttp2_bufs_remove_copy(nghttp2_bufs *bufs, uint8_t *out);
/*
* Resets |bufs| and makes the buffers empty.
*/

View File

@ -1730,6 +1730,42 @@ static int hd_inflate_remove_bufs(nghttp2_hd_inflater *inflater, nghttp2_nv *nv,
return 0;
}
static int hd_inflate_remove_bufs_with_name(nghttp2_hd_inflater *inflater,
nghttp2_nv *nv,
nghttp2_hd_entry *ent_name) {
size_t rv;
size_t buflen;
uint8_t *buf;
nghttp2_mem *mem;
mem = inflater->ctx.mem;
/* Allocate buffer including name in ent_name, plus terminating
NULL. */
buflen = ent_name->nv.namelen + 1 + nghttp2_bufs_len(&inflater->nvbufs);
buf = nghttp2_mem_malloc(mem, buflen);
if (buf == NULL) {
return NGHTTP2_ERR_NOMEM;
}
/* Copy including terminal NULL */
memcpy(buf, ent_name->nv.name, ent_name->nv.namelen + 1);
rv = nghttp2_bufs_remove_copy(&inflater->nvbufs,
buf + ent_name->nv.namelen + 1);
assert(ent_name->nv.namelen + 1 + rv == buflen);
nghttp2_bufs_reset(&inflater->nvbufs);
nv->name = buf;
nv->namelen = ent_name->nv.namelen;
nv->value = buf + nv->namelen + 1;
nv->valuelen = buflen - nv->namelen - 2;
return 0;
}
/*
* Finalize literal header representation - new name- reception. If
* header is emitted, |*nv_out| is filled with that value and 0 is
@ -1813,11 +1849,6 @@ static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
mem = inflater->ctx.mem;
rv = hd_inflate_remove_bufs(inflater, &nv, 1 /* value only */);
if (rv != 0) {
return NGHTTP2_ERR_NOMEM;
}
if (inflater->no_index) {
nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
} else {
@ -1826,31 +1857,33 @@ static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
ent_name = nghttp2_hd_table_get(&inflater->ctx, inflater->index);
nv.name = ent_name->nv.name;
nv.namelen = ent_name->nv.namelen;
if (inflater->index_required) {
nghttp2_hd_entry *new_ent;
uint8_t ent_flags;
int static_name;
ent_flags = NGHTTP2_HD_FLAG_VALUE_ALLOC | NGHTTP2_HD_FLAG_VALUE_GIFT;
static_name = inflater->index < NGHTTP2_STATIC_TABLE_LENGTH;
if (inflater->index < NGHTTP2_STATIC_TABLE_LENGTH) {
/* We don't copy name in static table */
rv = hd_inflate_remove_bufs(inflater, &nv, 1 /* value only */);
if (rv != 0) {
return NGHTTP2_ERR_NOMEM;
}
nv.name = ent_name->nv.name;
nv.namelen = ent_name->nv.namelen;
if (!static_name) {
ent_flags |= NGHTTP2_HD_FLAG_NAME_ALLOC;
/* For entry in static table, we must not touch ref, because it
is shared by threads */
++ent_name->ref;
ent_flags = NGHTTP2_HD_FLAG_VALUE_ALLOC | NGHTTP2_HD_FLAG_VALUE_GIFT;
} else {
rv = hd_inflate_remove_bufs_with_name(inflater, &nv, ent_name);
if (rv != 0) {
return NGHTTP2_ERR_NOMEM;
}
/* nv->name and nv->value are in the same buffer. */
ent_flags = NGHTTP2_HD_FLAG_NAME_ALLOC | NGHTTP2_HD_FLAG_NAME_GIFT;
}
new_ent = add_hd_table_incremental(&inflater->ctx, &nv, ent_name->token,
ent_flags);
if (!static_name && --ent_name->ref == 0) {
nghttp2_hd_entry_free(ent_name, mem);
nghttp2_mem_free(mem, ent_name);
}
/* At this point, ent_name might be deleted. */
if (new_ent) {
emit_indexed_header(nv_out, token_out, new_ent);
@ -1865,6 +1898,14 @@ static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
return NGHTTP2_ERR_NOMEM;
}
rv = hd_inflate_remove_bufs(inflater, &nv, 1 /* value only */);
if (rv != 0) {
return NGHTTP2_ERR_NOMEM;
}
nv.name = ent_name->nv.name;
nv.namelen = ent_name->nv.namelen;
emit_literal_header(nv_out, token_out, &nv);
if (nv.value != inflater->nvbufs.head->buf.pos) {