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; 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) { void nghttp2_bufs_reset(nghttp2_bufs *bufs) {
nghttp2_buf_chain *chain, *ci; nghttp2_buf_chain *chain, *ci;
size_t k; 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); 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. * 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; 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 * Finalize literal header representation - new name- reception. If
* header is emitted, |*nv_out| is filled with that value and 0 is * 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; 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) { if (inflater->no_index) {
nv.flags = NGHTTP2_NV_FLAG_NO_INDEX; nv.flags = NGHTTP2_NV_FLAG_NO_INDEX;
} else { } 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); 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) { if (inflater->index_required) {
nghttp2_hd_entry *new_ent; nghttp2_hd_entry *new_ent;
uint8_t ent_flags; uint8_t ent_flags;
int static_name;
ent_flags = NGHTTP2_HD_FLAG_VALUE_ALLOC | NGHTTP2_HD_FLAG_VALUE_GIFT; if (inflater->index < NGHTTP2_STATIC_TABLE_LENGTH) {
static_name = 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_VALUE_ALLOC | NGHTTP2_HD_FLAG_VALUE_GIFT;
ent_flags |= NGHTTP2_HD_FLAG_NAME_ALLOC; } else {
/* For entry in static table, we must not touch ref, because it rv = hd_inflate_remove_bufs_with_name(inflater, &nv, ent_name);
is shared by threads */ if (rv != 0) {
++ent_name->ref; 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, new_ent = add_hd_table_incremental(&inflater->ctx, &nv, ent_name->token,
ent_flags); ent_flags);
if (!static_name && --ent_name->ref == 0) { /* At this point, ent_name might be deleted. */
nghttp2_hd_entry_free(ent_name, mem);
nghttp2_mem_free(mem, ent_name);
}
if (new_ent) { if (new_ent) {
emit_indexed_header(nv_out, token_out, 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; 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); emit_literal_header(nv_out, token_out, &nv);
if (nv.value != inflater->nvbufs.head->buf.pos) { if (nv.value != inflater->nvbufs.head->buf.pos) {