Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Contribute to GitLab
Sign in / Register
Toggle navigation
N
nghttp2
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Issues
0
Issues
0
List
Boards
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Analytics
Analytics
CI / CD
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
Libraries
nghttp2
Commits
ff0d137f
Commit
ff0d137f
authored
Mar 12, 2016
by
Tatsuhiro Tsujikawa
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Reference counted HPACK name/value pair
parent
8da20975
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
with
549 additions
and
422 deletions
+549
-422
genlibtokenlookup.py
genlibtokenlookup.py
+1
-1
lib/Makefile.am
lib/Makefile.am
+4
-2
lib/includes/nghttp2/nghttp2.h
lib/includes/nghttp2/nghttp2.h
+47
-0
lib/nghttp2_hd.c
lib/nghttp2_hd.c
+205
-297
lib/nghttp2_hd.h
lib/nghttp2_hd.h
+50
-56
lib/nghttp2_http.c
lib/nghttp2_http.c
+44
-43
lib/nghttp2_http.h
lib/nghttp2_http.h
+2
-3
lib/nghttp2_mem.c
lib/nghttp2_mem.c
+4
-0
lib/nghttp2_mem.h
lib/nghttp2_mem.h
+1
-0
lib/nghttp2_rcbuf.c
lib/nghttp2_rcbuf.c
+98
-0
lib/nghttp2_rcbuf.h
lib/nghttp2_rcbuf.h
+80
-0
lib/nghttp2_session.c
lib/nghttp2_session.c
+10
-11
tests/nghttp2_hd_test.c
tests/nghttp2_hd_test.c
+3
-9
No files found.
genlibtokenlookup.py
View file @
ff0d137f
...
@@ -162,7 +162,7 @@ def gen_enum():
...
@@ -162,7 +162,7 @@ def gen_enum():
def
gen_index_header
():
def
gen_index_header
():
print
'''
\
print
'''
\
static inline int lookup_token(const uint8_t *name, size_t namelen) {
static inline int
32_t
lookup_token(const uint8_t *name, size_t namelen) {
switch (namelen) {'''
switch (namelen) {'''
b
=
build_header
(
HEADERS
)
b
=
build_header
(
HEADERS
)
for
size
in
sorted
(
b
.
keys
()):
for
size
in
sorted
(
b
.
keys
()):
...
...
lib/Makefile.am
View file @
ff0d137f
...
@@ -47,7 +47,8 @@ OBJECTS = nghttp2_pq.c nghttp2_map.c nghttp2_queue.c \
...
@@ -47,7 +47,8 @@ OBJECTS = nghttp2_pq.c nghttp2_map.c nghttp2_queue.c \
nghttp2_option.c
\
nghttp2_option.c
\
nghttp2_callbacks.c
\
nghttp2_callbacks.c
\
nghttp2_mem.c
\
nghttp2_mem.c
\
nghttp2_http.c
nghttp2_http.c
\
nghttp2_rcbuf.c
HFILES
=
nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h
\
HFILES
=
nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h
\
nghttp2_frame.h
\
nghttp2_frame.h
\
...
@@ -61,7 +62,8 @@ HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \
...
@@ -61,7 +62,8 @@ HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \
nghttp2_option.h
\
nghttp2_option.h
\
nghttp2_callbacks.h
\
nghttp2_callbacks.h
\
nghttp2_mem.h
\
nghttp2_mem.h
\
nghttp2_http.h
nghttp2_http.h
\
nghttp2_rcbuf.h
libnghttp2_la_SOURCES
=
$(HFILES)
$(OBJECTS)
libnghttp2_la_SOURCES
=
$(HFILES)
$(OBJECTS)
libnghttp2_la_LDFLAGS
=
-no-undefined
\
libnghttp2_la_LDFLAGS
=
-no-undefined
\
...
...
lib/includes/nghttp2/nghttp2.h
View file @
ff0d137f
...
@@ -419,6 +419,53 @@ typedef enum {
...
@@ -419,6 +419,53 @@ typedef enum {
NGHTTP2_ERR_FLOODED
=
-
904
NGHTTP2_ERR_FLOODED
=
-
904
}
nghttp2_error
;
}
nghttp2_error
;
/**
* @struct
*
* The object representing single contagious buffer.
*/
typedef
struct
{
/**
* The pointer to the buffer.
*/
uint8_t
*
base
;
/**
* The length of the buffer.
*/
size_t
len
;
}
nghttp2_vec
;
struct
nghttp2_rcbuf
;
/**
* @struct
*
* The object representing reference counted buffer. The details of
* this structure are intentionally hidden from the public API.
*/
typedef
struct
nghttp2_rcbuf
nghttp2_rcbuf
;
/**
* @function
*
* Increments the reference count of |rcbuf| by 1.
*/
void
nghttp2_rcbuf_incref
(
nghttp2_rcbuf
*
rcbuf
);
/**
* @function
*
* Decrements the reference count of |rcbuf| by 1. If the reference
* count becomes zero, the object pointed by |rcbuf| will be freed.
* In this case, application must not use |rcbuf| again.
*/
void
nghttp2_rcbuf_decref
(
nghttp2_rcbuf
*
rcbuf
);
/**
* Returns the underlying buffer managed by |rcbuf|.
*/
nghttp2_vec
nghttp2_rcbuf_get_buf
(
nghttp2_rcbuf
*
rcbuf
);
/**
/**
* @enum
* @enum
*
*
...
...
lib/nghttp2_hd.c
View file @
ff0d137f
...
@@ -34,15 +34,17 @@
...
@@ -34,15 +34,17 @@
/* Make scalar initialization form of nghttp2_hd_entry */
/* Make scalar initialization form of nghttp2_hd_entry */
#define MAKE_STATIC_ENT(N, V, T, H) \
#define MAKE_STATIC_ENT(N, V, T, H) \
{ \
{ \
{ (uint8_t *)(N), (uint8_t *)(V), sizeof((N)) - 1, sizeof((V)) - 1, 0 } \
{ NULL, NULL, (uint8_t *)(N), sizeof((N)) - 1, -1 } \
, NULL, 0, (H), (T), 1, NGHTTP2_HD_FLAG_NONE \
, {NULL, NULL, (uint8_t *)(V), sizeof((V)) - 1, -1}, \
{(uint8_t *)(N), (uint8_t *)(V), sizeof((N)) - 1, sizeof((V)) - 1, 0}, \
T, H \
}
}
/* Generated by mkstatictbl.py */
/* Generated by mkstatictbl.py */
/* 3rd parameter is nghttp2_token value for header field name. We use
/* 3rd parameter is nghttp2_token value for header field name. We use
first enum value if same header names are repeated (e.g.,
first enum value if same header names are repeated (e.g.,
:status). */
:status). */
static
nghttp2_hd_entry
static_table
[]
=
{
static
nghttp2_hd_
static_
entry
static_table
[]
=
{
MAKE_STATIC_ENT
(
":authority"
,
""
,
0
,
3153725150u
),
MAKE_STATIC_ENT
(
":authority"
,
""
,
0
,
3153725150u
),
MAKE_STATIC_ENT
(
":method"
,
"GET"
,
1
,
695666056u
),
MAKE_STATIC_ENT
(
":method"
,
"GET"
,
1
,
695666056u
),
MAKE_STATIC_ENT
(
":method"
,
"POST"
,
1
,
695666056u
),
MAKE_STATIC_ENT
(
":method"
,
"POST"
,
1
,
695666056u
),
...
@@ -114,7 +116,7 @@ static int memeq(const void *s1, const void *s2, size_t n) {
...
@@ -114,7 +116,7 @@ static int memeq(const void *s1, const void *s2, size_t n) {
* This function was generated by genlibtokenlookup.py. Inspired by
* This function was generated by genlibtokenlookup.py. Inspired by
* h2o header lookup. https://github.com/h2o/h2o
* h2o header lookup. https://github.com/h2o/h2o
*/
*/
static
int
lookup_token
(
const
uint8_t
*
name
,
size_t
namelen
)
{
static
int
32_t
lookup_token
(
const
uint8_t
*
name
,
size_t
namelen
)
{
switch
(
namelen
)
{
switch
(
namelen
)
{
case
2
:
case
2
:
switch
(
name
[
1
])
{
switch
(
name
[
1
])
{
...
@@ -790,86 +792,33 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
...
@@ -790,86 +792,33 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
return
-
1
;
return
-
1
;
}
}
int
nghttp2_hd_entry_init
(
nghttp2_hd_entry
*
ent
,
uint8_t
flags
,
uint8_t
*
name
,
void
nghttp2_hd_entry_init
(
nghttp2_hd_entry
*
ent
,
nghttp2_hd_nv
*
nv
)
{
size_t
namelen
,
uint8_t
*
value
,
size_t
valuelen
,
ent
->
nv
=
*
nv
;
int
token
,
nghttp2_mem
*
mem
)
{
ent
->
cnv
.
name
=
nv
->
name
->
base
;
int
rv
=
0
;
ent
->
cnv
.
namelen
=
nv
->
name
->
len
;
ent
->
cnv
.
value
=
nv
->
value
->
base
;
/* Since nghttp2_hd_entry is used for indexing, ent->nv.flags always
ent
->
cnv
.
valuelen
=
nv
->
value
->
len
;
NGHTTP2_NV_FLAG_NONE */
ent
->
cnv
.
flags
=
nv
->
flags
;
ent
->
nv
.
flags
=
NGHTTP2_NV_FLAG_NONE
;
if
((
flags
&
NGHTTP2_HD_FLAG_NAME_ALLOC
)
&&
(
flags
&
NGHTTP2_HD_FLAG_NAME_GIFT
)
==
0
)
{
if
(
namelen
==
0
)
{
flags
=
(
uint8_t
)(
flags
&
~
NGHTTP2_HD_FLAG_NAME_ALLOC
);
ent
->
nv
.
name
=
(
uint8_t
*
)
""
;
}
else
{
/* name may not be NULL terminated on compression. */
ent
->
nv
.
name
=
nghttp2_mem_malloc
(
mem
,
namelen
+
1
);
if
(
ent
->
nv
.
name
==
NULL
)
{
rv
=
NGHTTP2_ERR_NOMEM
;
goto
fail
;
}
memcpy
(
ent
->
nv
.
name
,
name
,
namelen
);
ent
->
nv
.
name
[
namelen
]
=
'\0'
;
}
}
else
{
ent
->
nv
.
name
=
name
;
}
if
((
flags
&
NGHTTP2_HD_FLAG_VALUE_ALLOC
)
&&
(
flags
&
NGHTTP2_HD_FLAG_VALUE_GIFT
)
==
0
)
{
if
(
valuelen
==
0
)
{
flags
=
(
uint8_t
)(
flags
&
~
NGHTTP2_HD_FLAG_VALUE_ALLOC
);
ent
->
nv
.
value
=
(
uint8_t
*
)
""
;
}
else
{
/* value may not be NULL terminated on compression. */
ent
->
nv
.
value
=
nghttp2_mem_malloc
(
mem
,
valuelen
+
1
);
if
(
ent
->
nv
.
value
==
NULL
)
{
rv
=
NGHTTP2_ERR_NOMEM
;
goto
fail2
;
}
memcpy
(
ent
->
nv
.
value
,
value
,
valuelen
);
ent
->
nv
.
value
[
valuelen
]
=
'\0'
;
}
}
else
{
ent
->
nv
.
value
=
value
;
}
ent
->
nv
.
namelen
=
namelen
;
ent
->
nv
.
valuelen
=
valuelen
;
ent
->
token
=
token
;
ent
->
ref
=
1
;
ent
->
flags
=
flags
;
ent
->
next
=
NULL
;
ent
->
next
=
NULL
;
ent
->
hash
=
0
;
ent
->
hash
=
0
;
return
0
;
nghttp2_rcbuf_incref
(
ent
->
nv
.
name
);
nghttp2_rcbuf_incref
(
ent
->
nv
.
value
);
fail2:
if
((
flags
&
NGHTTP2_HD_FLAG_NAME_ALLOC
)
&&
(
flags
&
NGHTTP2_HD_FLAG_NAME_GIFT
)
==
0
)
{
nghttp2_mem_free
(
mem
,
ent
->
nv
.
name
);
}
fail:
return
rv
;
}
}
void
nghttp2_hd_entry_free
(
nghttp2_hd_entry
*
ent
,
nghttp2_mem
*
mem
)
{
void
nghttp2_hd_entry_free
(
nghttp2_hd_entry
*
ent
)
{
assert
(
ent
->
ref
==
0
);
nghttp2_rcbuf_decref
(
ent
->
nv
.
value
);
if
(
ent
->
flags
&
NGHTTP2_HD_FLAG_NAME_ALLOC
)
{
nghttp2_rcbuf_decref
(
ent
->
nv
.
name
);
nghttp2_mem_free
(
mem
,
ent
->
nv
.
name
);
}
if
(
ent
->
flags
&
NGHTTP2_HD_FLAG_VALUE_ALLOC
)
{
nghttp2_mem_free
(
mem
,
ent
->
nv
.
value
);
}
}
}
static
int
name_eq
(
const
nghttp2_nv
*
a
,
const
nghttp2_nv
*
b
)
{
static
int
name_eq
(
const
nghttp2_hd_nv
*
a
,
const
nghttp2_nv
*
b
)
{
return
a
->
namelen
==
b
->
namelen
&&
memeq
(
a
->
name
,
b
->
name
,
a
->
namelen
);
return
a
->
name
->
len
==
b
->
namelen
&&
memeq
(
a
->
name
->
base
,
b
->
name
,
b
->
namelen
);
}
}
static
int
value_eq
(
const
nghttp2_nv
*
a
,
const
nghttp2_nv
*
b
)
{
static
int
value_eq
(
const
nghttp2_hd_nv
*
a
,
const
nghttp2_nv
*
b
)
{
return
a
->
valuelen
==
b
->
valuelen
&&
memeq
(
a
->
value
,
b
->
value
,
a
->
valuelen
);
return
a
->
value
->
len
==
b
->
valuelen
&&
memeq
(
a
->
value
->
base
,
b
->
value
,
b
->
valuelen
);
}
}
static
uint32_t
name_hash
(
const
nghttp2_nv
*
nv
)
{
static
uint32_t
name_hash
(
const
nghttp2_nv
*
nv
)
{
...
@@ -905,7 +854,7 @@ static void hd_map_insert(nghttp2_hd_map *map, nghttp2_hd_entry *ent) {
...
@@ -905,7 +854,7 @@ static void hd_map_insert(nghttp2_hd_map *map, nghttp2_hd_entry *ent) {
}
}
static
nghttp2_hd_entry
*
hd_map_find
(
nghttp2_hd_map
*
map
,
int
*
exact_match
,
static
nghttp2_hd_entry
*
hd_map_find
(
nghttp2_hd_map
*
map
,
int
*
exact_match
,
const
nghttp2_nv
*
nv
,
int
token
,
const
nghttp2_nv
*
nv
,
int
32_t
token
,
uint32_t
hash
)
{
uint32_t
hash
)
{
nghttp2_hd_entry
*
p
;
nghttp2_hd_entry
*
p
;
nghttp2_hd_entry
*
res
=
NULL
;
nghttp2_hd_entry
*
res
=
NULL
;
...
@@ -913,7 +862,7 @@ static nghttp2_hd_entry *hd_map_find(nghttp2_hd_map *map, int *exact_match,
...
@@ -913,7 +862,7 @@ static nghttp2_hd_entry *hd_map_find(nghttp2_hd_map *map, int *exact_match,
*
exact_match
=
0
;
*
exact_match
=
0
;
for
(
p
=
map
->
table
[
hash
&
(
HD_MAP_SIZE
-
1
)];
p
;
p
=
p
->
next
)
{
for
(
p
=
map
->
table
[
hash
&
(
HD_MAP_SIZE
-
1
)];
p
;
p
=
p
->
next
)
{
if
(
token
!=
p
->
token
||
if
(
token
!=
p
->
nv
.
token
||
(
token
==
-
1
&&
(
hash
!=
p
->
hash
||
!
name_eq
(
&
p
->
nv
,
nv
))))
{
(
token
==
-
1
&&
(
hash
!=
p
->
hash
||
!
name_eq
(
&
p
->
nv
,
nv
))))
{
continue
;
continue
;
}
}
...
@@ -1008,8 +957,8 @@ static void hd_ringbuf_free(nghttp2_hd_ringbuf *ringbuf, nghttp2_mem *mem) {
...
@@ -1008,8 +957,8 @@ static void hd_ringbuf_free(nghttp2_hd_ringbuf *ringbuf, nghttp2_mem *mem) {
}
}
for
(
i
=
0
;
i
<
ringbuf
->
len
;
++
i
)
{
for
(
i
=
0
;
i
<
ringbuf
->
len
;
++
i
)
{
nghttp2_hd_entry
*
ent
=
hd_ringbuf_get
(
ringbuf
,
i
);
nghttp2_hd_entry
*
ent
=
hd_ringbuf_get
(
ringbuf
,
i
);
--
ent
->
ref
;
nghttp2_hd_entry_free
(
ent
,
mem
);
nghttp2_hd_entry_free
(
ent
);
nghttp2_mem_free
(
mem
,
ent
);
nghttp2_mem_free
(
mem
,
ent
);
}
}
nghttp2_mem_free
(
mem
,
ringbuf
->
buffer
);
nghttp2_mem_free
(
mem
,
ringbuf
->
buffer
);
...
@@ -1098,7 +1047,6 @@ int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem) {
...
@@ -1098,7 +1047,6 @@ int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem) {
inflater
->
settings_hd_table_bufsize_max
=
NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE
;
inflater
->
settings_hd_table_bufsize_max
=
NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE
;
inflater
->
min_hd_table_bufsize_max
=
UINT32_MAX
;
inflater
->
min_hd_table_bufsize_max
=
UINT32_MAX
;
inflater
->
ent_keep
=
NULL
;
inflater
->
nv_name_keep
=
NULL
;
inflater
->
nv_name_keep
=
NULL
;
inflater
->
nv_value_keep
=
NULL
;
inflater
->
nv_value_keep
=
NULL
;
...
@@ -1108,6 +1056,9 @@ int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem) {
...
@@ -1108,6 +1056,9 @@ int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem) {
nghttp2_buf_init
(
&
inflater
->
namebuf
);
nghttp2_buf_init
(
&
inflater
->
namebuf
);
nghttp2_buf_init
(
&
inflater
->
valuebuf
);
nghttp2_buf_init
(
&
inflater
->
valuebuf
);
inflater
->
namercbuf
=
NULL
;
inflater
->
valuercbuf
=
NULL
;
inflater
->
huffman_encoded
=
0
;
inflater
->
huffman_encoded
=
0
;
inflater
->
index
=
0
;
inflater
->
index
=
0
;
inflater
->
left
=
0
;
inflater
->
left
=
0
;
...
@@ -1122,21 +1073,10 @@ fail:
...
@@ -1122,21 +1073,10 @@ fail:
}
}
static
void
hd_inflate_keep_free
(
nghttp2_hd_inflater
*
inflater
)
{
static
void
hd_inflate_keep_free
(
nghttp2_hd_inflater
*
inflater
)
{
nghttp2_mem
*
mem
;
nghttp2_rcbuf_decref
(
inflater
->
nv_value_keep
);
nghttp2_rcbuf_decref
(
inflater
->
nv_name_keep
);
mem
=
inflater
->
ctx
.
mem
;
if
(
inflater
->
ent_keep
)
{
if
(
inflater
->
ent_keep
->
ref
==
0
)
{
nghttp2_hd_entry_free
(
inflater
->
ent_keep
,
mem
);
nghttp2_mem_free
(
mem
,
inflater
->
ent_keep
);
}
inflater
->
ent_keep
=
NULL
;
}
nghttp2_mem_free
(
mem
,
inflater
->
nv_value_keep
);
inflater
->
nv_value_keep
=
NULL
;
inflater
->
nv_value_keep
=
NULL
;
nghttp2_mem_free
(
mem
,
inflater
->
nv_name_keep
);
inflater
->
nv_name_keep
=
NULL
;
inflater
->
nv_name_keep
=
NULL
;
}
}
...
@@ -1145,13 +1085,11 @@ void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater) {
...
@@ -1145,13 +1085,11 @@ 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
)
{
nghttp2_mem
*
mem
;
hd_inflate_keep_free
(
inflater
)
;
mem
=
inflater
->
ctx
.
mem
;
nghttp2_rcbuf_decref
(
inflater
->
valuercbuf
);
nghttp2_rcbuf_decref
(
inflater
->
namercbuf
);
hd_inflate_keep_free
(
inflater
);
nghttp2_buf_free
(
&
inflater
->
valuebuf
,
mem
);
nghttp2_buf_free
(
&
inflater
->
namebuf
,
mem
);
hd_context_free
(
&
inflater
->
ctx
);
hd_context_free
(
&
inflater
->
ctx
);
}
}
...
@@ -1159,23 +1097,13 @@ static size_t entry_room(size_t namelen, size_t valuelen) {
...
@@ -1159,23 +1097,13 @@ static size_t entry_room(size_t namelen, size_t valuelen) {
return
NGHTTP2_HD_ENTRY_OVERHEAD
+
namelen
+
valuelen
;
return
NGHTTP2_HD_ENTRY_OVERHEAD
+
namelen
+
valuelen
;
}
}
static
int
emit_indexed_header
(
nghttp2_nv
*
nv_out
,
int
*
token_out
,
static
int
emit_header
(
nghttp2_hd_nv
*
nv_out
,
nghttp2_hd_nv
*
nv
)
{
nghttp2_hd_entry
*
ent
)
{
DEBUGF
(
fprintf
(
stderr
,
"inflatehd: header emission: %s: %s
\n
"
,
nv
->
name
->
base
,
DEBUGF
(
fprintf
(
stderr
,
"inflatehd: header emission: %s: %s
\n
"
,
ent
->
nv
.
name
,
nv
->
value
->
base
));
ent
->
nv
.
value
));
/* ent->ref may be 0. This happens if the encoder emits literal
/* ent->ref may be 0. This happens if the encoder emits literal
block larger than header table capacity with indexing. */
block larger than header table capacity with indexing. */
*
nv_out
=
ent
->
nv
;
*
token_out
=
ent
->
token
;
return
0
;
}
static
int
emit_literal_header
(
nghttp2_nv
*
nv_out
,
int
*
token_out
,
nghttp2_nv
*
nv
)
{
DEBUGF
(
fprintf
(
stderr
,
"inflatehd: header emission: %s: %s
\n
"
,
nv
->
name
,
nv
->
value
));
*
nv_out
=
*
nv
;
*
nv_out
=
*
nv
;
*
token_out
=
lookup_token
(
nv
->
name
,
nv
->
namelen
);
return
0
;
return
0
;
}
}
...
@@ -1483,17 +1411,16 @@ static int emit_newname_block(nghttp2_bufs *bufs, const nghttp2_nv *nv,
...
@@ -1483,17 +1411,16 @@ static int emit_newname_block(nghttp2_bufs *bufs, const nghttp2_nv *nv,
return
0
;
return
0
;
}
}
static
nghttp2_hd_entry
*
static
int
add_hd_table_incremental
(
nghttp2_hd_context
*
context
,
add_hd_table_incremental
(
nghttp2_hd_context
*
context
,
const
nghttp2_nv
*
nv
,
nghttp2_hd_nv
*
nv
,
nghttp2_hd_map
*
map
,
int
token
,
uint8_t
entry_flags
,
nghttp2_hd_map
*
map
,
uint32_t
hash
)
{
uint32_t
hash
)
{
int
rv
;
int
rv
;
nghttp2_hd_entry
*
new_ent
;
nghttp2_hd_entry
*
new_ent
;
size_t
room
;
size_t
room
;
nghttp2_mem
*
mem
;
nghttp2_mem
*
mem
;
mem
=
context
->
mem
;
mem
=
context
->
mem
;
room
=
entry_room
(
nv
->
name
len
,
nv
->
value
len
);
room
=
entry_room
(
nv
->
name
->
len
,
nv
->
value
->
len
);
while
(
context
->
hd_table_bufsize
+
room
>
context
->
hd_table_bufsize_max
&&
while
(
context
->
hd_table_bufsize
+
room
>
context
->
hd_table_bufsize_max
&&
context
->
hd_table
.
len
>
0
)
{
context
->
hd_table
.
len
>
0
)
{
...
@@ -1501,72 +1428,53 @@ add_hd_table_incremental(nghttp2_hd_context *context, const nghttp2_nv *nv,
...
@@ -1501,72 +1428,53 @@ add_hd_table_incremental(nghttp2_hd_context *context, const nghttp2_nv *nv,
size_t
idx
=
context
->
hd_table
.
len
-
1
;
size_t
idx
=
context
->
hd_table
.
len
-
1
;
nghttp2_hd_entry
*
ent
=
hd_ringbuf_get
(
&
context
->
hd_table
,
idx
);
nghttp2_hd_entry
*
ent
=
hd_ringbuf_get
(
&
context
->
hd_table
,
idx
);
context
->
hd_table_bufsize
-=
entry_room
(
ent
->
nv
.
namelen
,
ent
->
nv
.
valuelen
);
context
->
hd_table_bufsize
-=
entry_room
(
ent
->
nv
.
name
->
len
,
ent
->
nv
.
value
->
len
);
DEBUGF
(
fprintf
(
stderr
,
"hpack: remove item from header table: %s: %s
\n
"
,
DEBUGF
(
fprintf
(
stderr
,
"hpack: remove item from header table: %s: %s
\n
"
,
ent
->
nv
.
name
,
ent
->
nv
.
valu
e
));
(
char
*
)
ent
->
nv
.
name
->
base
,
(
char
*
)
ent
->
nv
.
value
->
bas
e
));
hd_ringbuf_pop_back
(
&
context
->
hd_table
);
hd_ringbuf_pop_back
(
&
context
->
hd_table
);
if
(
map
)
{
if
(
map
)
{
hd_map_remove
(
map
,
ent
);
hd_map_remove
(
map
,
ent
);
}
}
if
(
--
ent
->
ref
==
0
)
{
nghttp2_hd_entry_free
(
ent
,
mem
);
nghttp2_mem_free
(
mem
,
ent
);
}
}
new_ent
=
nghttp2_mem_malloc
(
mem
,
sizeof
(
nghttp2_hd_entry
));
nghttp2_hd_entry_free
(
ent
);
if
(
new_ent
==
NULL
)
{
nghttp2_mem_free
(
mem
,
ent
);
return
NULL
;
}
rv
=
nghttp2_hd_entry_init
(
new_ent
,
entry_flags
,
nv
->
name
,
nv
->
namelen
,
nv
->
value
,
nv
->
valuelen
,
token
,
mem
);
if
(
rv
!=
0
)
{
nghttp2_mem_free
(
mem
,
new_ent
);
return
NULL
;
}
}
if
(
room
>
context
->
hd_table_bufsize_max
)
{
if
(
room
>
context
->
hd_table_bufsize_max
)
{
/* The entry taking more than NGHTTP2_HD_MAX_BUFFER_SIZE is
/* The entry taking more than NGHTTP2_HD_MAX_BUFFER_SIZE is
immediately evicted. */
immediately evicted. So we don't allocate memory for it. */
--
new_ent
->
ref
;
return
0
;
}
else
{
}
rv
=
hd_ringbuf_push_front
(
&
context
->
hd_table
,
new_ent
,
mem
);
if
(
rv
!=
0
)
{
new_ent
=
nghttp2_mem_malloc
(
mem
,
sizeof
(
nghttp2_hd_entry
));
--
new_ent
->
ref
;
if
(
new_ent
==
NULL
)
{
return
NGHTTP2_ERR_NOMEM
;
}
if
((
entry_flags
&
NGHTTP2_HD_FLAG_NAME_ALLOC
)
&&
nghttp2_hd_entry_init
(
new_ent
,
nv
);
(
entry_flags
&
NGHTTP2_HD_FLAG_NAME_GIFT
))
{
/* nv->name are managed by caller. */
new_ent
->
nv
.
name
=
NULL
;
new_ent
->
nv
.
namelen
=
0
;
}
if
((
entry_flags
&
NGHTTP2_HD_FLAG_VALUE_ALLOC
)
&&
(
entry_flags
&
NGHTTP2_HD_FLAG_VALUE_GIFT
))
{
/* nv->value are managed by caller. */
new_ent
->
nv
.
value
=
NULL
;
new_ent
->
nv
.
valuelen
=
0
;
}
nghttp2_hd_entry_free
(
new_ent
,
mem
);
rv
=
hd_ringbuf_push_front
(
&
context
->
hd_table
,
new_ent
,
mem
);
nghttp2_mem_free
(
mem
,
new_ent
);
return
NULL
;
if
(
rv
!=
0
)
{
}
nghttp2_hd_entry_free
(
new_ent
);
nghttp2_mem_free
(
mem
,
new_ent
);
new_ent
->
seq
=
context
->
next_seq
++
;
return
rv
;
new_ent
->
hash
=
hash
;
}
if
(
map
)
{
new_ent
->
seq
=
context
->
next_seq
++
;
hd_map_insert
(
map
,
new_ent
);
new_ent
->
hash
=
hash
;
}
context
->
hd_table_bufsize
+=
room
;
if
(
map
)
{
hd_map_insert
(
map
,
new_ent
);
}
}
return
new_ent
;
context
->
hd_table_bufsize
+=
room
;
return
0
;
}
}
typedef
struct
{
typedef
struct
{
...
@@ -1575,10 +1483,11 @@ typedef struct {
...
@@ -1575,10 +1483,11 @@ typedef struct {
uint8_t
name_value_match
;
uint8_t
name_value_match
;
}
search_result
;
}
search_result
;
static
search_result
search_static_table
(
const
nghttp2_nv
*
nv
,
int
token
,
static
search_result
search_static_table
(
const
nghttp2_nv
*
nv
,
int
32_t
token
,
int
indexing_mode
)
{
int
indexing_mode
)
{
search_result
res
=
{
token
,
0
};
search_result
res
=
{
token
,
0
};
int
i
;
int
i
;
nghttp2_hd_static_entry
*
ent
;
if
(
indexing_mode
==
NGHTTP2_HD_NEVER_INDEXING
)
{
if
(
indexing_mode
==
NGHTTP2_HD_NEVER_INDEXING
)
{
return
res
;
return
res
;
...
@@ -1587,7 +1496,9 @@ static search_result search_static_table(const nghttp2_nv *nv, int token,
...
@@ -1587,7 +1496,9 @@ static search_result search_static_table(const nghttp2_nv *nv, int token,
for
(
i
=
token
;
for
(
i
=
token
;
i
<=
NGHTTP2_TOKEN_WWW_AUTHENTICATE
&&
static_table
[
i
].
token
==
token
;
i
<=
NGHTTP2_TOKEN_WWW_AUTHENTICATE
&&
static_table
[
i
].
token
==
token
;
++
i
)
{
++
i
)
{
if
(
value_eq
(
&
static_table
[
i
].
nv
,
nv
))
{
ent
=
&
static_table
[
i
];
if
(
ent
->
value
.
len
==
nv
->
valuelen
&&
memcmp
(
ent
->
value
.
base
,
nv
->
value
,
nv
->
valuelen
)
==
0
)
{
res
.
index
=
i
;
res
.
index
=
i
;
res
.
name_value_match
=
1
;
res
.
name_value_match
=
1
;
return
res
;
return
res
;
...
@@ -1597,7 +1508,7 @@ static search_result search_static_table(const nghttp2_nv *nv, int token,
...
@@ -1597,7 +1508,7 @@ static search_result search_static_table(const nghttp2_nv *nv, int token,
}
}
static
search_result
search_hd_table
(
nghttp2_hd_context
*
context
,
static
search_result
search_hd_table
(
nghttp2_hd_context
*
context
,
const
nghttp2_nv
*
nv
,
int
token
,
const
nghttp2_nv
*
nv
,
int
32_t
token
,
int
indexing_mode
,
nghttp2_hd_map
*
map
,
int
indexing_mode
,
nghttp2_hd_map
*
map
,
uint32_t
hash
)
{
uint32_t
hash
)
{
search_result
res
=
{
-
1
,
0
};
search_result
res
=
{
-
1
,
0
};
...
@@ -1641,15 +1552,15 @@ static void hd_context_shrink_table_size(nghttp2_hd_context *context,
...
@@ -1641,15 +1552,15 @@ static void hd_context_shrink_table_size(nghttp2_hd_context *context,
context
->
hd_table
.
len
>
0
)
{
context
->
hd_table
.
len
>
0
)
{
size_t
idx
=
context
->
hd_table
.
len
-
1
;
size_t
idx
=
context
->
hd_table
.
len
-
1
;
nghttp2_hd_entry
*
ent
=
hd_ringbuf_get
(
&
context
->
hd_table
,
idx
);
nghttp2_hd_entry
*
ent
=
hd_ringbuf_get
(
&
context
->
hd_table
,
idx
);
context
->
hd_table_bufsize
-=
entry_room
(
ent
->
nv
.
namelen
,
ent
->
nv
.
valuelen
);
context
->
hd_table_bufsize
-=
entry_room
(
ent
->
nv
.
name
->
len
,
ent
->
nv
.
value
->
len
);
hd_ringbuf_pop_back
(
&
context
->
hd_table
);
hd_ringbuf_pop_back
(
&
context
->
hd_table
);
if
(
map
)
{
if
(
map
)
{
hd_map_remove
(
map
,
ent
);
hd_map_remove
(
map
,
ent
);
}
}
if
(
--
ent
->
ref
==
0
)
{
nghttp2_hd_entry_free
(
ent
,
mem
);
nghttp2_hd_entry_free
(
ent
);
nghttp2_mem_free
(
mem
,
ent
);
nghttp2_mem_free
(
mem
,
ent
);
}
}
}
}
}
...
@@ -1708,19 +1619,33 @@ static size_t get_max_index(nghttp2_hd_context *context) {
...
@@ -1708,19 +1619,33 @@ static size_t get_max_index(nghttp2_hd_context *context) {
return
context
->
hd_table
.
len
+
NGHTTP2_STATIC_TABLE_LENGTH
-
1
;
return
context
->
hd_table
.
len
+
NGHTTP2_STATIC_TABLE_LENGTH
-
1
;
}
}
nghttp2_hd_entry
*
nghttp2_hd_table_get
(
nghttp2_hd_context
*
context
,
nghttp2_hd_nv
nghttp2_hd_table_get
(
nghttp2_hd_context
*
context
,
size_t
idx
)
{
size_t
idx
)
{
assert
(
INDEX_RANGE_VALID
(
context
,
idx
));
assert
(
INDEX_RANGE_VALID
(
context
,
idx
));
if
(
idx
>=
NGHTTP2_STATIC_TABLE_LENGTH
)
{
if
(
idx
>=
NGHTTP2_STATIC_TABLE_LENGTH
)
{
return
hd_ringbuf_get
(
&
context
->
hd_table
,
return
hd_ringbuf_get
(
&
context
->
hd_table
,
idx
-
NGHTTP2_STATIC_TABLE_LENGTH
)
idx
-
NGHTTP2_STATIC_TABLE_LENGTH
)
;
->
nv
;
}
else
{
}
else
{
return
&
static_table
[
idx
];
nghttp2_hd_static_entry
*
ent
;
ent
=
&
static_table
[
idx
];
return
(
nghttp2_hd_nv
){
&
ent
->
name
,
&
ent
->
value
,
ent
->
token
,
NGHTTP2_NV_FLAG_NONE
};
}
}
static
const
nghttp2_nv
*
nghttp2_hd_table_get2
(
nghttp2_hd_context
*
context
,
size_t
idx
)
{
assert
(
INDEX_RANGE_VALID
(
context
,
idx
));
if
(
idx
>=
NGHTTP2_STATIC_TABLE_LENGTH
)
{
return
&
hd_ringbuf_get
(
&
context
->
hd_table
,
idx
-
NGHTTP2_STATIC_TABLE_LENGTH
)
->
cnv
;
}
}
return
&
static_table
[
idx
].
cnv
;
}
}
static
int
hd_deflate_decide_indexing
(
nghttp2_hd_deflater
*
deflater
,
static
int
hd_deflate_decide_indexing
(
nghttp2_hd_deflater
*
deflater
,
const
nghttp2_nv
*
nv
,
int
token
)
{
const
nghttp2_nv
*
nv
,
int
32_t
token
)
{
if
(
token
==
NGHTTP2_TOKEN__PATH
||
token
==
NGHTTP2_TOKEN_AGE
||
if
(
token
==
NGHTTP2_TOKEN__PATH
||
token
==
NGHTTP2_TOKEN_AGE
||
token
==
NGHTTP2_TOKEN_CONTENT_LENGTH
||
token
==
NGHTTP2_TOKEN_ETAG
||
token
==
NGHTTP2_TOKEN_CONTENT_LENGTH
||
token
==
NGHTTP2_TOKEN_ETAG
||
token
==
NGHTTP2_TOKEN_IF_MODIFIED_SINCE
||
token
==
NGHTTP2_TOKEN_IF_MODIFIED_SINCE
||
...
@@ -1740,7 +1665,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
...
@@ -1740,7 +1665,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
search_result
res
;
search_result
res
;
ssize_t
idx
;
ssize_t
idx
;
int
indexing_mode
;
int
indexing_mode
;
int
token
;
int
32_t
token
;
nghttp2_mem
*
mem
;
nghttp2_mem
*
mem
;
uint32_t
hash
=
0
;
uint32_t
hash
=
0
;
...
@@ -1789,27 +1714,35 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
...
@@ -1789,27 +1714,35 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
}
}
if
(
indexing_mode
==
NGHTTP2_HD_WITH_INDEXING
)
{
if
(
indexing_mode
==
NGHTTP2_HD_WITH_INDEXING
)
{
nghttp2_hd_entry
*
new_ent
;
nghttp2_hd_nv
hd_nv
;
if
(
idx
!=
-
1
&&
idx
<
(
ssize_t
)
NGHTTP2_STATIC_TABLE_LENGTH
)
{
if
(
idx
!=
-
1
&&
idx
<
(
ssize_t
)
NGHTTP2_STATIC_TABLE_LENGTH
)
{
nghttp2_nv
nv_indname
;
hd_nv
.
name
=
nghttp2_hd_table_get
(
&
deflater
->
ctx
,
(
size_t
)
idx
).
name
;
nv_indname
=
*
nv
;
nghttp2_rcbuf_incref
(
hd_nv
.
name
);
nv_indname
.
name
=
nghttp2_hd_table_get
(
&
deflater
->
ctx
,
(
size_t
)
idx
)
->
nv
.
name
;
new_ent
=
add_hd_table_incremental
(
&
deflater
->
ctx
,
&
nv_indname
,
token
,
NGHTTP2_HD_FLAG_VALUE_ALLOC
,
&
deflater
->
map
,
hash
);
}
else
{
}
else
{
new_ent
=
add_hd_table_incremental
(
&
deflater
->
ctx
,
nv
,
token
,
rv
=
nghttp2_rcbuf_new2
(
&
hd_nv
.
name
,
nv
->
name
,
nv
->
namelen
,
mem
);
NGHTTP2_HD_FLAG_NAME_ALLOC
|
if
(
rv
!=
0
)
{
NGHTTP2_HD_FLAG_VALUE_ALLOC
,
return
rv
;
&
deflater
->
map
,
hash
);
}
}
}
if
(
!
new_ent
)
{
return
NGHTTP2_ERR_HEADER_COMP
;
rv
=
nghttp2_rcbuf_new2
(
&
hd_nv
.
value
,
nv
->
value
,
nv
->
valuelen
,
mem
);
if
(
rv
!=
0
)
{
nghttp2_rcbuf_decref
(
hd_nv
.
name
);
return
rv
;
}
}
if
(
new_ent
->
ref
==
0
)
{
nghttp2_hd_entry_free
(
new_ent
,
mem
);
hd_nv
.
token
=
token
;
nghttp2_mem_free
(
mem
,
new_ent
);
hd_nv
.
flags
=
NGHTTP2_NV_FLAG_NONE
;
rv
=
add_hd_table_incremental
(
&
deflater
->
ctx
,
&
hd_nv
,
&
deflater
->
map
,
hash
);
nghttp2_rcbuf_decref
(
hd_nv
.
value
);
nghttp2_rcbuf_decref
(
hd_nv
.
name
);
if
(
rv
!=
0
)
{
return
NGHTTP2_ERR_HEADER_COMP
;
}
}
}
}
if
(
idx
==
-
1
)
{
if
(
idx
==
-
1
)
{
...
@@ -2093,10 +2026,10 @@ static ssize_t hd_inflate_read(nghttp2_hd_inflater *inflater, nghttp2_buf *buf,
...
@@ -2093,10 +2026,10 @@ static ssize_t hd_inflate_read(nghttp2_hd_inflater *inflater, nghttp2_buf *buf,
* Out of memory
* Out of memory
*/
*/
static
int
hd_inflate_commit_indexed
(
nghttp2_hd_inflater
*
inflater
,
static
int
hd_inflate_commit_indexed
(
nghttp2_hd_inflater
*
inflater
,
nghttp2_
nv
*
nv_out
,
int
*
token
_out
)
{
nghttp2_
hd_nv
*
nv
_out
)
{
nghttp2_hd_
entry
*
ent
=
nghttp2_hd_table_get
(
&
inflater
->
ctx
,
inflater
->
index
);
nghttp2_hd_
nv
nv
=
nghttp2_hd_table_get
(
&
inflater
->
ctx
,
inflater
->
index
);
emit_
indexed_header
(
nv_out
,
token_out
,
ent
);
emit_
header
(
nv_out
,
&
nv
);
return
0
;
return
0
;
}
}
...
@@ -2113,19 +2046,9 @@ static int hd_inflate_commit_indexed(nghttp2_hd_inflater *inflater,
...
@@ -2113,19 +2046,9 @@ static int hd_inflate_commit_indexed(nghttp2_hd_inflater *inflater,
* Out of memory
* Out of memory
*/
*/
static
int
hd_inflate_commit_newname
(
nghttp2_hd_inflater
*
inflater
,
static
int
hd_inflate_commit_newname
(
nghttp2_hd_inflater
*
inflater
,
nghttp2_nv
*
nv_out
,
int
*
token_out
)
{
nghttp2_hd_nv
*
nv_out
)
{
nghttp2_nv
nv
;
nghttp2_hd_nv
nv
;
nghttp2_mem
*
mem
;
int
rv
;
mem
=
inflater
->
ctx
.
mem
;
nv
.
name
=
inflater
->
namebuf
.
pos
;
nv
.
namelen
=
nghttp2_buf_len
(
&
inflater
->
namebuf
);
nv
.
value
=
inflater
->
valuebuf
.
pos
;
nv
.
valuelen
=
nghttp2_buf_len
(
&
inflater
->
valuebuf
);
nghttp2_buf_init
(
&
inflater
->
valuebuf
);
nghttp2_buf_init
(
&
inflater
->
namebuf
);
if
(
inflater
->
no_index
)
{
if
(
inflater
->
no_index
)
{
nv
.
flags
=
NGHTTP2_NV_FLAG_NO_INDEX
;
nv
.
flags
=
NGHTTP2_NV_FLAG_NO_INDEX
;
...
@@ -2133,35 +2056,26 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
...
@@ -2133,35 +2056,26 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
nv
.
flags
=
NGHTTP2_NV_FLAG_NONE
;
nv
.
flags
=
NGHTTP2_NV_FLAG_NONE
;
}
}
if
(
inflater
->
index_required
)
{
nv
.
name
=
inflater
->
namercbuf
;
nghttp2_hd_entry
*
new_ent
;
nv
.
value
=
inflater
->
valuercbuf
;
uint8_t
ent_flags
;
nv
.
token
=
lookup_token
(
inflater
->
namercbuf
->
base
,
inflater
->
namercbuf
->
len
);
ent_flags
=
NGHTTP2_HD_FLAG_NAME_ALLOC
|
NGHTTP2_HD_FLAG_NAME_GIFT
|
NGHTTP2_HD_FLAG_VALUE_ALLOC
|
NGHTTP2_HD_FLAG_VALUE_GIFT
;
new_ent
=
add_hd_table_incremental
(
&
inflater
->
ctx
,
&
nv
,
if
(
inflater
->
index_required
)
{
lookup_token
(
nv
.
name
,
nv
.
namelen
),
rv
=
add_hd_table_incremental
(
&
inflater
->
ctx
,
&
nv
,
NULL
,
0
);
ent_flags
,
NULL
,
0
);
if
(
new_ent
)
{
emit_indexed_header
(
nv_out
,
token_out
,
new_ent
);
inflater
->
ent_keep
=
new_ent
;
return
0
;
if
(
rv
!=
0
)
{
return
rv
;
}
}
nghttp2_mem_free
(
mem
,
nv
.
value
);
nghttp2_mem_free
(
mem
,
nv
.
name
);
return
NGHTTP2_ERR_NOMEM
;
}
}
emit_
literal_header
(
nv_out
,
token
_out
,
&
nv
);
emit_
header
(
nv
_out
,
&
nv
);
inflater
->
nv_name_keep
=
nv
.
name
;
inflater
->
nv_name_keep
=
nv
.
name
;
inflater
->
nv_value_keep
=
nv
.
value
;
inflater
->
nv_value_keep
=
nv
.
value
;
inflater
->
namercbuf
=
NULL
;
inflater
->
valuercbuf
=
NULL
;
return
0
;
return
0
;
}
}
...
@@ -2177,12 +2091,11 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
...
@@ -2177,12 +2091,11 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
* Out of memory
* Out of memory
*/
*/
static
int
hd_inflate_commit_indname
(
nghttp2_hd_inflater
*
inflater
,
static
int
hd_inflate_commit_indname
(
nghttp2_hd_inflater
*
inflater
,
nghttp2_nv
*
nv_out
,
int
*
token_out
)
{
nghttp2_hd_nv
*
nv_out
)
{
nghttp2_nv
nv
;
nghttp2_hd_nv
nv
;
nghttp2_hd_entry
*
ent_name
;
int
rv
;
nghttp2_mem
*
mem
;
mem
=
inflater
->
ctx
.
mem
;
nv
=
nghttp2_hd_table_get
(
&
inflater
->
ctx
,
inflater
->
index
)
;
if
(
inflater
->
no_index
)
{
if
(
inflater
->
no_index
)
{
nv
.
flags
=
NGHTTP2_NV_FLAG_NO_INDEX
;
nv
.
flags
=
NGHTTP2_NV_FLAG_NO_INDEX
;
...
@@ -2190,72 +2103,57 @@ static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
...
@@ -2190,72 +2103,57 @@ static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
nv
.
flags
=
NGHTTP2_NV_FLAG_NONE
;
nv
.
flags
=
NGHTTP2_NV_FLAG_NONE
;
}
}
ent_name
=
nghttp2_hd_table_get
(
&
inflater
->
ctx
,
inflater
->
index
);
nghttp2_rcbuf_incref
(
nv
.
name
);
if
(
inflater
->
index_required
)
{
nghttp2_hd_entry
*
new_ent
;
uint8_t
ent_flags
;
ent_flags
=
NGHTTP2_HD_FLAG_VALUE_ALLOC
|
NGHTTP2_HD_FLAG_VALUE_GIFT
;
if
(
inflater
->
index
>=
NGHTTP2_STATIC_TABLE_LENGTH
)
{
/* We don't copy name in static table */
ent_flags
|=
NGHTTP2_HD_FLAG_NAME_ALLOC
;
}
nv
.
name
=
ent_name
->
nv
.
name
;
nv
.
namelen
=
ent_name
->
nv
.
namelen
;
nv
.
value
=
inflater
->
valuebuf
.
pos
;
nv
.
valuelen
=
nghttp2_buf_len
(
&
inflater
->
valuebuf
);
nghttp2_buf_init
(
&
inflater
->
valuebuf
)
;
nv
.
value
=
inflater
->
valuercbuf
;
new_ent
=
add_hd_table_incremental
(
&
inflater
->
ctx
,
&
nv
,
ent_name
->
token
,
if
(
inflater
->
index_required
)
{
ent_flags
,
NULL
,
0
);
rv
=
add_hd_table_incremental
(
&
inflater
->
ctx
,
&
nv
,
NULL
,
0
);
if
(
rv
!=
0
)
{
/* At this point, ent_name might be deleted. */
nghttp2_rcbuf_decref
(
nv
.
name
);
return
NGHTTP2_ERR_NOMEM
;
if
(
new_ent
)
{
emit_indexed_header
(
nv_out
,
token_out
,
new_ent
);
inflater
->
ent_keep
=
new_ent
;
return
0
;
}
}
nghttp2_mem_free
(
mem
,
nv
.
value
);
return
NGHTTP2_ERR_NOMEM
;
}
}
nv
.
name
=
ent_name
->
nv
.
name
;
emit_header
(
nv_out
,
&
nv
);
nv
.
namelen
=
ent_name
->
nv
.
namelen
;
nv
.
value
=
inflater
->
valuebuf
.
pos
;
nv
.
valuelen
=
nghttp2_buf_len
(
&
inflater
->
valuebuf
);
nghttp2_buf_init
(
&
inflater
->
valuebuf
);
emit_literal_header
(
nv_out
,
token_out
,
&
nv
);
inflater
->
nv_name_keep
=
nv
.
name
;
inflater
->
nv_value_keep
=
nv
.
value
;
inflater
->
nv_value_keep
=
nv
.
value
;
inflater
->
valuercbuf
=
NULL
;
return
0
;
return
0
;
}
}
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
)
{
int
token
;
ssize_t
rv
;
nghttp2_hd_nv
hd_nv
;
rv
=
nghttp2_hd_inflate_hd2
(
inflater
,
&
hd_nv
,
inflate_flags
,
in
,
inlen
,
in_final
);
if
(
rv
<
0
)
{
return
rv
;
}
if
(
*
inflate_flags
&
NGHTTP2_HD_INFLATE_EMIT
)
{
nv_out
->
name
=
hd_nv
.
name
->
base
;
nv_out
->
namelen
=
hd_nv
.
name
->
len
;
nv_out
->
value
=
hd_nv
.
value
->
base
;
nv_out
->
valuelen
=
hd_nv
.
value
->
len
;
nv_out
->
flags
=
hd_nv
.
flags
;
}
return
nghttp2_hd_inflate_hd2
(
inflater
,
nv_out
,
inflate_flags
,
&
token
,
in
,
return
rv
;
inlen
,
in_final
);
}
}
ssize_t
nghttp2_hd_inflate_hd2
(
nghttp2_hd_inflater
*
inflater
,
ssize_t
nghttp2_hd_inflate_hd2
(
nghttp2_hd_inflater
*
inflater
,
nghttp2_nv
*
nv_out
,
int
*
inflate_flags
,
nghttp2_hd_nv
*
nv_out
,
int
*
inflate_flags
,
int
*
token_out
,
uint8_t
*
in
,
size_t
inlen
,
uint8_t
*
in
,
size_t
inlen
,
int
in_final
)
{
int
in_final
)
{
ssize_t
rv
=
0
;
ssize_t
rv
=
0
;
uint8_t
*
first
=
in
;
uint8_t
*
first
=
in
;
uint8_t
*
last
=
in
+
inlen
;
uint8_t
*
last
=
in
+
inlen
;
...
@@ -2271,7 +2169,6 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
...
@@ -2271,7 +2169,6 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
DEBUGF
(
fprintf
(
stderr
,
"inflatehd: start state=%d
\n
"
,
inflater
->
state
));
DEBUGF
(
fprintf
(
stderr
,
"inflatehd: start state=%d
\n
"
,
inflater
->
state
));
hd_inflate_keep_free
(
inflater
);
hd_inflate_keep_free
(
inflater
);
*
token_out
=
-
1
;
*
inflate_flags
=
NGHTTP2_HD_INFLATE_NONE
;
*
inflate_flags
=
NGHTTP2_HD_INFLATE_NONE
;
for
(;
in
!=
last
||
busy
;)
{
for
(;
in
!=
last
||
busy
;)
{
busy
=
0
;
busy
=
0
;
...
@@ -2377,7 +2274,7 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
...
@@ -2377,7 +2274,7 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
inflater
->
index
=
inflater
->
left
;
inflater
->
index
=
inflater
->
left
;
--
inflater
->
index
;
--
inflater
->
index
;
rv
=
hd_inflate_commit_indexed
(
inflater
,
nv_out
,
token_out
);
rv
=
hd_inflate_commit_indexed
(
inflater
,
nv_out
);
if
(
rv
<
0
)
{
if
(
rv
<
0
)
{
goto
fail
;
goto
fail
;
}
}
...
@@ -2422,17 +2319,21 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
...
@@ -2422,17 +2319,21 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
nghttp2_hd_huff_decode_context_init
(
&
inflater
->
huff_decode_ctx
);
nghttp2_hd_huff_decode_context_init
(
&
inflater
->
huff_decode_ctx
);
inflater
->
state
=
NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF
;
inflater
->
state
=
NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF
;
rv
=
nghttp2_buf_reserve
(
&
inflater
->
namebuf
,
inflater
->
left
*
2
+
1
,
mem
);
rv
=
nghttp2_rcbuf_new
(
&
inflater
->
namercbuf
,
inflater
->
left
*
2
+
1
,
mem
);
}
else
{
}
else
{
inflater
->
state
=
NGHTTP2_HD_STATE_NEWNAME_READ_NAME
;
inflater
->
state
=
NGHTTP2_HD_STATE_NEWNAME_READ_NAME
;
rv
=
nghttp2_
buf_reserve
(
&
inflater
->
name
buf
,
inflater
->
left
+
1
,
mem
);
rv
=
nghttp2_
rcbuf_new
(
&
inflater
->
namerc
buf
,
inflater
->
left
+
1
,
mem
);
}
}
if
(
rv
!=
0
)
{
if
(
rv
!=
0
)
{
goto
fail
;
goto
fail
;
}
}
nghttp2_buf_wrap_init
(
&
inflater
->
namebuf
,
inflater
->
namercbuf
->
base
,
inflater
->
namercbuf
->
len
);
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
->
namebuf
,
in
,
last
);
...
@@ -2452,6 +2353,7 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
...
@@ -2452,6 +2353,7 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
}
}
*
inflater
->
namebuf
.
last
=
'\0'
;
*
inflater
->
namebuf
.
last
=
'\0'
;
inflater
->
namercbuf
->
len
=
nghttp2_buf_len
(
&
inflater
->
namebuf
);
inflater
->
state
=
NGHTTP2_HD_STATE_CHECK_VALUELEN
;
inflater
->
state
=
NGHTTP2_HD_STATE_CHECK_VALUELEN
;
...
@@ -2473,6 +2375,7 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
...
@@ -2473,6 +2375,7 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
}
}
*
inflater
->
namebuf
.
last
=
'\0'
;
*
inflater
->
namebuf
.
last
=
'\0'
;
inflater
->
namercbuf
->
len
=
nghttp2_buf_len
(
&
inflater
->
namebuf
);
inflater
->
state
=
NGHTTP2_HD_STATE_CHECK_VALUELEN
;
inflater
->
state
=
NGHTTP2_HD_STATE_CHECK_VALUELEN
;
...
@@ -2505,18 +2408,21 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
...
@@ -2505,18 +2408,21 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
inflater
->
state
=
NGHTTP2_HD_STATE_READ_VALUEHUFF
;
inflater
->
state
=
NGHTTP2_HD_STATE_READ_VALUEHUFF
;
rv
=
nghttp2_
buf_reserve
(
&
inflater
->
value
buf
,
inflater
->
left
*
2
+
1
,
rv
=
nghttp2_
rcbuf_new
(
&
inflater
->
valuerc
buf
,
inflater
->
left
*
2
+
1
,
mem
);
mem
);
}
else
{
}
else
{
inflater
->
state
=
NGHTTP2_HD_STATE_READ_VALUE
;
inflater
->
state
=
NGHTTP2_HD_STATE_READ_VALUE
;
rv
=
nghttp2_
buf_reserve
(
&
inflater
->
value
buf
,
inflater
->
left
+
1
,
mem
);
rv
=
nghttp2_
rcbuf_new
(
&
inflater
->
valuerc
buf
,
inflater
->
left
+
1
,
mem
);
}
}
if
(
rv
!=
0
)
{
if
(
rv
!=
0
)
{
goto
fail
;
goto
fail
;
}
}
nghttp2_buf_wrap_init
(
&
inflater
->
valuebuf
,
inflater
->
valuercbuf
->
base
,
inflater
->
valuercbuf
->
len
);
busy
=
1
;
busy
=
1
;
break
;
break
;
...
@@ -2538,11 +2444,12 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
...
@@ -2538,11 +2444,12 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
}
}
*
inflater
->
valuebuf
.
last
=
'\0'
;
*
inflater
->
valuebuf
.
last
=
'\0'
;
inflater
->
valuercbuf
->
len
=
nghttp2_buf_len
(
&
inflater
->
valuebuf
);
if
(
inflater
->
opcode
==
NGHTTP2_HD_OPCODE_NEWNAME
)
{
if
(
inflater
->
opcode
==
NGHTTP2_HD_OPCODE_NEWNAME
)
{
rv
=
hd_inflate_commit_newname
(
inflater
,
nv_out
,
token_out
);
rv
=
hd_inflate_commit_newname
(
inflater
,
nv_out
);
}
else
{
}
else
{
rv
=
hd_inflate_commit_indname
(
inflater
,
nv_out
,
token_out
);
rv
=
hd_inflate_commit_indname
(
inflater
,
nv_out
);
}
}
if
(
rv
!=
0
)
{
if
(
rv
!=
0
)
{
...
@@ -2572,11 +2479,12 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
...
@@ -2572,11 +2479,12 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
}
}
*
inflater
->
valuebuf
.
last
=
'\0'
;
*
inflater
->
valuebuf
.
last
=
'\0'
;
inflater
->
valuercbuf
->
len
=
nghttp2_buf_len
(
&
inflater
->
valuebuf
);
if
(
inflater
->
opcode
==
NGHTTP2_HD_OPCODE_NEWNAME
)
{
if
(
inflater
->
opcode
==
NGHTTP2_HD_OPCODE_NEWNAME
)
{
rv
=
hd_inflate_commit_newname
(
inflater
,
nv_out
,
token_out
);
rv
=
hd_inflate_commit_newname
(
inflater
,
nv_out
);
}
else
{
}
else
{
rv
=
hd_inflate_commit_indname
(
inflater
,
nv_out
,
token_out
);
rv
=
hd_inflate_commit_indname
(
inflater
,
nv_out
);
}
}
if
(
rv
!=
0
)
{
if
(
rv
!=
0
)
{
...
@@ -2710,7 +2618,7 @@ static const nghttp2_nv *hd_get_table_entry(nghttp2_hd_context *context,
...
@@ -2710,7 +2618,7 @@ static const nghttp2_nv *hd_get_table_entry(nghttp2_hd_context *context,
return
NULL
;
return
NULL
;
}
}
return
&
nghttp2_hd_table_get
(
context
,
idx
)
->
nv
;
return
nghttp2_hd_table_get2
(
context
,
idx
)
;
}
}
size_t
nghttp2_hd_deflate_get_num_table_entries
(
nghttp2_hd_deflater
*
deflater
)
{
size_t
nghttp2_hd_deflate_get_num_table_entries
(
nghttp2_hd_deflater
*
deflater
)
{
...
...
lib/nghttp2_hd.h
View file @
ff0d137f
...
@@ -34,6 +34,7 @@
...
@@ -34,6 +34,7 @@
#include "nghttp2_hd_huffman.h"
#include "nghttp2_hd_huffman.h"
#include "nghttp2_buf.h"
#include "nghttp2_buf.h"
#include "nghttp2_mem.h"
#include "nghttp2_mem.h"
#include "nghttp2_rcbuf.h"
#define NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE NGHTTP2_DEFAULT_HEADER_TABLE_SIZE
#define NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE NGHTTP2_DEFAULT_HEADER_TABLE_SIZE
#define NGHTTP2_HD_ENTRY_OVERHEAD 32
#define NGHTTP2_HD_ENTRY_OVERHEAD 32
...
@@ -168,25 +169,29 @@ typedef enum {
...
@@ -168,25 +169,29 @@ typedef enum {
NGHTTP2_TOKEN_X_XSS_PROTECTION
,
NGHTTP2_TOKEN_X_XSS_PROTECTION
,
}
nghttp2_token
;
}
nghttp2_token
;
typedef
enum
{
NGHTTP2_HD_FLAG_NONE
=
0
,
/* Indicates name was dynamically allocated and must be freed */
NGHTTP2_HD_FLAG_NAME_ALLOC
=
1
,
/* Indicates value was dynamically allocated and must be freed */
NGHTTP2_HD_FLAG_VALUE_ALLOC
=
1
<<
1
,
/* Indicates that the name was gifted to the entry and no copying
necessary. */
NGHTTP2_HD_FLAG_NAME_GIFT
=
1
<<
2
,
/* Indicates that the value was gifted to the entry and no copying
necessary. */
NGHTTP2_HD_FLAG_VALUE_GIFT
=
1
<<
3
}
nghttp2_hd_flags
;
struct
nghttp2_hd_entry
;
struct
nghttp2_hd_entry
;
typedef
struct
nghttp2_hd_entry
nghttp2_hd_entry
;
typedef
struct
nghttp2_hd_entry
nghttp2_hd_entry
;
typedef
struct
{
/* The buffer containing header field name. NULL-termination is
guaranteed. */
nghttp2_rcbuf
*
name
;
/* The buffer containing header field value. NULL-termination is
guaranteed. */
nghttp2_rcbuf
*
value
;
/* nghttp2_token value for name. It could be -1 if we have no token
for that header field name. */
int32_t
token
;
/* Bitwise OR of one or more of nghttp2_nv_flag. */
uint8_t
flags
;
}
nghttp2_hd_nv
;
struct
nghttp2_hd_entry
{
struct
nghttp2_hd_entry
{
nghttp2_nv
nv
;
/* The header field name/value pair */
nghttp2_hd_nv
nv
;
/* This is solely for nghttp2_hd_{deflate,inflate}_get_table_entry
APIs to keep backward compatibility. */
nghttp2_nv
cnv
;
/* The next entry which shares same bucket in hash table. */
/* The next entry which shares same bucket in hash table. */
nghttp2_hd_entry
*
next
;
nghttp2_hd_entry
*
next
;
/* The sequence number. We will increment it by one whenever we
/* The sequence number. We will increment it by one whenever we
...
@@ -194,14 +199,17 @@ struct nghttp2_hd_entry {
...
@@ -194,14 +199,17 @@ struct nghttp2_hd_entry {
uint32_t
seq
;
uint32_t
seq
;
/* The hash value for header name (nv.name). */
/* The hash value for header name (nv.name). */
uint32_t
hash
;
uint32_t
hash
;
/* nghttp2_token value for nv.name. It could be -1 if we have no
token for that header field name. */
int
token
;
/* Reference count */
uint8_t
ref
;
uint8_t
flags
;
};
};
/* The entry used for static header table. */
typedef
struct
{
nghttp2_rcbuf
name
;
nghttp2_rcbuf
value
;
nghttp2_nv
cnv
;
int32_t
token
;
uint32_t
hash
;
}
nghttp2_hd_static_entry
;
typedef
struct
{
typedef
struct
{
nghttp2_hd_entry
**
buffer
;
nghttp2_hd_entry
**
buffer
;
size_t
mask
;
size_t
mask
;
...
@@ -275,17 +283,14 @@ struct nghttp2_hd_deflater {
...
@@ -275,17 +283,14 @@ struct nghttp2_hd_deflater {
struct
nghttp2_hd_inflater
{
struct
nghttp2_hd_inflater
{
nghttp2_hd_context
ctx
;
nghttp2_hd_context
ctx
;
/* header buffer */
nghttp2_buf
namebuf
,
valuebuf
;
/* 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
/* header buffer */
emission. This is required because in some cases the
nghttp2_buf
namebuf
,
valuebuf
;
ent_keep->ref == 0 and we have to keep track of it. */
nghttp2_rcbuf
*
namercbuf
,
*
valuercbuf
;
nghttp2_hd_entry
*
ent_keep
;
/* Pointer to the name/value pair which are used in the current
/* Pointer to the name/value pair buffer which is used in the
header emission. */
current header emission. */
nghttp2_rcbuf
*
nv_name_keep
,
*
nv_value_keep
;
uint8_t
*
nv_name_keep
,
*
nv_value_keep
;
/* The number of bytes to read */
/* The number of bytes to read */
size_t
left
;
size_t
left
;
/* The index in indexed repr or indexed name */
/* The index in indexed repr or indexed name */
...
@@ -309,24 +314,16 @@ struct nghttp2_hd_inflater {
...
@@ -309,24 +314,16 @@ struct nghttp2_hd_inflater {
};
};
/*
/*
* Initializes the |ent| members. If NGHTTP2_HD_FLAG_NAME_ALLOC bit
* Initializes the |ent| members. The reference counts of nv->name
* set in the |flags|, the content pointed by the |name| with length
* and nv->value are increased by one for each.
* |namelen| is copied. Likewise, if NGHTTP2_HD_FLAG_VALUE_ALLOC bit
* set in the |flags|, the content pointed by the |value| with length
* |valuelen| is copied. The |token| is enum number looked up by
* |name|. It could be -1 if we don't have that enum value.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
*/
int
nghttp2_hd_entry_init
(
nghttp2_hd_entry
*
ent
,
uint8_t
flags
,
uint8_t
*
name
,
void
nghttp2_hd_entry_init
(
nghttp2_hd_entry
*
ent
,
nghttp2_hd_nv
*
nv
);
size_t
namelen
,
uint8_t
*
value
,
size_t
valuelen
,
int
token
,
nghttp2_mem
*
mem
);
void
nghttp2_hd_entry_free
(
nghttp2_hd_entry
*
ent
,
nghttp2_mem
*
mem
);
/*
* This function decreases the reference counts of nv->name and
* nv->value.
*/
void
nghttp2_hd_entry_free
(
nghttp2_hd_entry
*
ent
);
/*
/*
* Initializes |deflater| for deflating name/values pairs.
* Initializes |deflater| for deflating name/values pairs.
...
@@ -407,16 +404,14 @@ int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem);
...
@@ -407,16 +404,14 @@ int nghttp2_hd_inflate_init(nghttp2_hd_inflater *inflater, nghttp2_mem *mem);
void
nghttp2_hd_inflate_free
(
nghttp2_hd_inflater
*
inflater
);
void
nghttp2_hd_inflate_free
(
nghttp2_hd_inflater
*
inflater
);
/*
/*
* Similar to nghttp2_hd_inflate_hd(), but this takes additional
* Similar to nghttp2_hd_inflate_hd(), but this takes nghttp2_hd_nv
* output parameter |token|. On successful header emission, it
* instead of nghttp2_nv as output parameter |nv_out|. Other than
* contains nghttp2_token value for nv_out->name. It could be -1 if
* that return values and semantics are the same as
* we don't have enum value for the name. Other than that return
* nghttp2_hd_inflate_hd().
* values and semantics are the same as nghttp2_hd_inflate_hd().
*/
*/
ssize_t
nghttp2_hd_inflate_hd2
(
nghttp2_hd_inflater
*
inflater
,
ssize_t
nghttp2_hd_inflate_hd2
(
nghttp2_hd_inflater
*
inflater
,
nghttp2_nv
*
nv_out
,
int
*
inflate_flags
,
nghttp2_hd_nv
*
nv_out
,
int
*
inflate_flags
,
int
*
token
,
uint8_t
*
in
,
size_t
inlen
,
uint8_t
*
in
,
size_t
inlen
,
int
in_final
);
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
,
...
@@ -430,8 +425,7 @@ int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,
...
@@ -430,8 +425,7 @@ int nghttp2_hd_emit_newname_block(nghttp2_bufs *bufs, nghttp2_nv *nv,
int
nghttp2_hd_emit_table_size
(
nghttp2_bufs
*
bufs
,
size_t
table_size
);
int
nghttp2_hd_emit_table_size
(
nghttp2_bufs
*
bufs
,
size_t
table_size
);
/* For unittesting purpose */
/* For unittesting purpose */
nghttp2_hd_entry
*
nghttp2_hd_table_get
(
nghttp2_hd_context
*
context
,
nghttp2_hd_nv
nghttp2_hd_table_get
(
nghttp2_hd_context
*
context
,
size_t
index
);
size_t
index
);
/* For unittesting purpose */
/* For unittesting purpose */
ssize_t
nghttp2_hd_decode_length
(
uint32_t
*
res
,
size_t
*
shift_ptr
,
int
*
final
,
ssize_t
nghttp2_hd_decode_length
(
uint32_t
*
res
,
size_t
*
shift_ptr
,
int
*
final
,
...
...
lib/nghttp2_http.c
View file @
ff0d137f
...
@@ -82,12 +82,12 @@ static int lws(const uint8_t *s, size_t n) {
...
@@ -82,12 +82,12 @@ static int lws(const uint8_t *s, size_t n) {
return
1
;
return
1
;
}
}
static
int
check_pseudo_header
(
nghttp2_stream
*
stream
,
const
nghttp2_nv
*
nv
,
static
int
check_pseudo_header
(
nghttp2_stream
*
stream
,
const
nghttp2_
hd_
nv
*
nv
,
int
flag
)
{
int
flag
)
{
if
(
stream
->
http_flags
&
flag
)
{
if
(
stream
->
http_flags
&
flag
)
{
return
0
;
return
0
;
}
}
if
(
lws
(
nv
->
value
,
nv
->
value
len
))
{
if
(
lws
(
nv
->
value
->
base
,
nv
->
value
->
len
))
{
return
0
;
return
0
;
}
}
stream
->
http_flags
=
(
uint16_t
)(
stream
->
http_flags
|
flag
);
stream
->
http_flags
=
(
uint16_t
)(
stream
->
http_flags
|
flag
);
...
@@ -112,16 +112,16 @@ static int check_path(nghttp2_stream *stream) {
...
@@ -112,16 +112,16 @@ static int check_path(nghttp2_stream *stream) {
(
stream
->
http_flags
&
NGHTTP2_HTTP_FLAG_PATH_ASTERISK
)));
(
stream
->
http_flags
&
NGHTTP2_HTTP_FLAG_PATH_ASTERISK
)));
}
}
static
int
http_request_on_header
(
nghttp2_stream
*
stream
,
nghttp2_nv
*
nv
,
static
int
http_request_on_header
(
nghttp2_stream
*
stream
,
nghttp2_
hd_
nv
*
nv
,
int
t
oken
,
int
t
railer
)
{
int
trailer
)
{
if
(
nv
->
name
[
0
]
==
':'
)
{
if
(
nv
->
name
->
base
[
0
]
==
':'
)
{
if
(
trailer
||
if
(
trailer
||
(
stream
->
http_flags
&
NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED
))
{
(
stream
->
http_flags
&
NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED
))
{
return
NGHTTP2_ERR_HTTP_HEADER
;
return
NGHTTP2_ERR_HTTP_HEADER
;
}
}
}
}
switch
(
token
)
{
switch
(
nv
->
token
)
{
case
NGHTTP2_TOKEN__AUTHORITY
:
case
NGHTTP2_TOKEN__AUTHORITY
:
if
(
!
check_pseudo_header
(
stream
,
nv
,
NGHTTP2_HTTP_FLAG__AUTHORITY
))
{
if
(
!
check_pseudo_header
(
stream
,
nv
,
NGHTTP2_HTTP_FLAG__AUTHORITY
))
{
return
NGHTTP2_ERR_HTTP_HEADER
;
return
NGHTTP2_ERR_HTTP_HEADER
;
...
@@ -131,16 +131,16 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
...
@@ -131,16 +131,16 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
if
(
!
check_pseudo_header
(
stream
,
nv
,
NGHTTP2_HTTP_FLAG__METHOD
))
{
if
(
!
check_pseudo_header
(
stream
,
nv
,
NGHTTP2_HTTP_FLAG__METHOD
))
{
return
NGHTTP2_ERR_HTTP_HEADER
;
return
NGHTTP2_ERR_HTTP_HEADER
;
}
}
switch
(
nv
->
valuelen
)
{
switch
(
nv
->
value
->
len
)
{
case
4
:
case
4
:
if
(
lstreq
(
"HEAD"
,
nv
->
value
,
nv
->
value
len
))
{
if
(
lstreq
(
"HEAD"
,
nv
->
value
->
base
,
nv
->
value
->
len
))
{
stream
->
http_flags
|=
NGHTTP2_HTTP_FLAG_METH_HEAD
;
stream
->
http_flags
|=
NGHTTP2_HTTP_FLAG_METH_HEAD
;
}
}
break
;
break
;
case
7
:
case
7
:
switch
(
nv
->
value
[
6
])
{
switch
(
nv
->
value
->
base
[
6
])
{
case
'T'
:
case
'T'
:
if
(
lstreq
(
"CONNECT"
,
nv
->
value
,
nv
->
value
len
))
{
if
(
lstreq
(
"CONNECT"
,
nv
->
value
->
base
,
nv
->
value
->
len
))
{
if
(
stream
->
stream_id
%
2
==
0
)
{
if
(
stream
->
stream_id
%
2
==
0
)
{
/* we won't allow CONNECT for push */
/* we won't allow CONNECT for push */
return
NGHTTP2_ERR_HTTP_HEADER
;
return
NGHTTP2_ERR_HTTP_HEADER
;
...
@@ -153,7 +153,7 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
...
@@ -153,7 +153,7 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
}
}
break
;
break
;
case
'S'
:
case
'S'
:
if
(
lstreq
(
"OPTIONS"
,
nv
->
value
,
nv
->
value
len
))
{
if
(
lstreq
(
"OPTIONS"
,
nv
->
value
->
base
,
nv
->
value
->
len
))
{
stream
->
http_flags
|=
NGHTTP2_HTTP_FLAG_METH_OPTIONS
;
stream
->
http_flags
|=
NGHTTP2_HTTP_FLAG_METH_OPTIONS
;
}
}
break
;
break
;
...
@@ -168,9 +168,9 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
...
@@ -168,9 +168,9 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
if
(
!
check_pseudo_header
(
stream
,
nv
,
NGHTTP2_HTTP_FLAG__PATH
))
{
if
(
!
check_pseudo_header
(
stream
,
nv
,
NGHTTP2_HTTP_FLAG__PATH
))
{
return
NGHTTP2_ERR_HTTP_HEADER
;
return
NGHTTP2_ERR_HTTP_HEADER
;
}
}
if
(
nv
->
value
[
0
]
==
'/'
)
{
if
(
nv
->
value
->
base
[
0
]
==
'/'
)
{
stream
->
http_flags
|=
NGHTTP2_HTTP_FLAG_PATH_REGULAR
;
stream
->
http_flags
|=
NGHTTP2_HTTP_FLAG_PATH_REGULAR
;
}
else
if
(
nv
->
value
len
==
1
&&
nv
->
valu
e
[
0
]
==
'*'
)
{
}
else
if
(
nv
->
value
->
len
==
1
&&
nv
->
value
->
bas
e
[
0
]
==
'*'
)
{
stream
->
http_flags
|=
NGHTTP2_HTTP_FLAG_PATH_ASTERISK
;
stream
->
http_flags
|=
NGHTTP2_HTTP_FLAG_PATH_ASTERISK
;
}
}
break
;
break
;
...
@@ -181,8 +181,8 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
...
@@ -181,8 +181,8 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
if
(
!
check_pseudo_header
(
stream
,
nv
,
NGHTTP2_HTTP_FLAG__SCHEME
))
{
if
(
!
check_pseudo_header
(
stream
,
nv
,
NGHTTP2_HTTP_FLAG__SCHEME
))
{
return
NGHTTP2_ERR_HTTP_HEADER
;
return
NGHTTP2_ERR_HTTP_HEADER
;
}
}
if
((
nv
->
value
len
==
4
&&
memieq
(
"http"
,
nv
->
valu
e
,
4
))
||
if
((
nv
->
value
->
len
==
4
&&
memieq
(
"http"
,
nv
->
value
->
bas
e
,
4
))
||
(
nv
->
value
len
==
5
&&
memieq
(
"https"
,
nv
->
valu
e
,
5
)))
{
(
nv
->
value
->
len
==
5
&&
memieq
(
"https"
,
nv
->
value
->
bas
e
,
5
)))
{
stream
->
http_flags
|=
NGHTTP2_HTTP_FLAG_SCHEME_HTTP
;
stream
->
http_flags
|=
NGHTTP2_HTTP_FLAG_SCHEME_HTTP
;
}
}
break
;
break
;
...
@@ -195,7 +195,7 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
...
@@ -195,7 +195,7 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
if
(
stream
->
content_length
!=
-
1
)
{
if
(
stream
->
content_length
!=
-
1
)
{
return
NGHTTP2_ERR_HTTP_HEADER
;
return
NGHTTP2_ERR_HTTP_HEADER
;
}
}
stream
->
content_length
=
parse_uint
(
nv
->
value
,
nv
->
value
len
);
stream
->
content_length
=
parse_uint
(
nv
->
value
->
base
,
nv
->
value
->
len
);
if
(
stream
->
content_length
==
-
1
)
{
if
(
stream
->
content_length
==
-
1
)
{
return
NGHTTP2_ERR_HTTP_HEADER
;
return
NGHTTP2_ERR_HTTP_HEADER
;
}
}
...
@@ -209,41 +209,41 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
...
@@ -209,41 +209,41 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
case
NGHTTP2_TOKEN_UPGRADE
:
case
NGHTTP2_TOKEN_UPGRADE
:
return
NGHTTP2_ERR_HTTP_HEADER
;
return
NGHTTP2_ERR_HTTP_HEADER
;
case
NGHTTP2_TOKEN_TE
:
case
NGHTTP2_TOKEN_TE
:
if
(
!
lstrieq
(
"trailers"
,
nv
->
value
,
nv
->
value
len
))
{
if
(
!
lstrieq
(
"trailers"
,
nv
->
value
->
base
,
nv
->
value
->
len
))
{
return
NGHTTP2_ERR_HTTP_HEADER
;
return
NGHTTP2_ERR_HTTP_HEADER
;
}
}
break
;
break
;
default:
default:
if
(
nv
->
name
[
0
]
==
':'
)
{
if
(
nv
->
name
->
base
[
0
]
==
':'
)
{
return
NGHTTP2_ERR_HTTP_HEADER
;
return
NGHTTP2_ERR_HTTP_HEADER
;
}
}
}
}
if
(
nv
->
name
[
0
]
!=
':'
)
{
if
(
nv
->
name
->
base
[
0
]
!=
':'
)
{
stream
->
http_flags
|=
NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED
;
stream
->
http_flags
|=
NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED
;
}
}
return
0
;
return
0
;
}
}
static
int
http_response_on_header
(
nghttp2_stream
*
stream
,
nghttp2_nv
*
nv
,
static
int
http_response_on_header
(
nghttp2_stream
*
stream
,
nghttp2_
hd_
nv
*
nv
,
int
t
oken
,
int
t
railer
)
{
int
trailer
)
{
if
(
nv
->
name
[
0
]
==
':'
)
{
if
(
nv
->
name
->
base
[
0
]
==
':'
)
{
if
(
trailer
||
if
(
trailer
||
(
stream
->
http_flags
&
NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED
))
{
(
stream
->
http_flags
&
NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED
))
{
return
NGHTTP2_ERR_HTTP_HEADER
;
return
NGHTTP2_ERR_HTTP_HEADER
;
}
}
}
}
switch
(
token
)
{
switch
(
nv
->
token
)
{
case
NGHTTP2_TOKEN__STATUS
:
{
case
NGHTTP2_TOKEN__STATUS
:
{
if
(
!
check_pseudo_header
(
stream
,
nv
,
NGHTTP2_HTTP_FLAG__STATUS
))
{
if
(
!
check_pseudo_header
(
stream
,
nv
,
NGHTTP2_HTTP_FLAG__STATUS
))
{
return
NGHTTP2_ERR_HTTP_HEADER
;
return
NGHTTP2_ERR_HTTP_HEADER
;
}
}
if
(
nv
->
valuelen
!=
3
)
{
if
(
nv
->
value
->
len
!=
3
)
{
return
NGHTTP2_ERR_HTTP_HEADER
;
return
NGHTTP2_ERR_HTTP_HEADER
;
}
}
stream
->
status_code
=
(
int16_t
)
parse_uint
(
nv
->
value
,
nv
->
value
len
);
stream
->
status_code
=
(
int16_t
)
parse_uint
(
nv
->
value
->
base
,
nv
->
value
->
len
);
if
(
stream
->
status_code
==
-
1
)
{
if
(
stream
->
status_code
==
-
1
)
{
return
NGHTTP2_ERR_HTTP_HEADER
;
return
NGHTTP2_ERR_HTTP_HEADER
;
}
}
...
@@ -253,7 +253,7 @@ static int http_response_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
...
@@ -253,7 +253,7 @@ static int http_response_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
if
(
stream
->
content_length
!=
-
1
)
{
if
(
stream
->
content_length
!=
-
1
)
{
return
NGHTTP2_ERR_HTTP_HEADER
;
return
NGHTTP2_ERR_HTTP_HEADER
;
}
}
stream
->
content_length
=
parse_uint
(
nv
->
value
,
nv
->
value
len
);
stream
->
content_length
=
parse_uint
(
nv
->
value
->
base
,
nv
->
value
->
len
);
if
(
stream
->
content_length
==
-
1
)
{
if
(
stream
->
content_length
==
-
1
)
{
return
NGHTTP2_ERR_HTTP_HEADER
;
return
NGHTTP2_ERR_HTTP_HEADER
;
}
}
...
@@ -267,17 +267,17 @@ static int http_response_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
...
@@ -267,17 +267,17 @@ static int http_response_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
case
NGHTTP2_TOKEN_UPGRADE
:
case
NGHTTP2_TOKEN_UPGRADE
:
return
NGHTTP2_ERR_HTTP_HEADER
;
return
NGHTTP2_ERR_HTTP_HEADER
;
case
NGHTTP2_TOKEN_TE
:
case
NGHTTP2_TOKEN_TE
:
if
(
!
lstrieq
(
"trailers"
,
nv
->
value
,
nv
->
value
len
))
{
if
(
!
lstrieq
(
"trailers"
,
nv
->
value
->
base
,
nv
->
value
->
len
))
{
return
NGHTTP2_ERR_HTTP_HEADER
;
return
NGHTTP2_ERR_HTTP_HEADER
;
}
}
break
;
break
;
default:
default:
if
(
nv
->
name
[
0
]
==
':'
)
{
if
(
nv
->
name
->
base
[
0
]
==
':'
)
{
return
NGHTTP2_ERR_HTTP_HEADER
;
return
NGHTTP2_ERR_HTTP_HEADER
;
}
}
}
}
if
(
nv
->
name
[
0
]
!=
':'
)
{
if
(
nv
->
name
->
base
[
0
]
!=
':'
)
{
stream
->
http_flags
|=
NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED
;
stream
->
http_flags
|=
NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED
;
}
}
...
@@ -375,7 +375,7 @@ static int check_scheme(const uint8_t *value, size_t len) {
...
@@ -375,7 +375,7 @@ static int check_scheme(const uint8_t *value, size_t len) {
}
}
int
nghttp2_http_on_header
(
nghttp2_session
*
session
,
nghttp2_stream
*
stream
,
int
nghttp2_http_on_header
(
nghttp2_session
*
session
,
nghttp2_stream
*
stream
,
nghttp2_frame
*
frame
,
nghttp2_
nv
*
nv
,
int
token
,
nghttp2_frame
*
frame
,
nghttp2_
hd_nv
*
nv
,
int
trailer
)
{
int
trailer
)
{
int
rv
;
int
rv
;
...
@@ -386,14 +386,14 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
...
@@ -386,14 +386,14 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
this, we may disrupt many web sites and/or libraries. So we
this, we may disrupt many web sites and/or libraries. So we
become conservative here, and just ignore those illegal regular
become conservative here, and just ignore those illegal regular
headers. */
headers. */
if
(
!
nghttp2_check_header_name
(
nv
->
name
,
nv
->
name
len
))
{
if
(
!
nghttp2_check_header_name
(
nv
->
name
->
base
,
nv
->
name
->
len
))
{
size_t
i
;
size_t
i
;
if
(
nv
->
name
len
>
0
&&
nv
->
nam
e
[
0
]
==
':'
)
{
if
(
nv
->
name
->
len
>
0
&&
nv
->
name
->
bas
e
[
0
]
==
':'
)
{
return
NGHTTP2_ERR_HTTP_HEADER
;
return
NGHTTP2_ERR_HTTP_HEADER
;
}
}
/* header field name must be lower-cased without exception */
/* header field name must be lower-cased without exception */
for
(
i
=
0
;
i
<
nv
->
namelen
;
++
i
)
{
for
(
i
=
0
;
i
<
nv
->
name
->
len
;
++
i
)
{
uint8_t
c
=
nv
->
name
[
i
];
uint8_t
c
=
nv
->
name
->
base
[
i
];
if
(
'A'
<=
c
&&
c
<=
'Z'
)
{
if
(
'A'
<=
c
&&
c
<=
'Z'
)
{
return
NGHTTP2_ERR_HTTP_HEADER
;
return
NGHTTP2_ERR_HTTP_HEADER
;
}
}
...
@@ -405,17 +405,18 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
...
@@ -405,17 +405,18 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
return
NGHTTP2_ERR_IGN_HTTP_HEADER
;
return
NGHTTP2_ERR_IGN_HTTP_HEADER
;
}
}
if
(
token
==
NGHTTP2_TOKEN__AUTHORITY
||
token
==
NGHTTP2_TOKEN_HOST
)
{
if
(
nv
->
token
==
NGHTTP2_TOKEN__AUTHORITY
||
rv
=
check_authority
(
nv
->
value
,
nv
->
valuelen
);
nv
->
token
==
NGHTTP2_TOKEN_HOST
)
{
}
else
if
(
token
==
NGHTTP2_TOKEN__SCHEME
)
{
rv
=
check_authority
(
nv
->
value
->
base
,
nv
->
value
->
len
);
rv
=
check_scheme
(
nv
->
value
,
nv
->
valuelen
);
}
else
if
(
nv
->
token
==
NGHTTP2_TOKEN__SCHEME
)
{
rv
=
check_scheme
(
nv
->
value
->
base
,
nv
->
value
->
len
);
}
else
{
}
else
{
rv
=
nghttp2_check_header_value
(
nv
->
value
,
nv
->
value
len
);
rv
=
nghttp2_check_header_value
(
nv
->
value
->
base
,
nv
->
value
->
len
);
}
}
if
(
rv
==
0
)
{
if
(
rv
==
0
)
{
assert
(
nv
->
namelen
>
0
);
assert
(
nv
->
name
->
len
>
0
);
if
(
nv
->
name
[
0
]
==
':'
)
{
if
(
nv
->
name
->
base
[
0
]
==
':'
)
{
return
NGHTTP2_ERR_HTTP_HEADER
;
return
NGHTTP2_ERR_HTTP_HEADER
;
}
}
/* When ignoring regular headers, we set this flag so that we
/* When ignoring regular headers, we set this flag so that we
...
@@ -426,10 +427,10 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
...
@@ -426,10 +427,10 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
}
}
if
(
session
->
server
||
frame
->
hd
.
type
==
NGHTTP2_PUSH_PROMISE
)
{
if
(
session
->
server
||
frame
->
hd
.
type
==
NGHTTP2_PUSH_PROMISE
)
{
return
http_request_on_header
(
stream
,
nv
,
t
oken
,
t
railer
);
return
http_request_on_header
(
stream
,
nv
,
trailer
);
}
}
return
http_response_on_header
(
stream
,
nv
,
t
oken
,
t
railer
);
return
http_response_on_header
(
stream
,
nv
,
trailer
);
}
}
int
nghttp2_http_on_request_headers
(
nghttp2_stream
*
stream
,
int
nghttp2_http_on_request_headers
(
nghttp2_stream
*
stream
,
...
...
lib/nghttp2_http.h
View file @
ff0d137f
...
@@ -36,8 +36,7 @@
...
@@ -36,8 +36,7 @@
/*
/*
* This function is called when HTTP header field |nv| in |frame| is
* This function is called when HTTP header field |nv| in |frame| is
* received for |stream|. This function will validate |nv| against
* received for |stream|. This function will validate |nv| against
* the current state of stream. The |token| is nghttp2_token value
* the current state of stream.
* for nv->name, or -1 if we don't have enum value for the name.
*
*
* This function returns 0 if it succeeds, or one of the following
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
* negative error codes:
...
@@ -49,7 +48,7 @@
...
@@ -49,7 +48,7 @@
* if it was not received because of compatibility reasons.
* if it was not received because of compatibility reasons.
*/
*/
int
nghttp2_http_on_header
(
nghttp2_session
*
session
,
nghttp2_stream
*
stream
,
int
nghttp2_http_on_header
(
nghttp2_session
*
session
,
nghttp2_stream
*
stream
,
nghttp2_frame
*
frame
,
nghttp2_
nv
*
nv
,
int
token
,
nghttp2_frame
*
frame
,
nghttp2_
hd_nv
*
nv
,
int
trailer
);
int
trailer
);
/*
/*
...
...
lib/nghttp2_mem.c
View file @
ff0d137f
...
@@ -52,6 +52,10 @@ void nghttp2_mem_free(nghttp2_mem *mem, void *ptr) {
...
@@ -52,6 +52,10 @@ void nghttp2_mem_free(nghttp2_mem *mem, void *ptr) {
mem
->
free
(
ptr
,
mem
->
mem_user_data
);
mem
->
free
(
ptr
,
mem
->
mem_user_data
);
}
}
void
nghttp2_mem_free2
(
nghttp2_free
free
,
void
*
ptr
,
void
*
mem_user_data
)
{
free
(
ptr
,
mem_user_data
);
}
void
*
nghttp2_mem_calloc
(
nghttp2_mem
*
mem
,
size_t
nmemb
,
size_t
size
)
{
void
*
nghttp2_mem_calloc
(
nghttp2_mem
*
mem
,
size_t
nmemb
,
size_t
size
)
{
return
mem
->
calloc
(
nmemb
,
size
,
mem
->
mem_user_data
);
return
mem
->
calloc
(
nmemb
,
size
,
mem
->
mem_user_data
);
}
}
...
...
lib/nghttp2_mem.h
View file @
ff0d137f
...
@@ -38,6 +38,7 @@ nghttp2_mem *nghttp2_mem_default(void);
...
@@ -38,6 +38,7 @@ nghttp2_mem *nghttp2_mem_default(void);
|mem|. */
|mem|. */
void
*
nghttp2_mem_malloc
(
nghttp2_mem
*
mem
,
size_t
size
);
void
*
nghttp2_mem_malloc
(
nghttp2_mem
*
mem
,
size_t
size
);
void
nghttp2_mem_free
(
nghttp2_mem
*
mem
,
void
*
ptr
);
void
nghttp2_mem_free
(
nghttp2_mem
*
mem
,
void
*
ptr
);
void
nghttp2_mem_free2
(
nghttp2_free
free
,
void
*
ptr
,
void
*
mem_user_data
);
void
*
nghttp2_mem_calloc
(
nghttp2_mem
*
mem
,
size_t
nmemb
,
size_t
size
);
void
*
nghttp2_mem_calloc
(
nghttp2_mem
*
mem
,
size_t
nmemb
,
size_t
size
);
void
*
nghttp2_mem_realloc
(
nghttp2_mem
*
mem
,
void
*
ptr
,
size_t
size
);
void
*
nghttp2_mem_realloc
(
nghttp2_mem
*
mem
,
void
*
ptr
,
size_t
size
);
...
...
lib/nghttp2_rcbuf.c
0 → 100644
View file @
ff0d137f
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2016 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include "nghttp2_rcbuf.h"
#include <string.h>
#include <assert.h>
#include "nghttp2_mem.h"
int
nghttp2_rcbuf_new
(
nghttp2_rcbuf
**
rcbuf_ptr
,
size_t
size
,
nghttp2_mem
*
mem
)
{
uint8_t
*
p
;
p
=
nghttp2_mem_malloc
(
mem
,
sizeof
(
nghttp2_rcbuf
)
+
size
);
if
(
p
==
NULL
)
{
return
NGHTTP2_ERR_NOMEM
;
}
*
rcbuf_ptr
=
(
void
*
)
p
;
(
*
rcbuf_ptr
)
->
mem_user_data
=
mem
->
mem_user_data
;
(
*
rcbuf_ptr
)
->
free
=
mem
->
free
;
(
*
rcbuf_ptr
)
->
base
=
p
+
sizeof
(
nghttp2_rcbuf
);
(
*
rcbuf_ptr
)
->
len
=
size
;
(
*
rcbuf_ptr
)
->
ref
=
1
;
return
0
;
}
int
nghttp2_rcbuf_new2
(
nghttp2_rcbuf
**
rcbuf_ptr
,
const
uint8_t
*
src
,
size_t
srclen
,
nghttp2_mem
*
mem
)
{
int
rv
;
rv
=
nghttp2_rcbuf_new
(
rcbuf_ptr
,
srclen
+
1
,
mem
);
if
(
rv
!=
0
)
{
return
rv
;
}
memcpy
((
*
rcbuf_ptr
)
->
base
,
src
,
srclen
);
(
*
rcbuf_ptr
)
->
len
=
srclen
;
(
*
rcbuf_ptr
)
->
base
[
srclen
]
=
'\0'
;
return
0
;
}
/*
* Frees |rcbuf| itself, regardless of its reference cout.
*/
void
nghttp2_rcbuf_del
(
nghttp2_rcbuf
*
rcbuf
)
{
nghttp2_mem_free2
(
rcbuf
->
free
,
rcbuf
,
rcbuf
->
mem_user_data
);
}
void
nghttp2_rcbuf_incref
(
nghttp2_rcbuf
*
rcbuf
)
{
if
(
rcbuf
->
ref
==
-
1
)
{
return
;
}
++
rcbuf
->
ref
;
}
void
nghttp2_rcbuf_decref
(
nghttp2_rcbuf
*
rcbuf
)
{
if
(
rcbuf
==
NULL
||
rcbuf
->
ref
==
-
1
)
{
return
;
}
assert
(
rcbuf
->
ref
>
0
);
if
(
--
rcbuf
->
ref
==
0
)
{
nghttp2_rcbuf_del
(
rcbuf
);
}
}
nghttp2_vec
nghttp2_rcbuf_get_buf
(
nghttp2_rcbuf
*
rcbuf
)
{
return
(
nghttp2_vec
){
rcbuf
->
base
,
rcbuf
->
len
};
}
lib/nghttp2_rcbuf.h
0 → 100644
View file @
ff0d137f
/*
* nghttp2 - HTTP/2 C Library
*
* Copyright (c) 2016 Tatsuhiro Tsujikawa
*
* Permission is hereby granted, free of charge, to any person obtaining
* a copy of this software and associated documentation files (the
* "Software"), to deal in the Software without restriction, including
* without limitation the rights to use, copy, modify, merge, publish,
* distribute, sublicense, and/or sell copies of the Software, and to
* permit persons to whom the Software is furnished to do so, subject to
* the following conditions:
*
* The above copyright notice and this permission notice shall be
* included in all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
* NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
* LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
* OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
* WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#ifndef NGHTTP2_RCBUF_H
#define NGHTTP2_RCBUF_H
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
/* HAVE_CONFIG_H */
#include <nghttp2/nghttp2.h>
struct
nghttp2_rcbuf
{
/* custom memory allocator belongs to the mem parameter when
creating this object. */
void
*
mem_user_data
;
nghttp2_free
free
;
/* The pointer to the underlying buffer */
uint8_t
*
base
;
/* Size of buffer pointed by |base|. */
size_t
len
;
/* Reference count */
int32_t
ref
;
};
/*
* Allocates nghttp2_rcbuf object with |size| as initial buffer size.
* When the function succeeds, the reference count becomes 1.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM:
* Out of memory.
*/
int
nghttp2_rcbuf_new
(
nghttp2_rcbuf
**
rcbuf_ptr
,
size_t
size
,
nghttp2_mem
*
mem
);
/*
* Like nghttp2_rcbuf_new(), but initializes the buffer with |src| of
* length |srclen|. This function allocates additional byte at the
* end and puts '\0' into it, so that the resulting buffer could be
* used as NULL-terminated string. Still (*rcbuf_ptr)->len equals to
* |srclen|.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM:
* Out of memory.
*/
int
nghttp2_rcbuf_new2
(
nghttp2_rcbuf
**
rcbuf_ptr
,
const
uint8_t
*
src
,
size_t
srclen
,
nghttp2_mem
*
mem
);
/*
* Frees |rcbuf| itself, regardless of its reference cout.
*/
void
nghttp2_rcbuf_del
(
nghttp2_rcbuf
*
rcbuf
);
#endif
/* NGHTTP2_RCBUF_H */
lib/nghttp2_session.c
View file @
ff0d137f
...
@@ -3122,12 +3122,12 @@ static int session_call_on_begin_headers(nghttp2_session *session,
...
@@ -3122,12 +3122,12 @@ static int session_call_on_begin_headers(nghttp2_session *session,
static
int
session_call_on_header
(
nghttp2_session
*
session
,
static
int
session_call_on_header
(
nghttp2_session
*
session
,
const
nghttp2_frame
*
frame
,
const
nghttp2_frame
*
frame
,
const
nghttp2_nv
*
nv
)
{
const
nghttp2_
hd_
nv
*
nv
)
{
int
rv
;
int
rv
;
if
(
session
->
callbacks
.
on_header_callback
)
{
if
(
session
->
callbacks
.
on_header_callback
)
{
rv
=
session
->
callbacks
.
on_header_callback
(
rv
=
session
->
callbacks
.
on_header_callback
(
session
,
frame
,
nv
->
name
,
nv
->
namelen
,
nv
->
value
,
nv
->
valuelen
,
session
,
frame
,
nv
->
name
->
base
,
nv
->
name
->
len
,
nv
->
value
->
base
,
nv
->
flags
,
session
->
user_data
);
nv
->
value
->
len
,
nv
->
flags
,
session
->
user_data
);
if
(
rv
==
NGHTTP2_ERR_PAUSE
||
if
(
rv
==
NGHTTP2_ERR_PAUSE
||
rv
==
NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE
)
{
rv
==
NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE
)
{
return
rv
;
return
rv
;
...
@@ -3317,11 +3317,10 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame,
...
@@ -3317,11 +3317,10 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame,
ssize_t
proclen
;
ssize_t
proclen
;
int
rv
;
int
rv
;
int
inflate_flags
;
int
inflate_flags
;
nghttp2_nv
nv
;
nghttp2_
hd_
nv
nv
;
nghttp2_stream
*
stream
;
nghttp2_stream
*
stream
;
nghttp2_stream
*
subject_stream
;
nghttp2_stream
*
subject_stream
;
int
trailer
=
0
;
int
trailer
=
0
;
int
token
;
*
readlen_ptr
=
0
;
*
readlen_ptr
=
0
;
stream
=
nghttp2_session_get_stream
(
session
,
frame
->
hd
.
stream_id
);
stream
=
nghttp2_session_get_stream
(
session
,
frame
->
hd
.
stream_id
);
...
@@ -3338,7 +3337,7 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame,
...
@@ -3338,7 +3337,7 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame,
for
(;;)
{
for
(;;)
{
inflate_flags
=
0
;
inflate_flags
=
0
;
proclen
=
nghttp2_hd_inflate_hd2
(
&
session
->
hd_inflater
,
&
nv
,
&
inflate_flags
,
proclen
=
nghttp2_hd_inflate_hd2
(
&
session
->
hd_inflater
,
&
nv
,
&
inflate_flags
,
&
token
,
in
,
inlen
,
final
);
in
,
inlen
,
final
);
if
(
nghttp2_is_fatal
((
int
)
proclen
))
{
if
(
nghttp2_is_fatal
((
int
)
proclen
))
{
return
(
int
)
proclen
;
return
(
int
)
proclen
;
}
}
...
@@ -3373,13 +3372,13 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame,
...
@@ -3373,13 +3372,13 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame,
if
(
call_header_cb
&&
(
inflate_flags
&
NGHTTP2_HD_INFLATE_EMIT
))
{
if
(
call_header_cb
&&
(
inflate_flags
&
NGHTTP2_HD_INFLATE_EMIT
))
{
rv
=
0
;
rv
=
0
;
if
(
subject_stream
&&
session_enforce_http_messaging
(
session
))
{
if
(
subject_stream
&&
session_enforce_http_messaging
(
session
))
{
rv
=
nghttp2_http_on_header
(
session
,
subject_stream
,
frame
,
&
nv
,
token
,
rv
=
nghttp2_http_on_header
(
session
,
subject_stream
,
frame
,
&
nv
,
trailer
);
trailer
);
if
(
rv
==
NGHTTP2_ERR_HTTP_HEADER
)
{
if
(
rv
==
NGHTTP2_ERR_HTTP_HEADER
)
{
DEBUGF
(
fprintf
(
DEBUGF
(
fprintf
(
stderr
,
"recv: HTTP error: type=%d, id=%d, header %.*s: %.*s
\n
"
,
stderr
,
"recv: HTTP error: type=%d, id=%d, header %.*s: %.*s
\n
"
,
frame
->
hd
.
type
,
subject_stream
->
stream_id
,
(
int
)
nv
.
namelen
,
frame
->
hd
.
type
,
subject_stream
->
stream_id
,
(
int
)
nv
.
name
->
len
,
nv
.
name
,
(
int
)
nv
.
valuelen
,
nv
.
valu
e
));
nv
.
name
->
base
,
(
int
)
nv
.
value
->
len
,
nv
.
value
->
bas
e
));
rv
=
rv
=
session_handle_invalid_stream2
(
session
,
subject_stream
->
stream_id
,
session_handle_invalid_stream2
(
session
,
subject_stream
->
stream_id
,
...
@@ -3394,8 +3393,8 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame,
...
@@ -3394,8 +3393,8 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame,
/* header is ignored */
/* header is ignored */
DEBUGF
(
fprintf
(
DEBUGF
(
fprintf
(
stderr
,
"recv: HTTP ignored: type=%d, id=%d, header %.*s: %.*s
\n
"
,
stderr
,
"recv: HTTP ignored: type=%d, id=%d, header %.*s: %.*s
\n
"
,
frame
->
hd
.
type
,
subject_stream
->
stream_id
,
(
int
)
nv
.
namelen
,
frame
->
hd
.
type
,
subject_stream
->
stream_id
,
(
int
)
nv
.
name
->
len
,
nv
.
name
,
(
int
)
nv
.
valuelen
,
nv
.
valu
e
));
nv
.
name
->
base
,
(
int
)
nv
.
value
->
len
,
nv
.
value
->
bas
e
));
}
}
}
}
if
(
rv
==
0
)
{
if
(
rv
==
0
)
{
...
...
tests/nghttp2_hd_test.c
View file @
ff0d137f
...
@@ -295,11 +295,6 @@ void test_nghttp2_hd_inflate_indname_inc(void) {
...
@@ -295,11 +295,6 @@ void test_nghttp2_hd_inflate_indname_inc(void) {
assert_nv_equal
(
&
nv
,
out
.
nva
,
1
,
mem
);
assert_nv_equal
(
&
nv
,
out
.
nva
,
1
,
mem
);
CU_ASSERT
(
1
==
inflater
.
ctx
.
hd_table
.
len
);
CU_ASSERT
(
1
==
inflater
.
ctx
.
hd_table
.
len
);
CU_ASSERT
(
62
==
nghttp2_hd_inflate_get_num_table_entries
(
&
inflater
));
CU_ASSERT
(
62
==
nghttp2_hd_inflate_get_num_table_entries
(
&
inflater
));
assert_nv_equal
(
&
nv
,
&
nghttp2_hd_table_get
(
&
inflater
.
ctx
,
NGHTTP2_STATIC_TABLE_LENGTH
+
inflater
.
ctx
.
hd_table
.
len
-
1
)
->
nv
,
1
,
mem
);
assert_nv_equal
(
&
nv
,
nghttp2_hd_inflate_get_table_entry
(
assert_nv_equal
(
&
nv
,
nghttp2_hd_inflate_get_table_entry
(
&
inflater
,
NGHTTP2_STATIC_TABLE_LENGTH
+
&
inflater
,
NGHTTP2_STATIC_TABLE_LENGTH
+
inflater
.
ctx
.
hd_table
.
len
),
inflater
.
ctx
.
hd_table
.
len
),
...
@@ -429,10 +424,9 @@ void test_nghttp2_hd_inflate_newname_inc(void) {
...
@@ -429,10 +424,9 @@ void test_nghttp2_hd_inflate_newname_inc(void) {
CU_ASSERT
(
1
==
out
.
nvlen
);
CU_ASSERT
(
1
==
out
.
nvlen
);
assert_nv_equal
(
&
nv
,
out
.
nva
,
1
,
mem
);
assert_nv_equal
(
&
nv
,
out
.
nva
,
1
,
mem
);
CU_ASSERT
(
1
==
inflater
.
ctx
.
hd_table
.
len
);
CU_ASSERT
(
1
==
inflater
.
ctx
.
hd_table
.
len
);
assert_nv_equal
(
&
nv
,
assert_nv_equal
(
&
nv
,
nghttp2_hd_inflate_get_table_entry
(
&
nghttp2_hd_table_get
(
&
inflater
.
ctx
,
&
inflater
,
NGHTTP2_STATIC_TABLE_LENGTH
+
NGHTTP2_STATIC_TABLE_LENGTH
+
inflater
.
ctx
.
hd_table
.
len
),
inflater
.
ctx
.
hd_table
.
len
-
1
)
->
nv
,
1
,
mem
);
1
,
mem
);
nva_out_reset
(
&
out
,
mem
);
nva_out_reset
(
&
out
,
mem
);
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment