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;
|
||||
}
|
||||
|
||||
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,
|
||||
nghttp2_nv **nva_ptr,
|
||||
uint8_t *in, size_t inlen)
|
||||
|
@ -1341,7 +1321,7 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_context *inflater,
|
|||
goto fail;
|
||||
}
|
||||
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) {
|
||||
DEBUGF(fprintf(stderr, "Name huffman decoding failed\n"));
|
||||
goto fail;
|
||||
|
@ -1369,7 +1349,7 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_context *inflater,
|
|||
goto fail;
|
||||
}
|
||||
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) {
|
||||
DEBUGF(fprintf(stderr, "Value huffman decoding failed\n"));
|
||||
free(decoded_huffman_name);
|
||||
|
@ -1453,7 +1433,7 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_context *inflater,
|
|||
goto fail;
|
||||
}
|
||||
if(value_huffman) {
|
||||
rv = inflate_decode(&value, in, valuelen, inflater->side);
|
||||
rv = nghttp2_hd_huff_decode(&value, in, valuelen, inflater->side);
|
||||
if(rv < 0) {
|
||||
DEBUGF(fprintf(stderr, "Value huffman decoding failed\n"));
|
||||
goto fail;
|
||||
|
|
|
@ -381,12 +381,11 @@ ssize_t nghttp2_hd_huff_decode_count(const uint8_t *src, size_t srclen,
|
|||
nghttp2_hd_side side);
|
||||
|
||||
/*
|
||||
* Decodes the given data |src| with length |srclen| to the given
|
||||
* memory location pointed by |dest|, allocated at lest |destlen|
|
||||
* bytes. The given input must be padded with the prefix of terminal
|
||||
* code. The caller is responsible to specify |destlen| at least the
|
||||
* length that nghttp2_hd_huff_decode_count() returns. If |side| is
|
||||
* NGHTTP2_HD_SIDE_REQUEST, the request huffman code table is
|
||||
* Decodes the given data |src| with length |srclen|. This function
|
||||
* allocates memory to store the result and assigns the its pointer to
|
||||
* |*dest_ptr| on success. The caller is responsible to release the
|
||||
* memory pointed by |*dest_ptr| if this function succeeds. If |side|
|
||||
* is NGHTTP2_HD_SIDE_REQUEST, the request huffman code table is
|
||||
* used. Otherwise, the response code table is used.
|
||||
*
|
||||
* 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|,
|
||||
* |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,
|
||||
nghttp2_hd_side side);
|
||||
|
||||
|
|
|
@ -213,7 +213,7 @@ ssize_t nghttp2_hd_huff_decode_count(const uint8_t *src, size_t srclen,
|
|||
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,
|
||||
nghttp2_hd_side side)
|
||||
{
|
||||
|
@ -221,6 +221,9 @@ ssize_t nghttp2_hd_huff_decode(uint8_t *dest, size_t destlen,
|
|||
size_t i, j;
|
||||
const nghttp2_huff_sym *huff_sym_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) {
|
||||
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;
|
||||
for(i = 0; i < srclen;) {
|
||||
int rv = huff_decode(src + i, srclen - i, bitoff,
|
||||
huff_sym_table, huff_decode_table);
|
||||
rv = huff_decode(src + i, srclen - i, bitoff,
|
||||
huff_sym_table, huff_decode_table);
|
||||
if(rv == -1) {
|
||||
if(check_last_byte(src, srclen, i, bitoff)) {
|
||||
break;
|
||||
}
|
||||
return -1;
|
||||
rv = NGHTTP2_ERR_HEADER_COMP;
|
||||
goto fail;
|
||||
}
|
||||
if(rv == 256) {
|
||||
/* 256 is special terminal symbol and it should not encoded in
|
||||
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;
|
||||
bitoff += huff_sym_table[rv].nbits;
|
||||
i += bitoff / 8;
|
||||
bitoff &= 0x7;
|
||||
}
|
||||
*dest_ptr = dest;
|
||||
return j;
|
||||
fail:
|
||||
free(dest);
|
||||
return rv;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue