nghttp2_hd: Use nghttp2_bufs, avoiding realloc()

This commit is contained in:
Tatsuhiro Tsujikawa 2014-03-11 21:18:28 +09:00
parent 7b2d585896
commit 3f56c938d8
7 changed files with 382 additions and 95 deletions

View File

@ -93,3 +93,200 @@ void nghttp2_buf_wrap_init(nghttp2_buf *buf, uint8_t *begin, size_t len)
buf->begin = buf->pos = buf->last = buf->mark = begin; buf->begin = buf->pos = buf->last = buf->mark = begin;
buf->end = begin + len; buf->end = begin + len;
} }
static int nghttp2_buf_chain_new(nghttp2_buf_chain **chain,
size_t chunk_length)
{
int rv;
*chain = malloc(sizeof(nghttp2_buf_chain));
if(*chain == NULL) {
return NGHTTP2_ERR_NOMEM;
}
(*chain)->next = NULL;
rv = nghttp2_buf_init2(&(*chain)->buf, chunk_length);
if(rv != 0) {
free(*chain);
return NGHTTP2_ERR_NOMEM;
}
return 0;
}
static void nghttp2_buf_chain_del(nghttp2_buf_chain *chain)
{
nghttp2_buf_free(&chain->buf);
free(chain);
}
int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length,
size_t max_chunk)
{
int rv;
nghttp2_buf_chain *chain;
if(max_chunk == 0) {
return NGHTTP2_ERR_INVALID_ARGUMENT;
}
rv = nghttp2_buf_chain_new(&chain, chunk_length);
if(rv != 0) {
return rv;
}
bufs->head = chain;
bufs->cur = bufs->head;
bufs->chunk_length = chunk_length;
bufs->chunk_left = max_chunk - 1;
return 0;
}
void nghttp2_bufs_free(nghttp2_bufs *bufs)
{
nghttp2_buf_chain *chain, *next_chain;
for(chain = bufs->head; chain;) {
next_chain = chain->next;
nghttp2_buf_chain_del(chain);
chain = next_chain;
}
}
static int nghttp2_bufs_avail(nghttp2_bufs *bufs)
{
return nghttp2_buf_avail(&bufs->cur->buf) +
bufs->chunk_left * bufs->chunk_left;
}
static int nghttp2_bufs_alloc_chain(nghttp2_bufs *bufs)
{
int rv;
nghttp2_buf_chain *chain;
if(bufs->cur->next) {
bufs->cur = bufs->cur->next;
return 0;
}
if(bufs->chunk_left == 0) {
return NGHTTP2_ERR_BUFFER_ERROR;
}
rv = nghttp2_buf_chain_new(&chain, bufs->chunk_length);
if(rv != 0) {
return rv;
}
--bufs->chunk_left;
bufs->cur->next = chain;
bufs->cur = chain;
return 0;
}
int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len)
{
int rv;
size_t nwrite;
nghttp2_buf *buf;
const uint8_t *p;
if((size_t)nghttp2_bufs_avail(bufs) < len) {
return NGHTTP2_ERR_BUFFER_ERROR;
}
p = data;
while(len) {
buf = &bufs->cur->buf;
nwrite = nghttp2_min((size_t)nghttp2_buf_avail(buf), len);
if(nwrite == 0) {
rv = nghttp2_bufs_alloc_chain(bufs);
if(rv != 0) {
return rv;
}
continue;
}
buf->last = nghttp2_cpymem(buf->last, p, nwrite);
p += len;
len -= nwrite;
}
return 0;
}
int nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b)
{
int rv;
nghttp2_buf *buf;
buf = &bufs->cur->buf;
if(nghttp2_buf_avail(buf) > 0) {
*buf->last++ = b;
return 0;
}
rv = nghttp2_bufs_alloc_chain(bufs);
if(rv != 0) {
return rv;
}
buf = &bufs->cur->buf;
*buf->last++ = b;
return 0;
}
ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out)
{
size_t len;
nghttp2_buf_chain *chain;
nghttp2_buf *buf;
uint8_t *res;
nghttp2_buf resbuf;
len = 0;
for(chain = bufs->head; chain; chain = chain->next) {
len += nghttp2_buf_len(&chain->buf);
}
res = malloc(len);
if(res == NULL) {
return NGHTTP2_ERR_NOMEM;
}
nghttp2_buf_wrap_init(&resbuf, res, len);
for(chain = bufs->head; chain; chain = chain->next) {
buf = &chain->buf;
resbuf.last = nghttp2_cpymem(resbuf.last, buf->pos, nghttp2_buf_len(buf));
nghttp2_buf_reset(buf);
}
bufs->cur = bufs->head;
*out = res;
return len;
}
void nghttp2_bufs_reset(nghttp2_bufs *bufs)
{
nghttp2_buf_chain *chain;
for(chain = bufs->head; chain; chain = chain->next) {
nghttp2_buf_reset(&chain->buf);
}
}

View File

@ -134,4 +134,39 @@ void nghttp2_buf_reset(nghttp2_buf *buf);
*/ */
void nghttp2_buf_wrap_init(nghttp2_buf *buf, uint8_t *begin, size_t len); void nghttp2_buf_wrap_init(nghttp2_buf *buf, uint8_t *begin, size_t len);
/*
* List of nghttp2_buf
*/
struct nghttp2_buf_chain;
typedef struct nghttp2_buf_chain nghttp2_buf_chain;
struct nghttp2_buf_chain {
nghttp2_buf_chain *next;
nghttp2_buf buf;
};
typedef struct {
nghttp2_buf_chain *head;
nghttp2_buf_chain *cur;
/* The buffer capacity of each buf */
size_t chunk_length;
/* The maximum number of nghttp2_buf_chain */
size_t chunk_left;
} nghttp2_bufs;
int nghttp2_bufs_init(nghttp2_bufs *bufs, size_t chunk_length,
size_t max_chunk);
void nghttp2_bufs_free(nghttp2_bufs *bufs);
int nghttp2_bufs_add(nghttp2_bufs *bufs, const void *data, size_t len);
int nghttp2_bufs_addb(nghttp2_bufs *bufs, uint8_t b);
ssize_t nghttp2_bufs_remove(nghttp2_bufs *bufs, uint8_t **out);
void nghttp2_bufs_reset(nghttp2_bufs *bufs);
#endif /* NGHTTP2_BUF_H */ #endif /* NGHTTP2_BUF_H */

View File

@ -341,8 +341,8 @@ int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater)
inflater->opcode = NGHTTP2_HD_OPCODE_NONE; inflater->opcode = NGHTTP2_HD_OPCODE_NONE;
inflater->state = NGHTTP2_HD_STATE_OPCODE; inflater->state = NGHTTP2_HD_STATE_OPCODE;
nghttp2_buffer_init(&inflater->namebuf, NGHTTP2_HD_MAX_NAME); nghttp2_bufs_init(&inflater->namebufs, NGHTTP2_HD_MAX_NAME, 1);
nghttp2_buffer_init(&inflater->valuebuf, NGHTTP2_HD_MAX_VALUE); nghttp2_bufs_init(&inflater->valuebufs, NGHTTP2_HD_MAX_VALUE / 2, 2);
inflater->huffman_encoded = 0; inflater->huffman_encoded = 0;
inflater->index = 0; inflater->index = 0;
inflater->left = 0; inflater->left = 0;
@ -379,8 +379,8 @@ void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater)
void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater) void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater)
{ {
hd_inflate_keep_free(inflater); hd_inflate_keep_free(inflater);
nghttp2_buffer_free(&inflater->namebuf); nghttp2_bufs_free(&inflater->namebufs);
nghttp2_buffer_free(&inflater->valuebuf); nghttp2_bufs_free(&inflater->valuebufs);
nghttp2_hd_context_free(&inflater->ctx); nghttp2_hd_context_free(&inflater->ctx);
} }
@ -410,7 +410,7 @@ static int emit_indexed_header(nghttp2_nv *nv_out, nghttp2_hd_entry *ent)
return 0; return 0;
} }
static int emit_newname_header(nghttp2_nv *nv_out, nghttp2_nv *nv) static int emit_literal_header(nghttp2_nv *nv_out, nghttp2_nv *nv)
{ {
DEBUGF(fprintf(stderr, "Header emission:\n")); DEBUGF(fprintf(stderr, "Header emission:\n"));
DEBUGF(fwrite(nv->name, nv->namelen, 1, stderr)); DEBUGF(fwrite(nv->name, nv->namelen, 1, stderr));
@ -421,21 +421,6 @@ static int emit_newname_header(nghttp2_nv *nv_out, nghttp2_nv *nv)
return 0; return 0;
} }
static int emit_indname_header(nghttp2_nv *nv_out, nghttp2_hd_entry *ent,
uint8_t *value, size_t valuelen)
{
DEBUGF(fprintf(stderr, "Header emission:\n"));
DEBUGF(fwrite(ent->nv.name, ent->nv.namelen, 1, stderr));
DEBUGF(fprintf(stderr, ": "));
DEBUGF(fwrite(value, valuelen, 1, stderr));
DEBUGF(fprintf(stderr, "\n"));
nv_out->name = ent->nv.name;
nv_out->namelen = ent->nv.namelen;
nv_out->value = value;
nv_out->valuelen = valuelen;
return 0;
}
static int ensure_write_buffer(nghttp2_buf *buf, size_t need) static int ensure_write_buffer(nghttp2_buf *buf, size_t need)
{ {
int rv; int rv;
@ -1234,7 +1219,7 @@ static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater,
* Huffman decoding failed * Huffman decoding failed
*/ */
static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater, static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
nghttp2_buffer *buffer, nghttp2_bufs *bufs,
uint8_t *in, uint8_t *last) uint8_t *in, uint8_t *last)
{ {
int rv; int rv;
@ -1243,7 +1228,7 @@ static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
last = in + inflater->left; last = in + inflater->left;
final = 1; final = 1;
} }
rv = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, buffer, rv = nghttp2_hd_huff_decode(&inflater->huff_decode_ctx, bufs,
in, last - in, final); in, last - in, final);
if(rv == NGHTTP2_ERR_BUFFER_ERROR) { if(rv == NGHTTP2_ERR_BUFFER_ERROR) {
return NGHTTP2_ERR_HEADER_COMP; return NGHTTP2_ERR_HEADER_COMP;
@ -1269,12 +1254,12 @@ static ssize_t hd_inflate_read_huff(nghttp2_hd_inflater *inflater,
* Header decompression failed * Header decompression failed
*/ */
static ssize_t hd_inflate_read(nghttp2_hd_inflater *inflater, static ssize_t hd_inflate_read(nghttp2_hd_inflater *inflater,
nghttp2_buffer *buffer, nghttp2_bufs *bufs,
uint8_t *in, uint8_t *last) uint8_t *in, uint8_t *last)
{ {
int rv; int rv;
size_t len = nghttp2_min(last - in, inflater->left); size_t len = nghttp2_min(last - in, inflater->left);
rv = nghttp2_buffer_add(buffer, in, len); rv = nghttp2_bufs_add(bufs, in, len);
if(rv == NGHTTP2_ERR_BUFFER_ERROR) { if(rv == NGHTTP2_ERR_BUFFER_ERROR) {
return NGHTTP2_ERR_HEADER_COMP; return NGHTTP2_ERR_HEADER_COMP;
} }
@ -1325,6 +1310,35 @@ static int hd_inflate_commit_indexed(nghttp2_hd_inflater *inflater,
return 1; return 1;
} }
static int hd_inflate_remove_bufs(nghttp2_hd_inflater *inflater,
nghttp2_nv *nv, int value_only)
{
ssize_t rv;
if(value_only) {
nv->name = NULL;
} else {
rv = nghttp2_bufs_remove(&inflater->namebufs, &nv->name);
if(rv < 0) {
return NGHTTP2_ERR_NOMEM;
}
nv->namelen = rv;
}
rv = nghttp2_bufs_remove(&inflater->valuebufs, &nv->value);
if(rv < 0) {
free(nv->name);
return NGHTTP2_ERR_NOMEM;
}
nv->valuelen = rv;
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
@ -1339,32 +1353,42 @@ static int hd_inflate_commit_indexed(nghttp2_hd_inflater *inflater,
static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater, static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
nghttp2_nv *nv_out) nghttp2_nv *nv_out)
{ {
nghttp2_nv nv = { int rv;
inflater->namebuf.buf, nghttp2_nv nv;
inflater->valuebuf.buf,
inflater->namebuf.len, rv = hd_inflate_remove_bufs(inflater, &nv, 0 /* name and value */);
inflater->valuebuf.len if(rv != 0) {
};
if(inflater->index_required) {
nghttp2_hd_entry *new_ent;
uint8_t ent_flags =
NGHTTP2_HD_FLAG_NAME_ALLOC | NGHTTP2_HD_FLAG_VALUE_ALLOC |
NGHTTP2_HD_FLAG_NAME_GIFT | NGHTTP2_HD_FLAG_VALUE_GIFT;
new_ent = add_hd_table_incremental(&inflater->ctx, NULL, &nv, ent_flags);
if(new_ent) {
nghttp2_buffer_release(&inflater->namebuf);
nghttp2_buffer_release(&inflater->valuebuf);
emit_indexed_header(nv_out, new_ent);
inflater->ent_keep = new_ent;
return 0;
}
return NGHTTP2_ERR_NOMEM; return NGHTTP2_ERR_NOMEM;
} }
emit_newname_header(nv_out, &nv);
inflater->name_keep = inflater->namebuf.buf; if(inflater->index_required) {
nghttp2_buffer_release(&inflater->namebuf); nghttp2_hd_entry *new_ent;
inflater->value_keep = inflater->valuebuf.buf; uint8_t ent_flags;
nghttp2_buffer_release(&inflater->valuebuf);
ent_flags =
NGHTTP2_HD_FLAG_NAME_ALLOC | NGHTTP2_HD_FLAG_VALUE_ALLOC |
NGHTTP2_HD_FLAG_NAME_GIFT | NGHTTP2_HD_FLAG_VALUE_GIFT;
new_ent = add_hd_table_incremental(&inflater->ctx, NULL, &nv, ent_flags);
if(new_ent) {
emit_indexed_header(nv_out, new_ent);
inflater->ent_keep = new_ent;
return 0;
}
free(nv.name);
free(nv.value);
return NGHTTP2_ERR_NOMEM;
}
emit_literal_header(nv_out, &nv);
inflater->name_keep = nv.name;
inflater->value_keep = nv.value;
return 0; return 0;
} }
@ -1382,12 +1406,24 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater, static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
nghttp2_nv *nv_out) nghttp2_nv *nv_out)
{ {
if(inflater->index_required) { int rv;
nghttp2_nv nv; nghttp2_nv nv;
rv = hd_inflate_remove_bufs(inflater, &nv, 1 /* value only */);
if(rv != 0) {
return NGHTTP2_ERR_NOMEM;
}
nv.name = inflater->ent_name->nv.name;
nv.namelen = inflater->ent_name->nv.namelen;
if(inflater->index_required) {
nghttp2_hd_entry *new_ent; nghttp2_hd_entry *new_ent;
uint8_t ent_flags = NGHTTP2_HD_FLAG_VALUE_ALLOC | uint8_t ent_flags;
NGHTTP2_HD_FLAG_VALUE_GIFT; int static_name;
int static_name = inflater->index >= inflater->ctx.hd_table.len;
ent_flags = NGHTTP2_HD_FLAG_VALUE_ALLOC | NGHTTP2_HD_FLAG_VALUE_GIFT;
static_name = inflater->index >= inflater->ctx.hd_table.len;
if(!static_name) { if(!static_name) {
ent_flags |= NGHTTP2_HD_FLAG_NAME_ALLOC; ent_flags |= NGHTTP2_HD_FLAG_NAME_ALLOC;
@ -1395,34 +1431,34 @@ static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
is shared by threads */ is shared by threads */
++inflater->ent_name->ref; ++inflater->ent_name->ref;
} }
nv.name = inflater->ent_name->nv.name;
nv.namelen = inflater->ent_name->nv.namelen;
nv.value = inflater->valuebuf.buf;
nv.valuelen = inflater->valuebuf.len;
new_ent = add_hd_table_incremental(&inflater->ctx, NULL, &nv, ent_flags); new_ent = add_hd_table_incremental(&inflater->ctx, NULL, &nv, ent_flags);
if(!static_name && --inflater->ent_name->ref == 0) { if(!static_name && --inflater->ent_name->ref == 0) {
nghttp2_hd_entry_free(inflater->ent_name); nghttp2_hd_entry_free(inflater->ent_name);
free(inflater->ent_name); free(inflater->ent_name);
} }
inflater->ent_name = NULL; inflater->ent_name = NULL;
if(new_ent) { if(new_ent) {
nghttp2_buffer_release(&inflater->valuebuf);
emit_indexed_header(nv_out, new_ent); emit_indexed_header(nv_out, new_ent);
inflater->ent_keep = new_ent; inflater->ent_keep = new_ent;
return 0; return 0;
} }
free(nv.value);
return NGHTTP2_ERR_NOMEM; return NGHTTP2_ERR_NOMEM;
} }
emit_indname_header(nv_out, inflater->ent_name,
inflater->valuebuf.buf, inflater->valuebuf.len);
inflater->value_keep = inflater->valuebuf.buf;
nghttp2_buffer_release(&inflater->valuebuf);
return 0;
}
static size_t guess_huff_decode_len(size_t encode_len) emit_literal_header(nv_out, &nv);
{
return encode_len * 3 / 2; inflater->value_keep = nv.value;
return 0;
} }
ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
@ -1562,48 +1598,53 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
inflater->left)); inflater->left));
return in - first; return in - first;
} }
rv = 0; rv = 0;
if(inflater->huffman_encoded) { if(inflater->huffman_encoded) {
nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx); nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
rv = nghttp2_buffer_reserve(&inflater->namebuf,
guess_huff_decode_len(inflater->left));
if(rv != 0) {
goto fail;
}
inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF; inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF;
} else { } else {
rv = nghttp2_buffer_reserve(&inflater->namebuf, inflater->left);
if(rv != 0) {
goto fail;
}
inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAME; inflater->state = NGHTTP2_HD_STATE_NEWNAME_READ_NAME;
} }
break; break;
case NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF: case NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF:
rv = hd_inflate_read_huff(inflater, &inflater->namebuf, in, last); rv = hd_inflate_read_huff(inflater, &inflater->namebufs, in, last);
if(rv < 0) { if(rv < 0) {
goto fail; goto fail;
} }
in += rv; in += rv;
DEBUGF(fprintf(stderr, "%zd bytes read\n", rv)); DEBUGF(fprintf(stderr, "%zd bytes read\n", rv));
if(inflater->left) { if(inflater->left) {
DEBUGF(fprintf(stderr, "still %zd bytes to go\n", inflater->left)); DEBUGF(fprintf(stderr, "still %zd bytes to go\n", inflater->left));
return in - first; return in - first;
} }
inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN; inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
break; break;
case NGHTTP2_HD_STATE_NEWNAME_READ_NAME: case NGHTTP2_HD_STATE_NEWNAME_READ_NAME:
rv = hd_inflate_read(inflater, &inflater->namebuf, in, last); rv = hd_inflate_read(inflater, &inflater->namebufs, in, last);
if(rv < 0) { if(rv < 0) {
goto fail; goto fail;
} }
in += rv; in += rv;
DEBUGF(fprintf(stderr, "%zd bytes read\n", rv)); DEBUGF(fprintf(stderr, "%zd bytes read\n", rv));
if(inflater->left) { if(inflater->left) {
DEBUGF(fprintf(stderr, "still %zd bytes to go\n", inflater->left)); DEBUGF(fprintf(stderr, "still %zd bytes to go\n", inflater->left));
return in - first; return in - first;
} }
inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN; inflater->state = NGHTTP2_HD_STATE_CHECK_VALUELEN;
break; break;
case NGHTTP2_HD_STATE_CHECK_VALUELEN: case NGHTTP2_HD_STATE_CHECK_VALUELEN:
hd_inflate_set_huffman_encoded(inflater, in); hd_inflate_set_huffman_encoded(inflater, in);
@ -1619,10 +1660,13 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
if(rv < 0) { if(rv < 0) {
goto fail; goto fail;
} }
in += rv; in += rv;
if(!rfin) { if(!rfin) {
return in - first; return in - first;
} }
DEBUGF(fprintf(stderr, "valuelen=%zd\n", inflater->left)); DEBUGF(fprintf(stderr, "valuelen=%zd\n", inflater->left));
if(inflater->left == 0) { if(inflater->left == 0) {
if(inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) { if(inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
@ -1637,64 +1681,75 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
*inflate_flags |= NGHTTP2_HD_INFLATE_EMIT; *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
return in - first; return in - first;
} }
if(inflater->huffman_encoded) { if(inflater->huffman_encoded) {
nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx); nghttp2_hd_huff_decode_context_init(&inflater->huff_decode_ctx);
rv = nghttp2_buffer_reserve(&inflater->valuebuf,
guess_huff_decode_len(inflater->left));
inflater->state = NGHTTP2_HD_STATE_READ_VALUEHUFF; inflater->state = NGHTTP2_HD_STATE_READ_VALUEHUFF;
} else { } else {
rv = nghttp2_buffer_reserve(&inflater->valuebuf, inflater->left);
if(rv != 0) {
goto fail;
}
inflater->state = NGHTTP2_HD_STATE_READ_VALUE; inflater->state = NGHTTP2_HD_STATE_READ_VALUE;
} }
break; break;
case NGHTTP2_HD_STATE_READ_VALUEHUFF: case NGHTTP2_HD_STATE_READ_VALUEHUFF:
rv = hd_inflate_read_huff(inflater, &inflater->valuebuf, in, last); rv = hd_inflate_read_huff(inflater, &inflater->valuebufs, in, last);
if(rv < 0) { if(rv < 0) {
goto fail; goto fail;
} }
in += rv; in += rv;
DEBUGF(fprintf(stderr, "%zd bytes read\n", rv)); DEBUGF(fprintf(stderr, "%zd bytes read\n", rv));
if(inflater->left) { if(inflater->left) {
DEBUGF(fprintf(stderr, "still %zd bytes to go\n", inflater->left)); DEBUGF(fprintf(stderr, "still %zd bytes to go\n", inflater->left));
return in - first; return in - first;
} }
if(inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) { if(inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
rv = hd_inflate_commit_newname(inflater, nv_out); rv = hd_inflate_commit_newname(inflater, nv_out);
} else { } else {
rv = hd_inflate_commit_indname(inflater, nv_out); rv = hd_inflate_commit_indname(inflater, nv_out);
} }
if(rv != 0) { if(rv != 0) {
goto fail; goto fail;
} }
inflater->state = NGHTTP2_HD_STATE_OPCODE; inflater->state = NGHTTP2_HD_STATE_OPCODE;
*inflate_flags |= NGHTTP2_HD_INFLATE_EMIT; *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
return in - first; return in - first;
case NGHTTP2_HD_STATE_READ_VALUE: case NGHTTP2_HD_STATE_READ_VALUE:
rv = hd_inflate_read(inflater, &inflater->valuebuf, in, last); rv = hd_inflate_read(inflater, &inflater->valuebufs, in, last);
if(rv < 0) { if(rv < 0) {
DEBUGF(fprintf(stderr, "value read failure %zd: %s\n", DEBUGF(fprintf(stderr, "value read failure %zd: %s\n",
rv, nghttp2_strerror(rv))); rv, nghttp2_strerror(rv)));
goto fail; goto fail;
} }
in += rv; in += rv;
DEBUGF(fprintf(stderr, "%zd bytes read\n", rv)); DEBUGF(fprintf(stderr, "%zd bytes read\n", rv));
if(inflater->left) { if(inflater->left) {
DEBUGF(fprintf(stderr, "still %zd bytes to go\n", inflater->left)); DEBUGF(fprintf(stderr, "still %zd bytes to go\n", inflater->left));
return in - first; return in - first;
} }
if(inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) { if(inflater->opcode == NGHTTP2_HD_OPCODE_NEWNAME) {
rv = hd_inflate_commit_newname(inflater, nv_out); rv = hd_inflate_commit_newname(inflater, nv_out);
} else { } else {
rv = hd_inflate_commit_indname(inflater, nv_out); rv = hd_inflate_commit_indname(inflater, nv_out);
} }
if(rv != 0) { if(rv != 0) {
goto fail; goto fail;
} }
inflater->state = NGHTTP2_HD_STATE_OPCODE; inflater->state = NGHTTP2_HD_STATE_OPCODE;
*inflate_flags |= NGHTTP2_HD_INFLATE_EMIT; *inflate_flags |= NGHTTP2_HD_INFLATE_EMIT;
return in - first; return in - first;
} }
} }

View File

@ -32,7 +32,6 @@
#include <nghttp2/nghttp2.h> #include <nghttp2/nghttp2.h>
#include "nghttp2_hd_huffman.h" #include "nghttp2_hd_huffman.h"
#include "nghttp2_buffer.h"
#include "nghttp2_buf.h" #include "nghttp2_buf.h"
#define NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE (1 << 12) #define NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE (1 << 12)
@ -41,7 +40,7 @@
/* The maximum value length of name/value pair. This is not specified /* The maximum value length of name/value pair. This is not specified
by the spec. We just chose the arbitrary size */ by the spec. We just chose the arbitrary size */
#define NGHTTP2_HD_MAX_NAME 256 #define NGHTTP2_HD_MAX_NAME 256
#define NGHTTP2_HD_MAX_VALUE 4096 #define NGHTTP2_HD_MAX_VALUE 8192
#define NGHTTP2_HD_MAX_BUFFER_LENGTH (1 << 15) #define NGHTTP2_HD_MAX_BUFFER_LENGTH (1 << 15)
/* Default size of maximum table buffer size for encoder. Even if /* Default size of maximum table buffer size for encoder. Even if
@ -146,9 +145,9 @@ typedef struct {
typedef struct { typedef struct {
nghttp2_hd_context ctx; nghttp2_hd_context ctx;
/* header name buffer */ /* header name buffer */
nghttp2_buffer namebuf; nghttp2_bufs namebufs;
/* header value buffer */ /* header value buffer */
nghttp2_buffer valuebuf; nghttp2_bufs valuebufs;
/* Stores current state of huffman decoding */ /* Stores current state of huffman decoding */
nghttp2_hd_huff_decode_context huff_decode_ctx; nghttp2_hd_huff_decode_context huff_decode_ctx;
/* Pointer to the nghttp2_hd_entry which is used current header /* Pointer to the nghttp2_hd_entry which is used current header
@ -418,7 +417,8 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);
* be initialized by nghttp2_hd_huff_decode_context_init(). The result * be initialized by nghttp2_hd_huff_decode_context_init(). The result
* will be added to |dest|. This function may expand |dest| as * will be added to |dest|. This function may expand |dest| as
* needed. The caller is responsible to release the memory of |dest| * needed. The caller is responsible to release the memory of |dest|
* by calling nghttp2_buffer_free(). * by calling nghttp2_bufs_free() or export its content using
* nghttp2_bufs_remove().
* *
* The caller must set the |final| to nonzero if the given input is * The caller must set the |final| to nonzero if the given input is
* the final block. * the final block.
@ -436,7 +436,7 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);
* Decoding process has failed. * Decoding process has failed.
*/ */
ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx, ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
nghttp2_buffer *dest, nghttp2_bufs *bufs,
const uint8_t *src, size_t srclen, int final); const uint8_t *src, size_t srclen, int final);
#endif /* NGHTTP2_HD_H */ #endif /* NGHTTP2_HD_H */

View File

@ -104,7 +104,7 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx)
} }
ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx, ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
nghttp2_buffer *dest, nghttp2_bufs *bufs,
const uint8_t *src, size_t srclen, int final) const uint8_t *src, size_t srclen, int final)
{ {
size_t i, j; size_t i, j;
@ -119,7 +119,7 @@ ssize_t nghttp2_hd_huff_decode(nghttp2_hd_huff_decode_context *ctx,
return NGHTTP2_ERR_HEADER_COMP; return NGHTTP2_ERR_HEADER_COMP;
} }
if(t->flags & NGHTTP2_HUFF_SYM) { if(t->flags & NGHTTP2_HUFF_SYM) {
rv = nghttp2_buffer_add_byte(dest, t->sym); rv = nghttp2_bufs_addb(bufs, t->sym);
if(rv != 0) { if(rv != 0) {
return rv; return rv;
} }

View File

@ -383,7 +383,7 @@ int nghttp2_check_header_value(const uint8_t *value, size_t len)
return 1; return 1;
} }
uint8_t* nghttp2_cpymem(uint8_t *dest, uint8_t *src, size_t len) uint8_t* nghttp2_cpymem(uint8_t *dest, const void *src, size_t len)
{ {
memcpy(dest, src, len); memcpy(dest, src, len);

View File

@ -131,6 +131,6 @@ void nghttp2_free(void *ptr);
* by the |dest|, assuming that the |dest| is at lest |len| bytes long * by the |dest|, assuming that the |dest| is at lest |len| bytes long
* . Returns dest + len. * . Returns dest + len.
*/ */
uint8_t* nghttp2_cpymem(uint8_t *dest, uint8_t *src, size_t len); uint8_t* nghttp2_cpymem(uint8_t *dest, const void *src, size_t len);
#endif /* NGHTTP2_HELPER_H */ #endif /* NGHTTP2_HELPER_H */