Commit 3f56c938 authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

nghttp2_hd: Use nghttp2_bufs, avoiding realloc()

parent 7b2d5858
......@@ -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->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);
}
}
......@@ -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);
/*
* 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 */
This diff is collapsed.
......@@ -32,7 +32,6 @@
#include <nghttp2/nghttp2.h>
#include "nghttp2_hd_huffman.h"
#include "nghttp2_buffer.h"
#include "nghttp2_buf.h"
#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
by the spec. We just chose the arbitrary size */
#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)
/* Default size of maximum table buffer size for encoder. Even if
......@@ -146,9 +145,9 @@ typedef struct {
typedef struct {
nghttp2_hd_context ctx;
/* header name buffer */
nghttp2_buffer namebuf;
nghttp2_bufs namebufs;
/* header value buffer */
nghttp2_buffer valuebuf;
nghttp2_bufs valuebufs;
/* Stores current state of huffman decoding */
nghttp2_hd_huff_decode_context huff_decode_ctx;
/* 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
* will be added to |dest|. This function may expand |dest| as
* 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 final block.
......@@ -436,7 +436,7 @@ void nghttp2_hd_huff_decode_context_init(nghttp2_hd_huff_decode_context *ctx);
* Decoding process has failed.
*/
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);
#endif /* NGHTTP2_HD_H */
......@@ -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,
nghttp2_buffer *dest,
nghttp2_bufs *bufs,
const uint8_t *src, size_t srclen, int final)
{
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;
}
if(t->flags & NGHTTP2_HUFF_SYM) {
rv = nghttp2_buffer_add_byte(dest, t->sym);
rv = nghttp2_bufs_addb(bufs, t->sym);
if(rv != 0) {
return rv;
}
......
......@@ -383,7 +383,7 @@ int nghttp2_check_header_value(const uint8_t *value, size_t len)
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);
......
......@@ -131,6 +131,6 @@ void nghttp2_free(void *ptr);
* by the |dest|, assuming that the |dest| is at lest |len| bytes long
* . 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 */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment