Add nghttp2_hd_inflate_hd2() and deprecate nghttp2_hd_inflate_hd()

The difference between them are former has const qualifier to the |in|
parameter, which is desirable since it is effectively read-only.
This commit is contained in:
Tatsuhiro Tsujikawa 2016-05-14 18:25:20 +09:00
parent 796160cb77
commit 2a96d433ec
8 changed files with 125 additions and 29 deletions

View File

@ -47,6 +47,7 @@ APIDOCS= \
nghttp2_hd_inflate_get_num_table_entries.rst \ nghttp2_hd_inflate_get_num_table_entries.rst \
nghttp2_hd_inflate_get_table_entry.rst \ nghttp2_hd_inflate_get_table_entry.rst \
nghttp2_hd_inflate_hd.rst \ nghttp2_hd_inflate_hd.rst \
nghttp2_hd_inflate_hd2.rst \
nghttp2_hd_inflate_new.rst \ nghttp2_hd_inflate_new.rst \
nghttp2_hd_inflate_new2.rst \ nghttp2_hd_inflate_new2.rst \
nghttp2_http2_strerror.rst \ nghttp2_http2_strerror.rst \

View File

@ -4553,7 +4553,7 @@ NGHTTP2_EXTERN void nghttp2_hd_inflate_del(nghttp2_hd_inflater *inflater);
* This function must not be called while header block is being * This function must not be called while header block is being
* inflated. In other words, this function must be called after * inflated. In other words, this function must be called after
* initialization of |inflater|, but before calling * initialization of |inflater|, but before calling
* `nghttp2_hd_inflate_hd()`, or after * `nghttp2_hd_inflate_hd2()`, or after
* `nghttp2_hd_inflate_end_headers()`. Otherwise, * `nghttp2_hd_inflate_end_headers()`. Otherwise,
* `NGHTTP2_ERR_INVALID_STATE` was returned. * `NGHTTP2_ERR_INVALID_STATE` was returned.
* *
@ -4594,6 +4594,10 @@ typedef enum {
/** /**
* @function * @function
* *
* .. warning::
*
* Deprecated. Use `nghttp2_hd_inflate_hd2()` instead.
*
* Inflates name/value block stored in |in| with length |inlen|. This * Inflates name/value block stored in |in| with length |inlen|. This
* function performs decompression. For each successful emission of * function performs decompression. For each successful emission of
* header name/value pair, :enum:`NGHTTP2_HD_INFLATE_EMIT` is set in * header name/value pair, :enum:`NGHTTP2_HD_INFLATE_EMIT` is set in
@ -4673,6 +4677,88 @@ NGHTTP2_EXTERN ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater,
int *inflate_flags, uint8_t *in, int *inflate_flags, uint8_t *in,
size_t inlen, int in_final); size_t inlen, int in_final);
/**
* @function
*
* Inflates name/value block stored in |in| with length |inlen|. This
* function performs decompression. For each successful emission of
* header name/value pair, :enum:`NGHTTP2_HD_INFLATE_EMIT` is set in
* |*inflate_flags| and name/value pair is assigned to the |nv_out|
* and the function returns. The caller must not free the members of
* |nv_out|.
*
* The |nv_out| may include pointers to the memory region in the |in|.
* The caller must retain the |in| while the |nv_out| is used.
*
* The application should call this function repeatedly until the
* ``(*inflate_flags) & NGHTTP2_HD_INFLATE_FINAL`` is nonzero and
* return value is non-negative. This means the all input values are
* processed successfully. Then the application must call
* `nghttp2_hd_inflate_end_headers()` to prepare for the next header
* block input.
*
* The caller can feed complete compressed header block. It also can
* feed it in several chunks. The caller must set |in_final| to
* nonzero if the given input is the last block of the compressed
* header.
*
* This function returns the number of bytes processed if it succeeds,
* or one of the following negative error codes:
*
* :enum:`NGHTTP2_ERR_NOMEM`
* Out of memory.
* :enum:`NGHTTP2_ERR_HEADER_COMP`
* Inflation process has failed.
* :enum:`NGHTTP2_ERR_BUFFER_ERROR`
* The header field name or value is too large.
*
* Example follows::
*
* int inflate_header_block(nghttp2_hd_inflater *hd_inflater,
* uint8_t *in, size_t inlen, int final)
* {
* ssize_t rv;
*
* for(;;) {
* nghttp2_nv nv;
* int inflate_flags = 0;
*
* rv = nghttp2_hd_inflate_hd2(hd_inflater, &nv, &inflate_flags,
* in, inlen, final);
*
* if(rv < 0) {
* fprintf(stderr, "inflate failed with error code %zd", rv);
* return -1;
* }
*
* in += rv;
* inlen -= rv;
*
* if(inflate_flags & NGHTTP2_HD_INFLATE_EMIT) {
* fwrite(nv.name, nv.namelen, 1, stderr);
* fprintf(stderr, ": ");
* fwrite(nv.value, nv.valuelen, 1, stderr);
* fprintf(stderr, "\n");
* }
* if(inflate_flags & NGHTTP2_HD_INFLATE_FINAL) {
* nghttp2_hd_inflate_end_headers(hd_inflater);
* break;
* }
* if((inflate_flags & NGHTTP2_HD_INFLATE_EMIT) == 0 &&
* inlen == 0) {
* break;
* }
* }
*
* return 0;
* }
*
*/
NGHTTP2_EXTERN ssize_t
nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out,
int *inflate_flags, const uint8_t *in, size_t inlen,
int in_final);
/** /**
* @function * @function
* *

View File

@ -862,11 +862,11 @@ static size_t encode_length(uint8_t *buf, size_t n, size_t prefix) {
* of bytes processed, or returns -1, indicating decoding error. * of bytes processed, or returns -1, indicating decoding error.
*/ */
static ssize_t decode_length(uint32_t *res, size_t *shift_ptr, int *final, static ssize_t decode_length(uint32_t *res, size_t *shift_ptr, int *final,
uint32_t initial, size_t shift, uint8_t *in, uint32_t initial, size_t shift, const uint8_t *in,
uint8_t *last, size_t prefix) { const uint8_t *last, size_t prefix) {
uint32_t k = (uint8_t)((1 << prefix) - 1); uint32_t k = (uint8_t)((1 << prefix) - 1);
uint32_t n = initial; uint32_t n = initial;
uint8_t *start = in; const uint8_t *start = in;
*shift_ptr = 0; *shift_ptr = 0;
*final = 0; *final = 0;
@ -1625,8 +1625,8 @@ static void hd_inflate_set_huffman_encoded(nghttp2_hd_inflater *inflater,
* Integer decoding failed * Integer decoding failed
*/ */
static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater, int *rfin, static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater, int *rfin,
uint8_t *in, uint8_t *last, size_t prefix, const uint8_t *in, const uint8_t *last,
size_t maxlen) { size_t prefix, size_t maxlen) {
ssize_t rv; ssize_t rv;
uint32_t out; uint32_t out;
@ -1667,8 +1667,8 @@ static ssize_t hd_inflate_read_len(nghttp2_hd_inflater *inflater, int *rfin,
* 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_buf *buf, uint8_t *in, nghttp2_buf *buf, const uint8_t *in,
uint8_t *last) { const uint8_t *last) {
ssize_t readlen; ssize_t readlen;
int final = 0; int final = 0;
if ((size_t)(last - in) >= inflater->left) { if ((size_t)(last - in) >= inflater->left) {
@ -1699,7 +1699,7 @@ 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, nghttp2_buf *buf, static ssize_t hd_inflate_read(nghttp2_hd_inflater *inflater, nghttp2_buf *buf,
uint8_t *in, uint8_t *last) { const uint8_t *in, const uint8_t *last) {
size_t len = nghttp2_min((size_t)(last - in), inflater->left); size_t len = nghttp2_min((size_t)(last - in), inflater->left);
buf->last = nghttp2_cpymem(buf->last, in, len); buf->last = nghttp2_cpymem(buf->last, in, len);
@ -1822,10 +1822,17 @@ static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out, ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out,
int *inflate_flags, uint8_t *in, size_t inlen, int *inflate_flags, uint8_t *in, size_t inlen,
int in_final) { int in_final) {
return nghttp2_hd_inflate_hd2(inflater, nv_out, inflate_flags, in, inlen,
in_final);
}
ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
nghttp2_nv *nv_out, int *inflate_flags,
const uint8_t *in, size_t inlen, int in_final) {
ssize_t rv; ssize_t rv;
nghttp2_hd_nv hd_nv; nghttp2_hd_nv hd_nv;
rv = nghttp2_hd_inflate_hd2(inflater, &hd_nv, inflate_flags, in, inlen, rv = nghttp2_hd_inflate_hd_nv(inflater, &hd_nv, inflate_flags, in, inlen,
in_final); in_final);
if (rv < 0) { if (rv < 0) {
@ -1845,12 +1852,13 @@ ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, nghttp2_nv *nv_out,
return rv; return rv;
} }
ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater, ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
nghttp2_hd_nv *nv_out, int *inflate_flags, nghttp2_hd_nv *nv_out, int *inflate_flags,
uint8_t *in, size_t inlen, int in_final) { const uint8_t *in, size_t inlen,
int in_final) {
ssize_t rv = 0; ssize_t rv = 0;
uint8_t *first = in; const uint8_t *first = in;
uint8_t *last = in + inlen; const uint8_t *last = in + inlen;
int rfin = 0; int rfin = 0;
int busy = 0; int busy = 0;
nghttp2_mem *mem; nghttp2_mem *mem;

View File

@ -353,9 +353,9 @@ void nghttp2_hd_inflate_free(nghttp2_hd_inflater *inflater);
* that return values and semantics are the same as * that return values and semantics are the same as
* nghttp2_hd_inflate_hd(). * nghttp2_hd_inflate_hd().
*/ */
ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater, ssize_t nghttp2_hd_inflate_hd_nv(nghttp2_hd_inflater *inflater,
nghttp2_hd_nv *nv_out, int *inflate_flags, nghttp2_hd_nv *nv_out, int *inflate_flags,
uint8_t *in, size_t inlen, int in_final); const uint8_t *in, size_t inlen, int in_final);
/* For unittesting purpose */ /* For unittesting purpose */
int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t index, int nghttp2_hd_emit_indname_block(nghttp2_bufs *bufs, size_t index,

View File

@ -3475,8 +3475,8 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame,
DEBUGF(fprintf(stderr, "recv: decoding header block %zu bytes\n", inlen)); DEBUGF(fprintf(stderr, "recv: decoding header block %zu bytes\n", inlen));
for (;;) { for (;;) {
inflate_flags = 0; inflate_flags = 0;
proclen = nghttp2_hd_inflate_hd2(&session->hd_inflater, &nv, &inflate_flags, proclen = nghttp2_hd_inflate_hd_nv(&session->hd_inflater, &nv,
in, inlen, final); &inflate_flags, in, inlen, final);
if (nghttp2_is_fatal((int)proclen)) { if (nghttp2_is_fatal((int)proclen)) {
return (int)proclen; return (int)proclen;
} }

View File

@ -314,9 +314,10 @@ cdef extern from 'nghttp2/nghttp2.h':
int nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater, int nghttp2_hd_inflate_change_table_size(nghttp2_hd_inflater *inflater,
size_t hd_table_bufsize_max) size_t hd_table_bufsize_max)
ssize_t nghttp2_hd_inflate_hd(nghttp2_hd_inflater *inflater, ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
nghttp2_nv *nv_out, int *inflate_flags, nghttp2_nv *nv_out, int *inflate_flags,
uint8_t *input, size_t inlen, int in_final) const uint8_t *input, size_t inlen,
int in_final)
int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater) int nghttp2_hd_inflate_end_headers(nghttp2_hd_inflater *inflater)

View File

@ -191,7 +191,7 @@ cdef class HDInflater:
res = [] res = []
while True: while True:
inflate_flags = 0 inflate_flags = 0
rv = cnghttp2.nghttp2_hd_inflate_hd(self._inflater, &nv, rv = cnghttp2.nghttp2_hd_inflate_hd2(self._inflater, &nv,
&inflate_flags, &inflate_flags,
buf, buflen, 1) buf, buflen, 1)
if rv < 0: if rv < 0:

View File

@ -178,7 +178,7 @@ ssize_t inflate_hd(nghttp2_hd_inflater *inflater, nva_out *out,
for (;;) { for (;;) {
inflate_flags = 0; inflate_flags = 0;
rv = nghttp2_hd_inflate_hd(inflater, &nv, &inflate_flags, bp.pos, rv = nghttp2_hd_inflate_hd2(inflater, &nv, &inflate_flags, bp.pos,
nghttp2_buf_len(&bp), final); nghttp2_buf_len(&bp), final);
if (rv < 0) { if (rv < 0) {