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
9 years ago
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():
def
gen_index_header
():
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) {'''
b
=
build_header
(
HEADERS
)
for
size
in
sorted
(
b
.
keys
()):
...
...
This diff is collapsed.
Click to expand it.
lib/Makefile.am
View file @
ff0d137f
...
...
@@ -47,7 +47,8 @@ OBJECTS = nghttp2_pq.c nghttp2_map.c nghttp2_queue.c \
nghttp2_option.c
\
nghttp2_callbacks.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
\
nghttp2_frame.h
\
...
...
@@ -61,7 +62,8 @@ HFILES = nghttp2_pq.h nghttp2_int.h nghttp2_map.h nghttp2_queue.h \
nghttp2_option.h
\
nghttp2_callbacks.h
\
nghttp2_mem.h
\
nghttp2_http.h
nghttp2_http.h
\
nghttp2_rcbuf.h
libnghttp2_la_SOURCES
=
$(HFILES)
$(OBJECTS)
libnghttp2_la_LDFLAGS
=
-no-undefined
\
...
...
This diff is collapsed.
Click to expand it.
lib/includes/nghttp2/nghttp2.h
View file @
ff0d137f
...
...
@@ -419,6 +419,53 @@ typedef enum {
NGHTTP2_ERR_FLOODED
=
-
904
}
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
*
...
...
This diff is collapsed.
Click to expand it.
lib/nghttp2_hd.c
View file @
ff0d137f
...
...
@@ -34,15 +34,17 @@
/* Make scalar initialization form of nghttp2_hd_entry */
#define MAKE_STATIC_ENT(N, V, T, H) \
{ \
{ (uint8_t *)(N), (uint8_t *)(V), sizeof((N)) - 1, sizeof((V)) - 1, 0 } \
, NULL, 0, (H), (T), 1, NGHTTP2_HD_FLAG_NONE \
{ NULL, NULL, (uint8_t *)(N), sizeof((N)) - 1, -1 } \
, {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 */
/* 3rd parameter is nghttp2_token value for header field name. We use
first enum value if same header names are repeated (e.g.,
:status). */
static
nghttp2_hd_entry
static_table
[]
=
{
static
nghttp2_hd_
static_
entry
static_table
[]
=
{
MAKE_STATIC_ENT
(
":authority"
,
""
,
0
,
3153725150u
),
MAKE_STATIC_ENT
(
":method"
,
"GET"
,
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) {
* This function was generated by genlibtokenlookup.py. Inspired by
* 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
)
{
case
2
:
switch
(
name
[
1
])
{
...
...
@@ -790,86 +792,33 @@ static int lookup_token(const uint8_t *name, size_t namelen) {
return
-
1
;
}
int
nghttp2_hd_entry_init
(
nghttp2_hd_entry
*
ent
,
uint8_t
flags
,
uint8_t
*
name
,
size_t
namelen
,
uint8_t
*
value
,
size_t
valuelen
,
int
token
,
nghttp2_mem
*
mem
)
{
int
rv
=
0
;
/* Since nghttp2_hd_entry is used for indexing, ent->nv.flags always
NGHTTP2_NV_FLAG_NONE */
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
;
void
nghttp2_hd_entry_init
(
nghttp2_hd_entry
*
ent
,
nghttp2_hd_nv
*
nv
)
{
ent
->
nv
=
*
nv
;
ent
->
cnv
.
name
=
nv
->
name
->
base
;
ent
->
cnv
.
namelen
=
nv
->
name
->
len
;
ent
->
cnv
.
value
=
nv
->
value
->
base
;
ent
->
cnv
.
valuelen
=
nv
->
value
->
len
;
ent
->
cnv
.
flags
=
nv
->
flags
;
ent
->
next
=
NULL
;
ent
->
hash
=
0
;
return
0
;
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
;
nghttp2_rcbuf_incref
(
ent
->
nv
.
name
);
nghttp2_rcbuf_incref
(
ent
->
nv
.
value
);
}
void
nghttp2_hd_entry_free
(
nghttp2_hd_entry
*
ent
,
nghttp2_mem
*
mem
)
{
assert
(
ent
->
ref
==
0
);
if
(
ent
->
flags
&
NGHTTP2_HD_FLAG_NAME_ALLOC
)
{
nghttp2_mem_free
(
mem
,
ent
->
nv
.
name
);
}
if
(
ent
->
flags
&
NGHTTP2_HD_FLAG_VALUE_ALLOC
)
{
nghttp2_mem_free
(
mem
,
ent
->
nv
.
value
);
}
void
nghttp2_hd_entry_free
(
nghttp2_hd_entry
*
ent
)
{
nghttp2_rcbuf_decref
(
ent
->
nv
.
value
);
nghttp2_rcbuf_decref
(
ent
->
nv
.
name
);
}
static
int
name_eq
(
const
nghttp2_nv
*
a
,
const
nghttp2_nv
*
b
)
{
return
a
->
namelen
==
b
->
namelen
&&
memeq
(
a
->
name
,
b
->
name
,
a
->
namelen
);
static
int
name_eq
(
const
nghttp2_hd_nv
*
a
,
const
nghttp2_nv
*
b
)
{
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
)
{
return
a
->
valuelen
==
b
->
valuelen
&&
memeq
(
a
->
value
,
b
->
value
,
a
->
valuelen
);
static
int
value_eq
(
const
nghttp2_hd_nv
*
a
,
const
nghttp2_nv
*
b
)
{
return
a
->
value
->
len
==
b
->
valuelen
&&
memeq
(
a
->
value
->
base
,
b
->
value
,
b
->
valuelen
);
}
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) {
}
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
)
{
nghttp2_hd_entry
*
p
;
nghttp2_hd_entry
*
res
=
NULL
;
...
...
@@ -913,7 +862,7 @@ static nghttp2_hd_entry *hd_map_find(nghttp2_hd_map *map, int *exact_match,
*
exact_match
=
0
;
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
))))
{
continue
;
}
...
...
@@ -1008,8 +957,8 @@ static void hd_ringbuf_free(nghttp2_hd_ringbuf *ringbuf, nghttp2_mem *mem) {
}
for
(
i
=
0
;
i
<
ringbuf
->
len
;
++
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
,
ringbuf
->
buffer
);
...
...
@@ -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
->
min_hd_table_bufsize_max
=
UINT32_MAX
;
inflater
->
ent_keep
=
NULL
;
inflater
->
nv_name_keep
=
NULL
;
inflater
->
nv_value_keep
=
NULL
;
...
...
@@ -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
->
valuebuf
);
inflater
->
namercbuf
=
NULL
;
inflater
->
valuercbuf
=
NULL
;
inflater
->
huffman_encoded
=
0
;
inflater
->
index
=
0
;
inflater
->
left
=
0
;
...
...
@@ -1122,21 +1073,10 @@ fail:
}
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
;
nghttp2_mem_free
(
mem
,
inflater
->
nv_name_keep
);
inflater
->
nv_name_keep
=
NULL
;
}
...
...
@@ -1145,13 +1085,11 @@ void nghttp2_hd_deflate_free(nghttp2_hd_deflater *deflater) {
}
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
);
}
...
...
@@ -1159,23 +1097,13 @@ static size_t entry_room(size_t namelen, size_t valuelen) {
return
NGHTTP2_HD_ENTRY_OVERHEAD
+
namelen
+
valuelen
;
}
static
int
emit_indexed_header
(
nghttp2_nv
*
nv_out
,
int
*
token_out
,
nghttp2_hd_entry
*
ent
)
{
DEBUGF
(
fprintf
(
stderr
,
"inflatehd: header emission: %s: %s
\n
"
,
ent
->
nv
.
name
,
ent
->
nv
.
value
));
static
int
emit_header
(
nghttp2_hd_nv
*
nv_out
,
nghttp2_hd_nv
*
nv
)
{
DEBUGF
(
fprintf
(
stderr
,
"inflatehd: header emission: %s: %s
\n
"
,
nv
->
name
->
base
,
nv
->
value
->
base
));
/* ent->ref may be 0. This happens if the encoder emits literal
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
;
*
token_out
=
lookup_token
(
nv
->
name
,
nv
->
namelen
);
return
0
;
}
...
...
@@ -1483,17 +1411,16 @@ static int emit_newname_block(nghttp2_bufs *bufs, const nghttp2_nv *nv,
return
0
;
}
static
nghttp2_hd_entry
*
add_hd_table_incremental
(
nghttp2_hd_context
*
context
,
const
nghttp2_nv
*
nv
,
int
token
,
uint8_t
entry_flags
,
nghttp2_hd_map
*
map
,
uint32_t
hash
)
{
static
int
add_hd_table_incremental
(
nghttp2_hd_context
*
context
,
nghttp2_hd_nv
*
nv
,
nghttp2_hd_map
*
map
,
uint32_t
hash
)
{
int
rv
;
nghttp2_hd_entry
*
new_ent
;
size_t
room
;
nghttp2_mem
*
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
&&
context
->
hd_table
.
len
>
0
)
{
...
...
@@ -1501,72 +1428,53 @@ add_hd_table_incremental(nghttp2_hd_context *context, const nghttp2_nv *nv,
size_t
idx
=
context
->
hd_table
.
len
-
1
;
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
"
,
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
);
if
(
map
)
{
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
));
if
(
new_ent
==
NULL
)
{
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
;
nghttp2_hd_entry_free
(
ent
);
nghttp2_mem_free
(
mem
,
ent
);
}
if
(
room
>
context
->
hd_table_bufsize_max
)
{
/* The entry taking more than NGHTTP2_HD_MAX_BUFFER_SIZE is
immediately evicted. */
--
new_ent
->
ref
;
}
else
{
rv
=
hd_ringbuf_push_front
(
&
context
->
hd_table
,
new_ent
,
mem
);
immediately evicted. So we don't allocate memory for it. */
return
0
;
}
if
(
rv
!=
0
)
{
--
new_ent
->
ref
;
new_ent
=
nghttp2_mem_malloc
(
mem
,
sizeof
(
nghttp2_hd_entry
));
if
(
new_ent
==
NULL
)
{
return
NGHTTP2_ERR_NOMEM
;
}
if
((
entry_flags
&
NGHTTP2_HD_FLAG_NAME_ALLOC
)
&&
(
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_init
(
new_ent
,
nv
);
nghttp2_hd_entry_free
(
new_ent
,
mem
);
nghttp2_mem_free
(
mem
,
new_ent
);
rv
=
hd_ringbuf_push_front
(
&
context
->
hd_table
,
new_ent
,
mem
);
return
NULL
;
}
if
(
rv
!=
0
)
{
nghttp2_hd_entry_free
(
new_ent
);
nghttp2_mem_free
(
mem
,
new_ent
);
new_ent
->
seq
=
context
->
next_seq
++
;
new_ent
->
hash
=
hash
;
return
rv
;
}
if
(
map
)
{
hd_map_insert
(
map
,
new_ent
);
}
new_ent
->
seq
=
context
->
next_seq
++
;
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
{
...
...
@@ -1575,10 +1483,11 @@ typedef struct {
uint8_t
name_value_match
;
}
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
)
{
search_result
res
=
{
token
,
0
};
int
i
;
nghttp2_hd_static_entry
*
ent
;
if
(
indexing_mode
==
NGHTTP2_HD_NEVER_INDEXING
)
{
return
res
;
...
...
@@ -1587,7 +1496,9 @@ static search_result search_static_table(const nghttp2_nv *nv, int token,
for
(
i
=
token
;
i
<=
NGHTTP2_TOKEN_WWW_AUTHENTICATE
&&
static_table
[
i
].
token
==
token
;
++
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
.
name_value_match
=
1
;
return
res
;
...
...
@@ -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
,
const
nghttp2_nv
*
nv
,
int
token
,
const
nghttp2_nv
*
nv
,
int
32_t
token
,
int
indexing_mode
,
nghttp2_hd_map
*
map
,
uint32_t
hash
)
{
search_result
res
=
{
-
1
,
0
};
...
...
@@ -1641,15 +1552,15 @@ static void hd_context_shrink_table_size(nghttp2_hd_context *context,
context
->
hd_table
.
len
>
0
)
{
size_t
idx
=
context
->
hd_table
.
len
-
1
;
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
);
if
(
map
)
{
hd_map_remove
(
map
,
ent
);
}
if
(
--
ent
->
ref
==
0
)
{
nghttp2_hd_entry_free
(
ent
,
mem
);
nghttp2_mem_free
(
mem
,
ent
);
}
nghttp2_hd_entry_free
(
ent
);
nghttp2_mem_free
(
mem
,
ent
);
}
}
...
...
@@ -1708,19 +1619,33 @@ static size_t get_max_index(nghttp2_hd_context *context) {
return
context
->
hd_table
.
len
+
NGHTTP2_STATIC_TABLE_LENGTH
-
1
;
}
nghttp2_hd_entry
*
nghttp2_hd_table_get
(
nghttp2_hd_context
*
context
,
size_t
idx
)
{
nghttp2_hd_nv
nghttp2_hd_table_get
(
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
)
;
return
hd_ringbuf_get
(
&
context
->
hd_table
,
idx
-
NGHTTP2_STATIC_TABLE_LENGTH
)
->
nv
;
}
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
,
const
nghttp2_nv
*
nv
,
int
token
)
{
const
nghttp2_nv
*
nv
,
int
32_t
token
)
{
if
(
token
==
NGHTTP2_TOKEN__PATH
||
token
==
NGHTTP2_TOKEN_AGE
||
token
==
NGHTTP2_TOKEN_CONTENT_LENGTH
||
token
==
NGHTTP2_TOKEN_ETAG
||
token
==
NGHTTP2_TOKEN_IF_MODIFIED_SINCE
||
...
...
@@ -1740,7 +1665,7 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
search_result
res
;
ssize_t
idx
;
int
indexing_mode
;
int
token
;
int
32_t
token
;
nghttp2_mem
*
mem
;
uint32_t
hash
=
0
;
...
...
@@ -1789,27 +1714,35 @@ static int deflate_nv(nghttp2_hd_deflater *deflater, nghttp2_bufs *bufs,
}
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
)
{
nghttp2_nv
nv_indname
;
nv_indname
=
*
nv
;
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
);
hd_nv
.
name
=
nghttp2_hd_table_get
(
&
deflater
->
ctx
,
(
size_t
)
idx
).
name
;
nghttp2_rcbuf_incref
(
hd_nv
.
name
);
}
else
{
new_ent
=
add_hd_table_incremental
(
&
deflater
->
ctx
,
nv
,
token
,
NGHTTP2_HD_FLAG_NAME_ALLOC
|
NGHTTP2_HD_FLAG_VALUE_ALLOC
,
&
deflater
->
map
,
hash
);
rv
=
nghttp2_rcbuf_new2
(
&
hd_nv
.
name
,
nv
->
name
,
nv
->
namelen
,
mem
);
if
(
rv
!=
0
)
{
return
rv
;
}
}
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
);
nghttp2_mem_free
(
mem
,
new_ent
);
hd_nv
.
token
=
token
;
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
)
{
...
...
@@ -2093,10 +2026,10 @@ static ssize_t hd_inflate_read(nghttp2_hd_inflater *inflater, nghttp2_buf *buf,
* Out of memory
*/
static
int
hd_inflate_commit_indexed
(
nghttp2_hd_inflater
*
inflater
,
nghttp2_
nv
*
nv_out
,
int
*
token
_out
)
{
nghttp2_hd_
entry
*
ent
=
nghttp2_hd_table_get
(
&
inflater
->
ctx
,
inflater
->
index
);
nghttp2_
hd_nv
*
nv
_out
)
{
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
;
}
...
...
@@ -2113,19 +2046,9 @@ static int hd_inflate_commit_indexed(nghttp2_hd_inflater *inflater,
* Out of memory
*/
static
int
hd_inflate_commit_newname
(
nghttp2_hd_inflater
*
inflater
,
nghttp2_nv
*
nv_out
,
int
*
token_out
)
{
nghttp2_nv
nv
;
nghttp2_mem
*
mem
;
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
);
nghttp2_hd_nv
*
nv_out
)
{
nghttp2_hd_nv
nv
;
int
rv
;
if
(
inflater
->
no_index
)
{
nv
.
flags
=
NGHTTP2_NV_FLAG_NO_INDEX
;
...
...
@@ -2133,35 +2056,26 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
nv
.
flags
=
NGHTTP2_NV_FLAG_NONE
;
}
if
(
inflater
->
index_required
)
{
nghttp2_hd_entry
*
new_ent
;
uint8_t
ent_flags
;
ent_flags
=
NGHTTP2_HD_FLAG_NAME_ALLOC
|
NGHTTP2_HD_FLAG_NAME_GIFT
|
NGHTTP2_HD_FLAG_VALUE_ALLOC
|
NGHTTP2_HD_FLAG_VALUE_GIFT
;
nv
.
name
=
inflater
->
namercbuf
;
nv
.
value
=
inflater
->
valuercbuf
;
nv
.
token
=
lookup_token
(
inflater
->
namercbuf
->
base
,
inflater
->
namercbuf
->
len
);
new_ent
=
add_hd_table_incremental
(
&
inflater
->
ctx
,
&
nv
,
lookup_token
(
nv
.
name
,
nv
.
namelen
),
ent_flags
,
NULL
,
0
);
if
(
new_ent
)
{
emit_indexed_header
(
nv_out
,
token_out
,
new_ent
);
inflater
->
ent_keep
=
new_ent
;
if
(
inflater
->
index_required
)
{
rv
=
add_hd_table_incremental
(
&
inflater
->
ctx
,
&
nv
,
NULL
,
0
);
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_value_keep
=
nv
.
value
;
inflater
->
namercbuf
=
NULL
;
inflater
->
valuercbuf
=
NULL
;
return
0
;
}
...
...
@@ -2177,12 +2091,11 @@ static int hd_inflate_commit_newname(nghttp2_hd_inflater *inflater,
* Out of memory
*/
static
int
hd_inflate_commit_indname
(
nghttp2_hd_inflater
*
inflater
,
nghttp2_nv
*
nv_out
,
int
*
token_out
)
{
nghttp2_nv
nv
;
nghttp2_hd_entry
*
ent_name
;
nghttp2_mem
*
mem
;
nghttp2_hd_nv
*
nv_out
)
{
nghttp2_hd_nv
nv
;
int
rv
;
mem
=
inflater
->
ctx
.
mem
;
nv
=
nghttp2_hd_table_get
(
&
inflater
->
ctx
,
inflater
->
index
)
;
if
(
inflater
->
no_index
)
{
nv
.
flags
=
NGHTTP2_NV_FLAG_NO_INDEX
;
...
...
@@ -2190,72 +2103,57 @@ static int hd_inflate_commit_indname(nghttp2_hd_inflater *inflater,
nv
.
flags
=
NGHTTP2_NV_FLAG_NONE
;
}
ent_name
=
nghttp2_hd_table_get
(
&
inflater
->
ctx
,
inflater
->
index
);
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_rcbuf_incref
(
nv
.
name
);
nghttp2_buf_init
(
&
inflater
->
valuebuf
)
;
nv
.
value
=
inflater
->
valuercbuf
;
new_ent
=
add_hd_table_incremental
(
&
inflater
->
ctx
,
&
nv
,
ent_name
->
token
,
ent_flags
,
NULL
,
0
);
/* At this point, ent_name might be deleted. */
if
(
new_ent
)
{
emit_indexed_header
(
nv_out
,
token_out
,
new_ent
);
inflater
->
ent_keep
=
new_ent
;
return
0
;
if
(
inflater
->
index_required
)
{
rv
=
add_hd_table_incremental
(
&
inflater
->
ctx
,
&
nv
,
NULL
,
0
);
if
(
rv
!=
0
)
{
nghttp2_rcbuf_decref
(
nv
.
name
);
return
NGHTTP2_ERR_NOMEM
;
}
nghttp2_mem_free
(
mem
,
nv
.
value
);
return
NGHTTP2_ERR_NOMEM
;
}
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
);
emit_literal_header
(
nv_out
,
token_out
,
&
nv
);
emit_header
(
nv_out
,
&
nv
);
inflater
->
nv_name_keep
=
nv
.
name
;
inflater
->
nv_value_keep
=
nv
.
value
;
inflater
->
valuercbuf
=
NULL
;
return
0
;
}
ssize_t
nghttp2_hd_inflate_hd
(
nghttp2_hd_inflater
*
inflater
,
nghttp2_nv
*
nv_out
,
int
*
inflate_flags
,
uint8_t
*
in
,
size_t
inlen
,
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
,
inlen
,
in_final
);
return
rv
;
}
ssize_t
nghttp2_hd_inflate_hd2
(
nghttp2_hd_inflater
*
inflater
,
nghttp2_nv
*
nv_out
,
int
*
inflate_flags
,
int
*
token_out
,
uint8_t
*
in
,
size_t
inlen
,
int
in_final
)
{
nghttp2_hd_nv
*
nv_out
,
int
*
inflate_flags
,
uint8_t
*
in
,
size_t
inlen
,
int
in_final
)
{
ssize_t
rv
=
0
;
uint8_t
*
first
=
in
;
uint8_t
*
last
=
in
+
inlen
;
...
...
@@ -2271,7 +2169,6 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
DEBUGF
(
fprintf
(
stderr
,
"inflatehd: start state=%d
\n
"
,
inflater
->
state
));
hd_inflate_keep_free
(
inflater
);
*
token_out
=
-
1
;
*
inflate_flags
=
NGHTTP2_HD_INFLATE_NONE
;
for
(;
in
!=
last
||
busy
;)
{
busy
=
0
;
...
...
@@ -2377,7 +2274,7 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
inflater
->
index
=
inflater
->
left
;
--
inflater
->
index
;
rv
=
hd_inflate_commit_indexed
(
inflater
,
nv_out
,
token_out
);
rv
=
hd_inflate_commit_indexed
(
inflater
,
nv_out
);
if
(
rv
<
0
)
{
goto
fail
;
}
...
...
@@ -2422,17 +2319,21 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
nghttp2_hd_huff_decode_context_init
(
&
inflater
->
huff_decode_ctx
);
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
{
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
)
{
goto
fail
;
}
nghttp2_buf_wrap_init
(
&
inflater
->
namebuf
,
inflater
->
namercbuf
->
base
,
inflater
->
namercbuf
->
len
);
break
;
case
NGHTTP2_HD_STATE_NEWNAME_READ_NAMEHUFF
:
rv
=
hd_inflate_read_huff
(
inflater
,
&
inflater
->
namebuf
,
in
,
last
);
...
...
@@ -2452,6 +2353,7 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
}
*
inflater
->
namebuf
.
last
=
'\0'
;
inflater
->
namercbuf
->
len
=
nghttp2_buf_len
(
&
inflater
->
namebuf
);
inflater
->
state
=
NGHTTP2_HD_STATE_CHECK_VALUELEN
;
...
...
@@ -2473,6 +2375,7 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
}
*
inflater
->
namebuf
.
last
=
'\0'
;
inflater
->
namercbuf
->
len
=
nghttp2_buf_len
(
&
inflater
->
namebuf
);
inflater
->
state
=
NGHTTP2_HD_STATE_CHECK_VALUELEN
;
...
...
@@ -2505,18 +2408,21 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
inflater
->
state
=
NGHTTP2_HD_STATE_READ_VALUEHUFF
;
rv
=
nghttp2_
buf_reserve
(
&
inflater
->
value
buf
,
inflater
->
left
*
2
+
1
,
mem
);
rv
=
nghttp2_
rcbuf_new
(
&
inflater
->
valuerc
buf
,
inflater
->
left
*
2
+
1
,
mem
);
}
else
{
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
)
{
goto
fail
;
}
nghttp2_buf_wrap_init
(
&
inflater
->
valuebuf
,
inflater
->
valuercbuf
->
base
,
inflater
->
valuercbuf
->
len
);
busy
=
1
;
break
;
...
...
@@ -2538,11 +2444,12 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
}
*
inflater
->
valuebuf
.
last
=
'\0'
;
inflater
->
valuercbuf
->
len
=
nghttp2_buf_len
(
&
inflater
->
valuebuf
);
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
{
rv
=
hd_inflate_commit_indname
(
inflater
,
nv_out
,
token_out
);
rv
=
hd_inflate_commit_indname
(
inflater
,
nv_out
);
}
if
(
rv
!=
0
)
{
...
...
@@ -2572,11 +2479,12 @@ ssize_t nghttp2_hd_inflate_hd2(nghttp2_hd_inflater *inflater,
}
*
inflater
->
valuebuf
.
last
=
'\0'
;
inflater
->
valuercbuf
->
len
=
nghttp2_buf_len
(
&
inflater
->
valuebuf
);
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
{
rv
=
hd_inflate_commit_indname
(
inflater
,
nv_out
,
token_out
);
rv
=
hd_inflate_commit_indname
(
inflater
,
nv_out
);
}
if
(
rv
!=
0
)
{
...
...
@@ -2710,7 +2618,7 @@ static const nghttp2_nv *hd_get_table_entry(nghttp2_hd_context *context,
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
)
{
...
...
This diff is collapsed.
Click to expand it.
lib/nghttp2_hd.h
View file @
ff0d137f
...
...
@@ -34,6 +34,7 @@
#include "nghttp2_hd_huffman.h"
#include "nghttp2_buf.h"
#include "nghttp2_mem.h"
#include "nghttp2_rcbuf.h"
#define NGHTTP2_HD_DEFAULT_MAX_BUFFER_SIZE NGHTTP2_DEFAULT_HEADER_TABLE_SIZE
#define NGHTTP2_HD_ENTRY_OVERHEAD 32
...
...
@@ -168,25 +169,29 @@ typedef enum {
NGHTTP2_TOKEN_X_XSS_PROTECTION
,
}
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
;
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
{
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. */
nghttp2_hd_entry
*
next
;
/* The sequence number. We will increment it by one whenever we
...
...
@@ -194,14 +199,17 @@ struct nghttp2_hd_entry {
uint32_t
seq
;
/* The hash value for header name (nv.name). */
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
{
nghttp2_hd_entry
**
buffer
;
size_t
mask
;
...
...
@@ -275,17 +283,14 @@ struct nghttp2_hd_deflater {
struct
nghttp2_hd_inflater
{
nghttp2_hd_context
ctx
;
/* header buffer */
nghttp2_buf
namebuf
,
valuebuf
;
/* Stores current state of huffman decoding */
nghttp2_hd_huff_decode_context
huff_decode_ctx
;
/* Pointer to the nghttp2_hd_entry which is used current header
emission. This is required because in some cases the
ent_keep->ref == 0 and we have to keep track of it. */
nghttp2_hd_entry
*
ent_keep
;
/* Pointer to the name/value pair buffer which is used in the
current header emission. */
uint8_t
*
nv_name_keep
,
*
nv_value_keep
;
/* header buffer */
nghttp2_buf
namebuf
,
valuebuf
;
nghttp2_rcbuf
*
namercbuf
,
*
valuercbuf
;
/* Pointer to the name/value pair which are used in the current
header emission. */
nghttp2_rcbuf
*
nv_name_keep
,
*
nv_value_keep
;
/* The number of bytes to read */
size_t
left
;
/* The index in indexed repr or indexed name */
...
...
@@ -309,24 +314,16 @@ struct nghttp2_hd_inflater {
};
/*
* Initializes the |ent| members. If NGHTTP2_HD_FLAG_NAME_ALLOC bit
* set in the |flags|, the content pointed by the |name| with length
* |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.
* Initializes the |ent| members. The reference counts of nv->name
* and nv->value are increased by one for each.
*/
int
nghttp2_hd_entry_init
(
nghttp2_hd_entry
*
ent
,
uint8_t
flags
,
uint8_t
*
name
,
size_t
namelen
,
uint8_t
*
value
,
size_t
valuelen
,
int
token
,
nghttp2_mem
*
mem
);
void
nghttp2_hd_entry_init
(
nghttp2_hd_entry
*
ent
,
nghttp2_hd_nv
*
nv
);
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.
...
...
@@ -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
);
/*
* Similar to nghttp2_hd_inflate_hd(), but this takes additional
* output parameter |token|. On successful header emission, it
* contains nghttp2_token value for nv_out->name. It could be -1 if
* we don't have enum value for the name. Other than that return
* values and semantics are the same as nghttp2_hd_inflate_hd().
* Similar to nghttp2_hd_inflate_hd(), but this takes nghttp2_hd_nv
* instead of nghttp2_nv as output parameter |nv_out|. Other than
* that return values and semantics are the same as
* nghttp2_hd_inflate_hd().
*/
ssize_t
nghttp2_hd_inflate_hd2
(
nghttp2_hd_inflater
*
inflater
,
nghttp2_nv
*
nv_out
,
int
*
inflate_flags
,
int
*
token
,
uint8_t
*
in
,
size_t
inlen
,
int
in_final
);
nghttp2_hd_nv
*
nv_out
,
int
*
inflate_flags
,
uint8_t
*
in
,
size_t
inlen
,
int
in_final
);
/* For unittesting purpose */
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,
int
nghttp2_hd_emit_table_size
(
nghttp2_bufs
*
bufs
,
size_t
table_size
);
/* For unittesting purpose */
nghttp2_hd_entry
*
nghttp2_hd_table_get
(
nghttp2_hd_context
*
context
,
size_t
index
);
nghttp2_hd_nv
nghttp2_hd_table_get
(
nghttp2_hd_context
*
context
,
size_t
index
);
/* For unittesting purpose */
ssize_t
nghttp2_hd_decode_length
(
uint32_t
*
res
,
size_t
*
shift_ptr
,
int
*
final
,
...
...
This diff is collapsed.
Click to expand it.
lib/nghttp2_http.c
View file @
ff0d137f
...
...
@@ -82,12 +82,12 @@ static int lws(const uint8_t *s, size_t n) {
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
)
{
if
(
stream
->
http_flags
&
flag
)
{
return
0
;
}
if
(
lws
(
nv
->
value
,
nv
->
value
len
))
{
if
(
lws
(
nv
->
value
->
base
,
nv
->
value
->
len
))
{
return
0
;
}
stream
->
http_flags
=
(
uint16_t
)(
stream
->
http_flags
|
flag
);
...
...
@@ -112,16 +112,16 @@ static int check_path(nghttp2_stream *stream) {
(
stream
->
http_flags
&
NGHTTP2_HTTP_FLAG_PATH_ASTERISK
)));
}
static
int
http_request_on_header
(
nghttp2_stream
*
stream
,
nghttp2_nv
*
nv
,
int
t
oken
,
int
t
railer
)
{
if
(
nv
->
name
[
0
]
==
':'
)
{
static
int
http_request_on_header
(
nghttp2_stream
*
stream
,
nghttp2_
hd_
nv
*
nv
,
int
trailer
)
{
if
(
nv
->
name
->
base
[
0
]
==
':'
)
{
if
(
trailer
||
(
stream
->
http_flags
&
NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED
))
{
return
NGHTTP2_ERR_HTTP_HEADER
;
}
}
switch
(
token
)
{
switch
(
nv
->
token
)
{
case
NGHTTP2_TOKEN__AUTHORITY
:
if
(
!
check_pseudo_header
(
stream
,
nv
,
NGHTTP2_HTTP_FLAG__AUTHORITY
))
{
return
NGHTTP2_ERR_HTTP_HEADER
;
...
...
@@ -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
))
{
return
NGHTTP2_ERR_HTTP_HEADER
;
}
switch
(
nv
->
valuelen
)
{
switch
(
nv
->
value
->
len
)
{
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
;
}
break
;
case
7
:
switch
(
nv
->
value
[
6
])
{
switch
(
nv
->
value
->
base
[
6
])
{
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
)
{
/* we won't allow CONNECT for push */
return
NGHTTP2_ERR_HTTP_HEADER
;
...
...
@@ -153,7 +153,7 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
}
break
;
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
;
}
break
;
...
...
@@ -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
))
{
return
NGHTTP2_ERR_HTTP_HEADER
;
}
if
(
nv
->
value
[
0
]
==
'/'
)
{
if
(
nv
->
value
->
base
[
0
]
==
'/'
)
{
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
;
}
break
;
...
...
@@ -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
))
{
return
NGHTTP2_ERR_HTTP_HEADER
;
}
if
((
nv
->
value
len
==
4
&&
memieq
(
"http"
,
nv
->
valu
e
,
4
))
||
(
nv
->
value
len
==
5
&&
memieq
(
"https"
,
nv
->
valu
e
,
5
)))
{
if
((
nv
->
value
->
len
==
4
&&
memieq
(
"http"
,
nv
->
value
->
bas
e
,
4
))
||
(
nv
->
value
->
len
==
5
&&
memieq
(
"https"
,
nv
->
value
->
bas
e
,
5
)))
{
stream
->
http_flags
|=
NGHTTP2_HTTP_FLAG_SCHEME_HTTP
;
}
break
;
...
...
@@ -195,7 +195,7 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
if
(
stream
->
content_length
!=
-
1
)
{
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
)
{
return
NGHTTP2_ERR_HTTP_HEADER
;
}
...
...
@@ -209,41 +209,41 @@ static int http_request_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
case
NGHTTP2_TOKEN_UPGRADE
:
return
NGHTTP2_ERR_HTTP_HEADER
;
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
;
}
break
;
default:
if
(
nv
->
name
[
0
]
==
':'
)
{
if
(
nv
->
name
->
base
[
0
]
==
':'
)
{
return
NGHTTP2_ERR_HTTP_HEADER
;
}
}
if
(
nv
->
name
[
0
]
!=
':'
)
{
if
(
nv
->
name
->
base
[
0
]
!=
':'
)
{
stream
->
http_flags
|=
NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED
;
}
return
0
;
}
static
int
http_response_on_header
(
nghttp2_stream
*
stream
,
nghttp2_nv
*
nv
,
int
t
oken
,
int
t
railer
)
{
if
(
nv
->
name
[
0
]
==
':'
)
{
static
int
http_response_on_header
(
nghttp2_stream
*
stream
,
nghttp2_
hd_
nv
*
nv
,
int
trailer
)
{
if
(
nv
->
name
->
base
[
0
]
==
':'
)
{
if
(
trailer
||
(
stream
->
http_flags
&
NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED
))
{
return
NGHTTP2_ERR_HTTP_HEADER
;
}
}
switch
(
token
)
{
switch
(
nv
->
token
)
{
case
NGHTTP2_TOKEN__STATUS
:
{
if
(
!
check_pseudo_header
(
stream
,
nv
,
NGHTTP2_HTTP_FLAG__STATUS
))
{
return
NGHTTP2_ERR_HTTP_HEADER
;
}
if
(
nv
->
valuelen
!=
3
)
{
if
(
nv
->
value
->
len
!=
3
)
{
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
)
{
return
NGHTTP2_ERR_HTTP_HEADER
;
}
...
...
@@ -253,7 +253,7 @@ static int http_response_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
if
(
stream
->
content_length
!=
-
1
)
{
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
)
{
return
NGHTTP2_ERR_HTTP_HEADER
;
}
...
...
@@ -267,17 +267,17 @@ static int http_response_on_header(nghttp2_stream *stream, nghttp2_nv *nv,
case
NGHTTP2_TOKEN_UPGRADE
:
return
NGHTTP2_ERR_HTTP_HEADER
;
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
;
}
break
;
default:
if
(
nv
->
name
[
0
]
==
':'
)
{
if
(
nv
->
name
->
base
[
0
]
==
':'
)
{
return
NGHTTP2_ERR_HTTP_HEADER
;
}
}
if
(
nv
->
name
[
0
]
!=
':'
)
{
if
(
nv
->
name
->
base
[
0
]
!=
':'
)
{
stream
->
http_flags
|=
NGHTTP2_HTTP_FLAG_PSEUDO_HEADER_DISALLOWED
;
}
...
...
@@ -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
,
nghttp2_frame
*
frame
,
nghttp2_
nv
*
nv
,
int
token
,
nghttp2_frame
*
frame
,
nghttp2_
hd_nv
*
nv
,
int
trailer
)
{
int
rv
;
...
...
@@ -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
become conservative here, and just ignore those illegal regular
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
;
if
(
nv
->
name
len
>
0
&&
nv
->
nam
e
[
0
]
==
':'
)
{
if
(
nv
->
name
->
len
>
0
&&
nv
->
name
->
bas
e
[
0
]
==
':'
)
{
return
NGHTTP2_ERR_HTTP_HEADER
;
}
/* header field name must be lower-cased without exception */
for
(
i
=
0
;
i
<
nv
->
namelen
;
++
i
)
{
uint8_t
c
=
nv
->
name
[
i
];
for
(
i
=
0
;
i
<
nv
->
name
->
len
;
++
i
)
{
uint8_t
c
=
nv
->
name
->
base
[
i
];
if
(
'A'
<=
c
&&
c
<=
'Z'
)
{
return
NGHTTP2_ERR_HTTP_HEADER
;
}
...
...
@@ -405,17 +405,18 @@ int nghttp2_http_on_header(nghttp2_session *session, nghttp2_stream *stream,
return
NGHTTP2_ERR_IGN_HTTP_HEADER
;
}
if
(
token
==
NGHTTP2_TOKEN__AUTHORITY
||
token
==
NGHTTP2_TOKEN_HOST
)
{
rv
=
check_authority
(
nv
->
value
,
nv
->
valuelen
);
}
else
if
(
token
==
NGHTTP2_TOKEN__SCHEME
)
{
rv
=
check_scheme
(
nv
->
value
,
nv
->
valuelen
);
if
(
nv
->
token
==
NGHTTP2_TOKEN__AUTHORITY
||
nv
->
token
==
NGHTTP2_TOKEN_HOST
)
{
rv
=
check_authority
(
nv
->
value
->
base
,
nv
->
value
->
len
);
}
else
if
(
nv
->
token
==
NGHTTP2_TOKEN__SCHEME
)
{
rv
=
check_scheme
(
nv
->
value
->
base
,
nv
->
value
->
len
);
}
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
)
{
assert
(
nv
->
namelen
>
0
);
if
(
nv
->
name
[
0
]
==
':'
)
{
assert
(
nv
->
name
->
len
>
0
);
if
(
nv
->
name
->
base
[
0
]
==
':'
)
{
return
NGHTTP2_ERR_HTTP_HEADER
;
}
/* 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,
}
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
,
...
...
This diff is collapsed.
Click to expand it.
lib/nghttp2_http.h
View file @
ff0d137f
...
...
@@ -36,8 +36,7 @@
/*
* This function is called when HTTP header field |nv| in |frame| is
* received for |stream|. This function will validate |nv| against
* the current state of stream. The |token| is nghttp2_token value
* for nv->name, or -1 if we don't have enum value for the name.
* the current state of stream.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
...
...
@@ -49,7 +48,7 @@
* if it was not received because of compatibility reasons.
*/
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
);
/*
...
...
This diff is collapsed.
Click to expand it.
lib/nghttp2_mem.c
View file @
ff0d137f
...
...
@@ -52,6 +52,10 @@ void nghttp2_mem_free(nghttp2_mem *mem, void *ptr) {
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
)
{
return
mem
->
calloc
(
nmemb
,
size
,
mem
->
mem_user_data
);
}
...
...
This diff is collapsed.
Click to expand it.
lib/nghttp2_mem.h
View file @
ff0d137f
...
...
@@ -38,6 +38,7 @@ nghttp2_mem *nghttp2_mem_default(void);
|mem|. */
void
*
nghttp2_mem_malloc
(
nghttp2_mem
*
mem
,
size_t
size
);
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_realloc
(
nghttp2_mem
*
mem
,
void
*
ptr
,
size_t
size
);
...
...
This diff is collapsed.
Click to expand it.
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
};
}
This diff is collapsed.
Click to expand it.
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 */
This diff is collapsed.
Click to expand it.
lib/nghttp2_session.c
View file @
ff0d137f
...
...
@@ -3122,12 +3122,12 @@ static int session_call_on_begin_headers(nghttp2_session *session,
static
int
session_call_on_header
(
nghttp2_session
*
session
,
const
nghttp2_frame
*
frame
,
const
nghttp2_nv
*
nv
)
{
const
nghttp2_
hd_
nv
*
nv
)
{
int
rv
;
if
(
session
->
callbacks
.
on_header_callback
)
{
rv
=
session
->
callbacks
.
on_header_callback
(
session
,
frame
,
nv
->
name
,
nv
->
namelen
,
nv
->
value
,
nv
->
valuelen
,
nv
->
flags
,
session
->
user_data
);
session
,
frame
,
nv
->
name
->
base
,
nv
->
name
->
len
,
nv
->
value
->
base
,
nv
->
value
->
len
,
nv
->
flags
,
session
->
user_data
);
if
(
rv
==
NGHTTP2_ERR_PAUSE
||
rv
==
NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE
)
{
return
rv
;
...
...
@@ -3317,11 +3317,10 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame,
ssize_t
proclen
;
int
rv
;
int
inflate_flags
;
nghttp2_nv
nv
;
nghttp2_
hd_
nv
nv
;
nghttp2_stream
*
stream
;
nghttp2_stream
*
subject_stream
;
int
trailer
=
0
;
int
token
;
*
readlen_ptr
=
0
;
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,
for
(;;)
{
inflate_flags
=
0
;
proclen
=
nghttp2_hd_inflate_hd2
(
&
session
->
hd_inflater
,
&
nv
,
&
inflate_flags
,
&
token
,
in
,
inlen
,
final
);
in
,
inlen
,
final
);
if
(
nghttp2_is_fatal
((
int
)
proclen
))
{
return
(
int
)
proclen
;
}
...
...
@@ -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
))
{
rv
=
0
;
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
);
if
(
rv
==
NGHTTP2_ERR_HTTP_HEADER
)
{
DEBUGF
(
fprintf
(
stderr
,
"recv: HTTP error: type=%d, id=%d, header %.*s: %.*s
\n
"
,
frame
->
hd
.
type
,
subject_stream
->
stream_id
,
(
int
)
nv
.
namelen
,
nv
.
name
,
(
int
)
nv
.
valuelen
,
nv
.
valu
e
));
frame
->
hd
.
type
,
subject_stream
->
stream_id
,
(
int
)
nv
.
name
->
len
,
nv
.
name
->
base
,
(
int
)
nv
.
value
->
len
,
nv
.
value
->
bas
e
));
rv
=
session_handle_invalid_stream2
(
session
,
subject_stream
->
stream_id
,
...
...
@@ -3394,8 +3393,8 @@ static int inflate_header_block(nghttp2_session *session, nghttp2_frame *frame,
/* header is ignored */
DEBUGF
(
fprintf
(
stderr
,
"recv: HTTP ignored: type=%d, id=%d, header %.*s: %.*s
\n
"
,
frame
->
hd
.
type
,
subject_stream
->
stream_id
,
(
int
)
nv
.
namelen
,
nv
.
name
,
(
int
)
nv
.
valuelen
,
nv
.
valu
e
));
frame
->
hd
.
type
,
subject_stream
->
stream_id
,
(
int
)
nv
.
name
->
len
,
nv
.
name
->
base
,
(
int
)
nv
.
value
->
len
,
nv
.
value
->
bas
e
));
}
}
if
(
rv
==
0
)
{
...
...
This diff is collapsed.
Click to expand it.
tests/nghttp2_hd_test.c
View file @
ff0d137f
...
...
@@ -295,11 +295,6 @@ void test_nghttp2_hd_inflate_indname_inc(void) {
assert_nv_equal
(
&
nv
,
out
.
nva
,
1
,
mem
);
CU_ASSERT
(
1
==
inflater
.
ctx
.
hd_table
.
len
);
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
(
&
inflater
,
NGHTTP2_STATIC_TABLE_LENGTH
+
inflater
.
ctx
.
hd_table
.
len
),
...
...
@@ -429,10 +424,9 @@ void test_nghttp2_hd_inflate_newname_inc(void) {
CU_ASSERT
(
1
==
out
.
nvlen
);
assert_nv_equal
(
&
nv
,
out
.
nva
,
1
,
mem
);
CU_ASSERT
(
1
==
inflater
.
ctx
.
hd_table
.
len
);
assert_nv_equal
(
&
nv
,
&
nghttp2_hd_table_get
(
&
inflater
.
ctx
,
NGHTTP2_STATIC_TABLE_LENGTH
+
inflater
.
ctx
.
hd_table
.
len
-
1
)
->
nv
,
assert_nv_equal
(
&
nv
,
nghttp2_hd_inflate_get_table_entry
(
&
inflater
,
NGHTTP2_STATIC_TABLE_LENGTH
+
inflater
.
ctx
.
hd_table
.
len
),
1
,
mem
);
nva_out_reset
(
&
out
,
mem
);
...
...
This diff is collapsed.
Click to expand it.
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