nghttp2_hd: Avoid nghttp2_hd_huff_decode_count
Huffman decoding is costly. It is faster to do geometric realloc than calling nghttp2_hd_huff_decode_count to know the length in advance.
This commit is contained in:
parent
ccd0f83018
commit
9eb031ce83
|
@ -1237,26 +1237,6 @@ static int inflater_post_process_hd_entry(nghttp2_hd_context *inflater,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static ssize_t inflate_decode(uint8_t **dest_ptr, uint8_t *in, size_t inlen,
|
|
||||||
nghttp2_hd_side side)
|
|
||||||
{
|
|
||||||
ssize_t declen;
|
|
||||||
if(inlen == 0) {
|
|
||||||
*dest_ptr = NULL;
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
declen = nghttp2_hd_huff_decode_count(in, inlen, side);
|
|
||||||
if(declen == -1) {
|
|
||||||
return NGHTTP2_ERR_HEADER_COMP;
|
|
||||||
}
|
|
||||||
*dest_ptr = malloc(declen);
|
|
||||||
if(*dest_ptr == NULL) {
|
|
||||||
return NGHTTP2_ERR_HEADER_COMP;
|
|
||||||
}
|
|
||||||
nghttp2_hd_huff_decode(*dest_ptr, declen, in, inlen, side);
|
|
||||||
return declen;
|
|
||||||
}
|
|
||||||
|
|
||||||
ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_context *inflater,
|
ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_context *inflater,
|
||||||
nghttp2_nv **nva_ptr,
|
nghttp2_nv **nva_ptr,
|
||||||
uint8_t *in, size_t inlen)
|
uint8_t *in, size_t inlen)
|
||||||
|
@ -1341,7 +1321,7 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_context *inflater,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if(name_huffman) {
|
if(name_huffman) {
|
||||||
rv = inflate_decode(&nv.name, in, namelen, inflater->side);
|
rv = nghttp2_hd_huff_decode(&nv.name, in, namelen, inflater->side);
|
||||||
if(rv < 0) {
|
if(rv < 0) {
|
||||||
DEBUGF(fprintf(stderr, "Name huffman decoding failed\n"));
|
DEBUGF(fprintf(stderr, "Name huffman decoding failed\n"));
|
||||||
goto fail;
|
goto fail;
|
||||||
|
@ -1369,7 +1349,7 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_context *inflater,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if(value_huffman) {
|
if(value_huffman) {
|
||||||
rv = inflate_decode(&nv.value, in, valuelen, inflater->side);
|
rv = nghttp2_hd_huff_decode(&nv.value, in, valuelen, inflater->side);
|
||||||
if(rv < 0) {
|
if(rv < 0) {
|
||||||
DEBUGF(fprintf(stderr, "Value huffman decoding failed\n"));
|
DEBUGF(fprintf(stderr, "Value huffman decoding failed\n"));
|
||||||
free(decoded_huffman_name);
|
free(decoded_huffman_name);
|
||||||
|
@ -1453,7 +1433,7 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_context *inflater,
|
||||||
goto fail;
|
goto fail;
|
||||||
}
|
}
|
||||||
if(value_huffman) {
|
if(value_huffman) {
|
||||||
rv = inflate_decode(&value, in, valuelen, inflater->side);
|
rv = nghttp2_hd_huff_decode(&value, in, valuelen, inflater->side);
|
||||||
if(rv < 0) {
|
if(rv < 0) {
|
||||||
DEBUGF(fprintf(stderr, "Value huffman decoding failed\n"));
|
DEBUGF(fprintf(stderr, "Value huffman decoding failed\n"));
|
||||||
goto fail;
|
goto fail;
|
||||||
|
|
|
@ -381,12 +381,11 @@ ssize_t nghttp2_hd_huff_decode_count(const uint8_t *src, size_t srclen,
|
||||||
nghttp2_hd_side side);
|
nghttp2_hd_side side);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Decodes the given data |src| with length |srclen| to the given
|
* Decodes the given data |src| with length |srclen|. This function
|
||||||
* memory location pointed by |dest|, allocated at lest |destlen|
|
* allocates memory to store the result and assigns the its pointer to
|
||||||
* bytes. The given input must be padded with the prefix of terminal
|
* |*dest_ptr| on success. The caller is responsible to release the
|
||||||
* code. The caller is responsible to specify |destlen| at least the
|
* memory pointed by |*dest_ptr| if this function succeeds. If |side|
|
||||||
* length that nghttp2_hd_huff_decode_count() returns. If |side| is
|
* is NGHTTP2_HD_SIDE_REQUEST, the request huffman code table is
|
||||||
* NGHTTP2_HD_SIDE_REQUEST, the request huffman code table is
|
|
||||||
* used. Otherwise, the response code table is used.
|
* used. Otherwise, the response code table is used.
|
||||||
*
|
*
|
||||||
* This function returns the number of written bytes. This return
|
* This function returns the number of written bytes. This return
|
||||||
|
@ -394,9 +393,15 @@ ssize_t nghttp2_hd_huff_decode_count(const uint8_t *src, size_t srclen,
|
||||||
* nghttp2_hd_huff_decode_count() if it is given with the same |src|,
|
* nghttp2_hd_huff_decode_count() if it is given with the same |src|,
|
||||||
* |srclen|, and |side|.
|
* |srclen|, and |side|.
|
||||||
*
|
*
|
||||||
* This function returns -1 if it fails.
|
* If this function fails, it returns one of the following negative
|
||||||
|
* return codes:
|
||||||
|
*
|
||||||
|
* NGHTTP2_ERR_NOMEM
|
||||||
|
* Out of memory.
|
||||||
|
* NGHTTP2_ERR_HEADER_COMP
|
||||||
|
* Decoding process has failed.
|
||||||
*/
|
*/
|
||||||
ssize_t nghttp2_hd_huff_decode(uint8_t *dest, size_t destlen,
|
ssize_t nghttp2_hd_huff_decode(uint8_t **dest_ptr,
|
||||||
const uint8_t *src, size_t srclen,
|
const uint8_t *src, size_t srclen,
|
||||||
nghttp2_hd_side side);
|
nghttp2_hd_side side);
|
||||||
|
|
||||||
|
|
|
@ -213,7 +213,7 @@ ssize_t nghttp2_hd_huff_decode_count(const uint8_t *src, size_t srclen,
|
||||||
return j;
|
return j;
|
||||||
}
|
}
|
||||||
|
|
||||||
ssize_t nghttp2_hd_huff_decode(uint8_t *dest, size_t destlen,
|
ssize_t nghttp2_hd_huff_decode(uint8_t **dest_ptr,
|
||||||
const uint8_t *src, size_t srclen,
|
const uint8_t *src, size_t srclen,
|
||||||
nghttp2_hd_side side)
|
nghttp2_hd_side side)
|
||||||
{
|
{
|
||||||
|
@ -221,6 +221,9 @@ ssize_t nghttp2_hd_huff_decode(uint8_t *dest, size_t destlen,
|
||||||
size_t i, j;
|
size_t i, j;
|
||||||
const nghttp2_huff_sym *huff_sym_table;
|
const nghttp2_huff_sym *huff_sym_table;
|
||||||
const huff_decode_table_type *huff_decode_table;
|
const huff_decode_table_type *huff_decode_table;
|
||||||
|
uint8_t *dest = NULL;
|
||||||
|
size_t destlen = 0;
|
||||||
|
int rv;
|
||||||
|
|
||||||
if(side == NGHTTP2_HD_SIDE_REQUEST) {
|
if(side == NGHTTP2_HD_SIDE_REQUEST) {
|
||||||
huff_sym_table = req_huff_sym_table;
|
huff_sym_table = req_huff_sym_table;
|
||||||
|
@ -231,23 +234,39 @@ ssize_t nghttp2_hd_huff_decode(uint8_t *dest, size_t destlen,
|
||||||
}
|
}
|
||||||
j = 0;
|
j = 0;
|
||||||
for(i = 0; i < srclen;) {
|
for(i = 0; i < srclen;) {
|
||||||
int rv = huff_decode(src + i, srclen - i, bitoff,
|
rv = huff_decode(src + i, srclen - i, bitoff,
|
||||||
huff_sym_table, huff_decode_table);
|
huff_sym_table, huff_decode_table);
|
||||||
if(rv == -1) {
|
if(rv == -1) {
|
||||||
if(check_last_byte(src, srclen, i, bitoff)) {
|
if(check_last_byte(src, srclen, i, bitoff)) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
return -1;
|
rv = NGHTTP2_ERR_HEADER_COMP;
|
||||||
|
goto fail;
|
||||||
}
|
}
|
||||||
if(rv == 256) {
|
if(rv == 256) {
|
||||||
/* 256 is special terminal symbol and it should not encoded in
|
/* 256 is special terminal symbol and it should not encoded in
|
||||||
byte string. */
|
byte string. */
|
||||||
return -1;
|
rv = NGHTTP2_ERR_HEADER_COMP;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
if(j == destlen) {
|
||||||
|
size_t new_len = j == 0 ? 32 : j * 2;
|
||||||
|
uint8_t *new_dest = realloc(dest, new_len);
|
||||||
|
if(new_dest == NULL) {
|
||||||
|
rv = NGHTTP2_ERR_NOMEM;
|
||||||
|
goto fail;
|
||||||
|
}
|
||||||
|
dest = new_dest;
|
||||||
|
destlen = new_len;
|
||||||
}
|
}
|
||||||
dest[j++] = rv;
|
dest[j++] = rv;
|
||||||
bitoff += huff_sym_table[rv].nbits;
|
bitoff += huff_sym_table[rv].nbits;
|
||||||
i += bitoff / 8;
|
i += bitoff / 8;
|
||||||
bitoff &= 0x7;
|
bitoff &= 0x7;
|
||||||
}
|
}
|
||||||
|
*dest_ptr = dest;
|
||||||
return j;
|
return j;
|
||||||
|
fail:
|
||||||
|
free(dest);
|
||||||
|
return rv;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue