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
1db21953
Commit
1db21953
authored
Feb 09, 2014
by
Tatsuhiro Tsujikawa
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement padding for HEADERS and CONTINUATION
parent
10feab02
Changes
14
Show whitespace changes
Inline
Side-by-side
Showing
14 changed files
with
452 additions
and
198 deletions
+452
-198
lib/includes/nghttp2/nghttp2.h
lib/includes/nghttp2/nghttp2.h
+21
-10
lib/nghttp2_frame.c
lib/nghttp2_frame.c
+48
-33
lib/nghttp2_frame.h
lib/nghttp2_frame.h
+16
-6
lib/nghttp2_session.c
lib/nghttp2_session.c
+246
-83
lib/nghttp2_session.h
lib/nghttp2_session.h
+7
-6
src/HttpServer.cc
src/HttpServer.cc
+3
-3
src/HttpServer.h
src/HttpServer.h
+1
-1
src/app_helper.cc
src/app_helper.cc
+30
-6
src/nghttp.cc
src/nghttp.cc
+7
-7
src/nghttpd.cc
src/nghttpd.cc
+3
-3
tests/nghttp2_frame_test.c
tests/nghttp2_frame_test.c
+19
-9
tests/nghttp2_session_test.c
tests/nghttp2_session_test.c
+43
-31
tests/nghttp2_test_helper.c
tests/nghttp2_test_helper.c
+5
-0
tests/nghttp2_test_helper.h
tests/nghttp2_test_helper.h
+3
-0
No files found.
lib/includes/nghttp2/nghttp2.h
View file @
1db21953
...
...
@@ -151,9 +151,9 @@ typedef struct {
* @macro
*
* The default value of DATA padding alignment. See
* :member:`NGHTTP2_OPT_
DATA_
PAD_ALIGNMENT`.
* :member:`NGHTTP2_OPT_PAD_ALIGNMENT`.
*/
#define NGHTTP2_
DATA_
PAD_ALIGNMENT 256
#define NGHTTP2_PAD_ALIGNMENT 256
/**
* @enum
...
...
@@ -655,6 +655,11 @@ typedef struct {
* The frame header.
*/
nghttp2_frame_hd
hd
;
/**
* The length of the padding in this frame. This includes PAD_HIGH
* and PAD_LOW.
*/
size_t
padlen
;
/**
* The name/value pairs.
*/
...
...
@@ -746,6 +751,11 @@ typedef struct {
* The frame header.
*/
nghttp2_frame_hd
hd
;
/**
* The length of the padding in this frame. This includes PAD_HIGH
* and PAD_LOW.
*/
size_t
padlen
;
/**
* The name/value pairs.
*/
...
...
@@ -1324,13 +1334,14 @@ typedef enum {
*/
NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS
=
1
<<
2
,
/**
* This option specifies the alignment of padding in DATA frame. If
* this option is set to N, padding is added to DATA payload so that
* its payload length is divisible by N. Due to flow control,
* padding is not always added according to this alignment. The
* option value must be greater than or equal to 8.
* This option specifies the alignment of padding in frame
* payload. If this option is set to N, padding is added to frame
* payload so that its payload length is divisible by N. For DATA
* frame, due to flow control, padding is not always added according
* to this alignment. The option value must be greater than or equal
* to 8.
*/
NGHTTP2_OPT_
DATA_
PAD_ALIGNMENT
=
1
<<
3
NGHTTP2_OPT_PAD_ALIGNMENT
=
1
<<
3
}
nghttp2_opt
;
/**
...
...
@@ -1352,9 +1363,9 @@ typedef struct {
*/
uint8_t
no_auto_connection_window_update
;
/**
* :enum:`NGHTTP2_OPT_
DATA_
PAD_ALIGNMENT`
* :enum:`NGHTTP2_OPT_PAD_ALIGNMENT`
*/
uint16_t
data_
pad_alignment
;
uint16_t
pad_alignment
;
}
nghttp2_opt_set
;
/**
...
...
lib/nghttp2_frame.c
View file @
1db21953
...
...
@@ -193,9 +193,9 @@ void nghttp2_frame_data_init(nghttp2_data *frame, nghttp2_private_data *pdata)
}
}
size_t
nghttp2_frame_
data_trail_padlen
(
nghttp2_data
*
frame
)
size_t
nghttp2_frame_
trail_padlen
(
nghttp2_frame
*
frame
,
size_t
padlen
)
{
return
frame
->
padlen
return
padlen
-
((
frame
->
hd
.
flags
&
NGHTTP2_FLAG_PAD_HIGH
)
>
0
)
-
((
frame
->
hd
.
flags
&
NGHTTP2_FLAG_PAD_LOW
)
>
0
);
}
...
...
@@ -214,19 +214,6 @@ void nghttp2_frame_private_data_init(nghttp2_private_data *frame,
void
nghttp2_frame_private_data_free
(
nghttp2_private_data
*
frame
)
{}
/*
* Returns the offset of the name/header block in the HEADERS frame,
* including frame header length.
*/
static
size_t
headers_nv_offset
(
nghttp2_headers
*
frame
)
{
if
(
frame
->
hd
.
flags
&
NGHTTP2_FLAG_PRIORITY
)
{
return
NGHTTP2_FRAME_HEAD_LENGTH
+
4
;
}
else
{
return
NGHTTP2_FRAME_HEAD_LENGTH
;
}
}
size_t
nghttp2_frame_headers_payload_nv_offset
(
nghttp2_headers
*
frame
)
{
if
(
frame
->
hd
.
flags
&
NGHTTP2_FLAG_PRIORITY
)
{
...
...
@@ -238,23 +225,41 @@ size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame)
ssize_t
nghttp2_frame_pack_headers
(
uint8_t
**
buf_ptr
,
size_t
*
buflen_ptr
,
size_t
*
bufoff_ptr
,
nghttp2_headers
*
frame
,
nghttp2_hd_deflater
*
deflater
)
nghttp2_hd_deflater
*
deflater
,
size_t
align
)
{
ssize_t
framelen
;
size_t
nv_offset
=
headers_nv_offset
(
frame
);
size_t
payloadoff
=
NGHTTP2_FRAME_HEAD_LENGTH
+
2
;
size_t
nv_offset
=
payloadoff
+
nghttp2_frame_headers_payload_nv_offset
(
frame
);
ssize_t
rv
;
size_t
payloadlen
;
rv
=
nghttp2_hd_deflate_hd
(
deflater
,
buf_ptr
,
buflen_ptr
,
nv_offset
,
frame
->
nva
,
frame
->
nvlen
);
if
(
rv
<
0
)
{
return
rv
;
}
framelen
=
rv
+
nv_offset
;
if
(
NGHTTP2_FRAME_HEAD_LENGTH
+
NGHTTP2_MAX_FRAME_LENGTH
<
rv
+
nv_offset
)
{
frame
->
hd
.
length
=
NGHTTP2_MAX_FRAME_LENGTH
;
frame
->
hd
.
flags
&=
~
NGHTTP2_FLAG_END_HEADERS
;
payloadlen
=
nghttp2_frame_headers_payload_nv_offset
(
frame
)
+
rv
;
if
(
align
>
0
)
{
ssize_t
padlen
;
padlen
=
nghttp2_frame_add_pad
(
buf_ptr
,
buflen_ptr
,
bufoff_ptr
,
&
frame
->
hd
.
flags
,
payloadlen
,
payloadlen
+
align
,
align
);
if
(
padlen
<
0
)
{
return
padlen
;
}
frame
->
padlen
=
padlen
;
frame
->
hd
.
length
=
payloadlen
+
padlen
;
}
else
{
frame
->
hd
.
length
=
framelen
-
NGHTTP2_FRAME_HEAD_LENGTH
;
*
bufoff_ptr
=
2
;
frame
->
padlen
=
0
;
frame
->
hd
.
length
=
payloadlen
;
}
/* If frame->nvlen == 0, *buflen_ptr may be smaller than
nv_offset */
...
...
@@ -262,13 +267,21 @@ ssize_t nghttp2_frame_pack_headers(uint8_t **buf_ptr,
if
(
rv
<
0
)
{
return
rv
;
}
memset
(
*
buf_ptr
,
0
,
nv_offset
);
memset
(
*
buf_ptr
+
*
bufoff_ptr
,
0
,
NGHTTP2_FRAME_HEAD_LENGTH
);
/* pack ctrl header after length is determined */
nghttp2_frame_pack_frame_hd
(
*
buf_ptr
,
&
frame
->
hd
);
if
(
NGHTTP2_FRAME_HEAD_LENGTH
+
NGHTTP2_MAX_FRAME_LENGTH
<
rv
+
nv_offset
)
{
/* Needs CONTINUATION */
nghttp2_frame_hd
hd
=
frame
->
hd
;
hd
.
flags
&=
~
(
NGHTTP2_FLAG_END_HEADERS
|
NGHTTP2_FLAG_PAD_HIGH
|
NGHTTP2_FLAG_PAD_LOW
);
nghttp2_frame_pack_frame_hd
(
*
buf_ptr
+
*
bufoff_ptr
,
&
hd
);
}
else
{
nghttp2_frame_pack_frame_hd
(
*
buf_ptr
+
*
bufoff_ptr
,
&
frame
->
hd
);
}
if
(
frame
->
hd
.
flags
&
NGHTTP2_FLAG_PRIORITY
)
{
nghttp2_put_uint32be
(
&
(
*
buf_ptr
)[
8
],
frame
->
pri
);
nghttp2_put_uint32be
(
&
(
*
buf_ptr
)[
payloadoff
],
frame
->
pri
);
}
return
frame
len
;
return
frame
->
hd
.
length
+
NGHTTP2_FRAME_HEAD_LENGTH
+
*
bufoff_ptr
;
}
int
nghttp2_frame_unpack_headers_payload
(
nghttp2_headers
*
frame
,
...
...
@@ -276,7 +289,6 @@ int nghttp2_frame_unpack_headers_payload(nghttp2_headers *frame,
size_t
payloadlen
)
{
if
(
frame
->
hd
.
flags
&
NGHTTP2_FLAG_PRIORITY
)
{
assert
(
payloadlen
==
4
);
frame
->
pri
=
nghttp2_get_uint32
(
payload
)
&
NGHTTP2_PRIORITY_MASK
;
}
else
{
frame
->
pri
=
NGHTTP2_PRI_DEFAULT
;
...
...
@@ -660,19 +672,23 @@ ssize_t nghttp2_frame_add_pad(uint8_t **buf_ptr, size_t *buflen_ptr,
payloadmax
);
size_t
padlen
=
nextlen
-
payloadlen
;
size_t
trail_padlen
=
0
;
size_t
headoff
=
2
;
size_t
trail_padoff
=
headoff
+
NGHTTP2_FRAME_HEAD_LENGTH
+
payloadlen
;
/* extra 2 bytes for PAD_HIGH and PAD_LOW. */
size_t
trail_padoff
=
2
+
NGHTTP2_FRAME_HEAD_LENGTH
+
payloadlen
;
if
(
padlen
>
257
)
{
headoff
=
0
;
*
bufoff_ptr
=
0
;
trail_padlen
=
padlen
-
2
;
*
flags_ptr
|=
NGHTTP2_FLAG_PAD_HIGH
|
NGHTTP2_FLAG_PAD_LOW
;
(
*
buf_ptr
)[
NGHTTP2_FRAME_HEAD_LENGTH
]
=
trail_padlen
>>
8
;
(
*
buf_ptr
)[
NGHTTP2_FRAME_HEAD_LENGTH
+
1
]
=
trail_padlen
&
0xff
;
}
else
if
(
padlen
>
0
)
{
headoff
=
1
;
*
bufoff_ptr
=
1
;
trail_padlen
=
padlen
-
1
;
*
flags_ptr
|=
NGHTTP2_FLAG_PAD_LOW
;
(
*
buf_ptr
)[
NGHTTP2_FRAME_HEAD_LENGTH
+
1
]
=
trail_padlen
;
}
else
{
*
bufoff_ptr
=
2
;
return
0
;
}
rv
=
nghttp2_reserve_buffer
(
buf_ptr
,
buflen_ptr
,
...
...
@@ -682,7 +698,6 @@ ssize_t nghttp2_frame_add_pad(uint8_t **buf_ptr, size_t *buflen_ptr,
}
memset
((
*
buf_ptr
)
+
trail_padoff
,
0
,
trail_padlen
);
*
bufoff_ptr
=
headoff
;
return
padlen
;
}
lib/nghttp2_frame.h
View file @
1db21953
...
...
@@ -104,14 +104,21 @@ size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame);
* expansion occurred, memory previously pointed by |*buf_ptr| may
* change. |*buf_ptr| and |*buflen_ptr| are updated accordingly.
*
* The first byte the frame is serialized is returned in the
* |*bufoff_ptr|.
*
* The |align| is used as padding alignment. If the |align| is zero,
* no padding is added.
*
* frame->hd.length is assigned after length is determined during
* packing process. If payload length is strictly larger than
* NGHTTP2_MAX_FRAME_LENGTH, payload data is still serialized as is,
* but frame->hd.length is set to NGHTTP2_MAX_FRAME_LENGTH and
* NGHTTP2_FLAG_END_HEADERS flag is cleared from frame->hd.flags.
*
* This function returns the size of packed frame if it succeeds, or
* returns one of the following negative error codes:
* This function returns the size of packed frame (which includes
* |*bufoff_ptr| bytes) if it succeeds, or returns one of the
* following negative error codes:
*
* NGHTTP2_ERR_HEADER_COMP
* The deflate operation failed.
...
...
@@ -122,8 +129,10 @@ size_t nghttp2_frame_headers_payload_nv_offset(nghttp2_headers *frame);
*/
ssize_t
nghttp2_frame_pack_headers
(
uint8_t
**
buf_ptr
,
size_t
*
buflen_ptr
,
size_t
*
bufoff_ptr
,
nghttp2_headers
*
frame
,
nghttp2_hd_deflater
*
deflater
);
nghttp2_hd_deflater
*
deflater
,
size_t
align
);
/*
* Unpacks HEADERS frame byte sequence into |frame|. This function
...
...
@@ -427,10 +436,11 @@ void nghttp2_frame_window_update_free(nghttp2_window_update *frame);
void
nghttp2_frame_data_init
(
nghttp2_data
*
frame
,
nghttp2_private_data
*
pdata
);
/*
* Returns the number of padding data after application data
* payload. Thus this does not include the PAD_HIGH and PAD_LOW.
* Returns the number of padding bytes after payload. The total
* padding length is given in the |padlen|. The returned value does
* not include the PAD_HIGH and PAD_LOW.
*/
size_t
nghttp2_frame_
data_trail_padlen
(
nghttp2_data
*
frame
);
size_t
nghttp2_frame_
trail_padlen
(
nghttp2_frame
*
frame
,
size_t
padlen
);
void
nghttp2_frame_private_data_init
(
nghttp2_private_data
*
frame
,
uint8_t
flags
,
...
...
lib/nghttp2_session.c
View file @
1db21953
...
...
@@ -173,6 +173,7 @@ static void nghttp2_inbound_frame_reset(nghttp2_session *session)
iframe
->
left
=
NGHTTP2_FRAME_HEAD_LENGTH
;
iframe
->
niv
=
0
;
iframe
->
payloadleft
=
0
;
iframe
->
padlen
=
0
;
iframe
->
error_code
=
0
;
iframe
->
buflen
=
0
;
}
...
...
@@ -223,11 +224,11 @@ static int nghttp2_session_new(nghttp2_session **session_ptr,
(
*
session_ptr
)
->
opt_flags
|=
NGHTTP2_OPTMASK_NO_AUTO_CONNECTION_WINDOW_UPDATE
;
}
if
((
opt_set_mask
&
NGHTTP2_OPT_
DATA_
PAD_ALIGNMENT
)
&&
opt_set
->
data_
pad_alignment
>=
8
)
{
(
*
session_ptr
)
->
data_pad_alignment
=
opt_set
->
data_
pad_alignment
;
if
((
opt_set_mask
&
NGHTTP2_OPT_PAD_ALIGNMENT
)
&&
opt_set
->
pad_alignment
>=
8
)
{
(
*
session_ptr
)
->
pad_alignment
=
opt_set
->
pad_alignment
;
}
else
{
(
*
session_ptr
)
->
data_pad_alignment
=
NGHTTP2_DATA
_PAD_ALIGNMENT
;
(
*
session_ptr
)
->
pad_alignment
=
NGHTTP2
_PAD_ALIGNMENT
;
}
(
*
session_ptr
)
->
remote_window_size
=
NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE
;
...
...
@@ -1119,8 +1120,10 @@ static ssize_t nghttp2_session_prep_frame(nghttp2_session *session,
}
framebuflen
=
nghttp2_frame_pack_headers
(
&
session
->
aob
.
framebuf
,
&
session
->
aob
.
framebufmax
,
&
session
->
aob
.
framebufoff
,
&
frame
->
headers
,
&
session
->
hd_deflater
);
&
session
->
hd_deflater
,
session
->
pad_alignment
);
if
(
framebuflen
<
0
)
{
return
framebuflen
;
}
...
...
@@ -1442,8 +1445,11 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session)
session
->
aob
.
framebufmark
,
NGHTTP2_MAX_FRAME_LENGTH
);
cont_hd
.
type
=
NGHTTP2_CONTINUATION
;
if
(
cont_hd
.
length
<
NGHTTP2_MAX_FRAME_LENGTH
)
{
if
(
cont_hd
.
length
+
session
->
aob
.
framebufmark
==
session
->
aob
.
framebuflen
)
{
cont_hd
.
flags
=
NGHTTP2_FLAG_END_HEADERS
;
cont_hd
.
flags
|=
(
NGHTTP2_FLAG_PAD_HIGH
|
NGHTTP2_FLAG_PAD_LOW
)
&
frame
->
hd
.
flags
;
}
else
{
cont_hd
.
flags
=
NGHTTP2_FLAG_NONE
;
}
...
...
@@ -1456,9 +1462,6 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session)
session
->
aob
.
framebufoff
-=
NGHTTP2_FRAME_HEAD_LENGTH
;
return
0
;
}
/* Update frame payload length to include data sent in
CONTINUATION frame. */
frame
->
hd
.
length
=
session
->
aob
.
framebuflen
-
NGHTTP2_FRAME_HEAD_LENGTH
;
}
rv
=
session_call_on_frame_send
(
session
,
frame
);
if
(
nghttp2_is_fatal
(
rv
))
{
...
...
@@ -3318,24 +3321,73 @@ static int inbound_frame_set_settings_entry(nghttp2_inbound_frame *iframe)
* accordingly. If padding is set, this function returns 1. If no
* padding is set, this function returns 0. On error, returns -1.
*/
static
int
inbound_frame_handle_pad
(
nghttp2_inbound_frame
*
iframe
)
static
int
inbound_frame_handle_pad
(
nghttp2_inbound_frame
*
iframe
,
nghttp2_frame_hd
*
hd
)
{
if
(
iframe
->
frame
.
hd
.
flags
&
NGHTTP2_FLAG_PAD_HIGH
)
{
if
((
iframe
->
frame
.
hd
.
flags
&
NGHTTP2_FLAG_PAD_LOW
)
==
0
)
{
if
(
hd
->
flags
&
NGHTTP2_FLAG_PAD_HIGH
)
{
if
((
hd
->
flags
&
NGHTTP2_FLAG_PAD_LOW
)
==
0
)
{
return
-
1
;
}
iframe
->
state
=
NGHTTP2_IB_READ_NBYTE
;
iframe
->
left
=
2
;
return
1
;
}
if
(
iframe
->
frame
.
hd
.
flags
&
NGHTTP2_FLAG_PAD_LOW
)
{
if
(
hd
->
flags
&
NGHTTP2_FLAG_PAD_LOW
)
{
iframe
->
state
=
NGHTTP2_IB_READ_NBYTE
;
iframe
->
left
=
1
;
return
1
;
}
DEBUGF
(
fprintf
(
stderr
,
"no padding
\n
"
));
return
0
;
}
/*
* Computes number of padding based on flags. This function returns
* the calculated length if it succeeds, or -1.
*/
static
ssize_t
inbound_frame_compute_pad
(
nghttp2_inbound_frame
*
iframe
)
{
size_t
padlen
;
padlen
=
iframe
->
buf
[
0
];
if
(
iframe
->
frame
.
hd
.
flags
&
NGHTTP2_FLAG_PAD_HIGH
)
{
padlen
<<=
8
;
padlen
|=
iframe
->
buf
[
1
];
++
padlen
;
}
++
padlen
;
DEBUGF
(
fprintf
(
stderr
,
"padlen=%zu
\n
"
,
padlen
));
if
(
padlen
>
iframe
->
frame
.
hd
.
length
)
{
return
-
1
;
}
iframe
->
padlen
=
padlen
;
return
padlen
;
}
/*
* This function returns the effective payload length in the data of
* length |readlen| when the remaning payload is |payloadleft|. The
* |payloadleft| does not include |readlen|. If padding was started
* strictly before this data chunk, this function returns -1.
*/
static
ssize_t
inbound_frame_effective_readlen
(
nghttp2_inbound_frame
*
iframe
,
size_t
payloadleft
,
size_t
readlen
)
{
size_t
trail_padlen
=
nghttp2_frame_trail_padlen
(
&
iframe
->
frame
,
iframe
->
padlen
);
if
(
trail_padlen
>
payloadleft
)
{
size_t
padlen
;
padlen
=
trail_padlen
-
payloadleft
;
if
(
readlen
<
padlen
)
{
return
-
1
;
}
else
{
return
readlen
-
padlen
;
}
}
return
readlen
;
}
ssize_t
nghttp2_session_mem_recv
(
nghttp2_session
*
session
,
const
uint8_t
*
in
,
size_t
inlen
)
{
...
...
@@ -3363,7 +3415,6 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
switch
(
iframe
->
frame
.
hd
.
type
)
{
case
NGHTTP2_DATA
:
{
DEBUGF
(
fprintf
(
stderr
,
"DATA
\n
"
));
iframe
->
frame
.
data
.
padlen
=
0
;
/* Check stream is open. If it is not open or closing,
ignore payload. */
busy
=
1
;
...
...
@@ -3377,7 +3428,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
if
(
nghttp2_is_fatal
(
rv
))
{
return
rv
;
}
rv
=
inbound_frame_handle_pad
(
iframe
);
rv
=
inbound_frame_handle_pad
(
iframe
,
&
iframe
->
frame
.
hd
);
if
(
rv
<
0
)
{
iframe
->
state
=
NGHTTP2_IB_IGN_DATA
;
rv
=
nghttp2_session_terminate_session
(
session
,
...
...
@@ -3395,6 +3446,20 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
}
case
NGHTTP2_HEADERS
:
DEBUGF
(
fprintf
(
stderr
,
"HEADERS
\n
"
));
rv
=
inbound_frame_handle_pad
(
iframe
,
&
iframe
->
frame
.
hd
);
if
(
rv
<
0
)
{
busy
=
1
;
iframe
->
state
=
NGHTTP2_IB_IGN_PAYLOAD
;
rv
=
nghttp2_session_terminate_session
(
session
,
NGHTTP2_PROTOCOL_ERROR
);
if
(
nghttp2_is_fatal
(
rv
))
{
return
rv
;
}
break
;
}
if
(
rv
==
1
)
{
break
;
}
if
(
iframe
->
frame
.
hd
.
flags
&
NGHTTP2_FLAG_PRIORITY
)
{
if
(
iframe
->
payloadleft
<
4
)
{
busy
=
1
;
...
...
@@ -3497,16 +3562,8 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
switch
(
iframe
->
frame
.
hd
.
type
)
{
case
NGHTTP2_DATA
:
busy
=
1
;
iframe
->
frame
.
data
.
padlen
=
iframe
->
buf
[
0
];
if
(
iframe
->
frame
.
hd
.
flags
&
NGHTTP2_FLAG_PAD_HIGH
)
{
iframe
->
frame
.
data
.
padlen
<<=
8
;
iframe
->
frame
.
data
.
padlen
|=
iframe
->
buf
[
1
];
++
iframe
->
frame
.
data
.
padlen
;
}
++
iframe
->
frame
.
data
.
padlen
;
DEBUGF
(
fprintf
(
stderr
,
"padlen=%zu
\n
"
,
iframe
->
frame
.
data
.
padlen
));
if
(
iframe
->
frame
.
data
.
padlen
>
iframe
->
frame
.
hd
.
length
)
{
rv
=
inbound_frame_compute_pad
(
iframe
);
if
(
rv
<
0
)
{
rv
=
nghttp2_session_terminate_session
(
session
,
NGHTTP2_PROTOCOL_ERROR
);
if
(
nghttp2_is_fatal
(
rv
))
{
...
...
@@ -3515,9 +3572,36 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
iframe
->
state
=
NGHTTP2_IB_IGN_DATA
;
break
;
}
iframe
->
frame
.
data
.
padlen
=
rv
;
iframe
->
state
=
NGHTTP2_IB_READ_DATA
;
break
;
case
NGHTTP2_HEADERS
:
if
(
iframe
->
padlen
==
0
&&
iframe
->
frame
.
hd
.
flags
&
NGHTTP2_FLAG_PAD_LOW
)
{
rv
=
inbound_frame_compute_pad
(
iframe
);
if
(
rv
<
0
)
{
busy
=
1
;
rv
=
nghttp2_session_terminate_session
(
session
,
NGHTTP2_PROTOCOL_ERROR
);
if
(
nghttp2_is_fatal
(
rv
))
{
return
rv
;
}
iframe
->
state
=
NGHTTP2_IB_IGN_PAYLOAD
;
break
;
}
iframe
->
frame
.
headers
.
padlen
=
rv
;
if
(
iframe
->
frame
.
hd
.
flags
&
NGHTTP2_FLAG_PRIORITY
)
{
if
(
iframe
->
payloadleft
<
4
)
{
busy
=
1
;
iframe
->
state
=
NGHTTP2_IB_FRAME_SIZE_ERROR
;
break
;
}
iframe
->
state
=
NGHTTP2_IB_READ_NBYTE
;
iframe
->
left
=
4
;
iframe
->
buflen
=
0
;
break
;
}
}
rv
=
session_process_headers_frame
(
session
);
if
(
nghttp2_is_fatal
(
rv
))
{
return
rv
;
...
...
@@ -3580,7 +3664,8 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
}
break
;
case
NGHTTP2_IB_READ_HEADER_BLOCK
:
case
NGHTTP2_IB_IGN_HEADER_BLOCK
:
case
NGHTTP2_IB_IGN_HEADER_BLOCK
:
{
ssize_t
data_readlen
;
#ifdef DEBUGBUILD
if
(
iframe
->
state
==
NGHTTP2_IB_READ_HEADER_BLOCK
)
{
fprintf
(
stderr
,
"[IB_READ_HEADER_BLOCK]
\n
"
);
...
...
@@ -3591,24 +3676,41 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
readlen
=
inbound_frame_payload_readlen
(
iframe
,
in
,
last
);
DEBUGF
(
fprintf
(
stderr
,
"readlen=%zu, payloadleft=%zu
\n
"
,
readlen
,
iframe
->
payloadleft
-
readlen
));
data_readlen
=
inbound_frame_effective_readlen
(
iframe
,
iframe
->
payloadleft
-
readlen
,
readlen
);
if
(
data_readlen
>=
0
)
{
size_t
trail_padlen
;
size_t
hd_proclen
=
0
;
trail_padlen
=
nghttp2_frame_trail_padlen
(
&
iframe
->
frame
,
iframe
->
padlen
);
DEBUGF
(
fprintf
(
stderr
,
"block final=%d
\n
"
,
(
iframe
->
frame
.
hd
.
flags
&
NGHTTP2_FLAG_END_HEADERS
)
&&
iframe
->
payloadleft
==
readlen
));
rv
=
inflate_header_block
(
session
,
&
iframe
->
frame
,
&
readlen
,
(
uint8_t
*
)
in
,
readlen
,
iframe
->
payloadleft
-
data_readlen
==
trail_padlen
));
rv
=
inflate_header_block
(
session
,
&
iframe
->
frame
,
&
hd_proclen
,
(
uint8_t
*
)
in
,
data_readlen
,
(
iframe
->
frame
.
hd
.
flags
&
NGHTTP2_FLAG_END_HEADERS
)
&&
iframe
->
payloadleft
==
re
adlen
,
iframe
->
payloadleft
-
data_readlen
==
trail_p
adlen
,
iframe
->
state
==
NGHTTP2_IB_READ_HEADER_BLOCK
);
if
(
nghttp2_is_fatal
(
rv
))
{
return
rv
;
}
in
+=
readlen
;
iframe
->
payloadleft
-=
readlen
;
if
(
rv
==
NGHTTP2_ERR_PAUSE
)
{
in
+=
hd_proclen
;
iframe
->
payloadleft
-=
hd_proclen
;
return
in
-
first
;
}
in
+=
readlen
;
iframe
->
payloadleft
-=
readlen
;
if
(
rv
==
NGHTTP2_ERR_TEMPORAL_CALLBACK_FAILURE
)
{
/* The application says no more headers. We decompress the
rest of the header block but not invoke on_header_callback
...
...
@@ -3619,6 +3721,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
if
(
nghttp2_is_fatal
(
rv
))
{
return
rv
;
}
busy
=
1
;
iframe
->
state
=
NGHTTP2_IB_IGN_HEADER_BLOCK
;
break
;
}
...
...
@@ -3627,32 +3730,40 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
if
(
iframe
->
payloadleft
==
0
)
{
nghttp2_inbound_frame_reset
(
session
);
}
else
{
busy
=
1
;
iframe
->
state
=
NGHTTP2_IB_IGN_PAYLOAD
;
}
break
;
}
}
else
{
in
+=
readlen
;
iframe
->
payloadleft
-=
readlen
;
}
if
(
iframe
->
payloadleft
)
{
break
;
}
if
(
iframe
->
state
==
NGHTTP2_IB_READ_HEADER_BLOCK
)
{
rv
=
session_after_header_block_received
(
session
);
if
(
nghttp2_is_fatal
(
rv
))
{
return
rv
;
}
}
if
((
iframe
->
frame
.
hd
.
flags
&
NGHTTP2_FLAG_END_HEADERS
)
==
0
)
{
iframe
->
left
=
NGHTTP2_FRAME_HEAD_LENGTH
;
iframe
->
error_code
=
0
;
iframe
->
buflen
=
0
;
iframe
->
padlen
=
0
;
if
(
iframe
->
state
==
NGHTTP2_IB_READ_HEADER_BLOCK
)
{
iframe
->
state
=
NGHTTP2_IB_EXPECT_CONTINUATION
;
}
else
{
iframe
->
state
=
NGHTTP2_IB_IGN_CONTINUATION
;
}
}
else
{
if
(
iframe
->
state
==
NGHTTP2_IB_READ_HEADER_BLOCK
)
{
rv
=
session_after_header_block_received
(
session
);
if
(
nghttp2_is_fatal
(
rv
))
{
return
rv
;
}
}
nghttp2_inbound_frame_reset
(
session
);
}
break
;
}
case
NGHTTP2_IB_IGN_PAYLOAD
:
DEBUGF
(
fprintf
(
stderr
,
"[IB_IGN_PAYLOAD]
\n
"
));
readlen
=
inbound_frame_payload_readlen
(
iframe
,
in
,
last
);
...
...
@@ -3761,9 +3872,30 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
iframe
->
state
=
NGHTTP2_IB_IGN_PAYLOAD
;
break
;
}
if
(
cont_hd
.
flags
&
NGHTTP2_FLAG_END_HEADERS
)
{
iframe
->
frame
.
hd
.
flags
|=
NGHTTP2_FLAG_END_HEADERS
;
iframe
->
frame
.
hd
.
flags
|=
cont_hd
.
flags
&
(
NGHTTP2_FLAG_END_HEADERS
|
NGHTTP2_FLAG_PAD_HIGH
|
NGHTTP2_FLAG_PAD_LOW
);
rv
=
inbound_frame_handle_pad
(
iframe
,
&
cont_hd
);
if
(
rv
<
0
)
{
busy
=
1
;
iframe
->
state
=
NGHTTP2_IB_IGN_PAYLOAD
;
rv
=
nghttp2_session_terminate_session
(
session
,
NGHTTP2_PROTOCOL_ERROR
);
if
(
nghttp2_is_fatal
(
rv
))
{
return
rv
;
}
break
;
}
if
(
rv
==
1
)
{
if
(
iframe
->
state
==
NGHTTP2_IB_EXPECT_CONTINUATION
)
{
iframe
->
state
=
NGHTTP2_IB_READ_PAD_CONTINUATION
;
}
else
{
iframe
->
state
=
NGHTTP2_IB_IGN_PAD_CONTINUATION
;
}
break
;
}
busy
=
1
;
if
(
iframe
->
state
==
NGHTTP2_IB_EXPECT_CONTINUATION
)
{
iframe
->
state
=
NGHTTP2_IB_READ_HEADER_BLOCK
;
...
...
@@ -3771,6 +3903,46 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
iframe
->
state
=
NGHTTP2_IB_IGN_HEADER_BLOCK
;
}
break
;
case
NGHTTP2_IB_READ_PAD_CONTINUATION
:
case
NGHTTP2_IB_IGN_PAD_CONTINUATION
:
#ifdef DEBUGBUILD
if
(
iframe
->
state
==
NGHTTP2_IB_READ_PAD_CONTINUATION
)
{
fprintf
(
stderr
,
"[IB_READ_PAD_CONTINUATION]
\n
"
);
}
else
{
fprintf
(
stderr
,
"[IB_IGN_PAD_CONTINUATION]
\n
"
);
}
#endif
/* DEBUGBUILD */
readlen
=
inbound_frame_buf_read
(
iframe
,
in
,
last
);
in
+=
readlen
;
iframe
->
payloadleft
-=
readlen
;
DEBUGF
(
fprintf
(
stderr
,
"readlen=%zu, payloadleft=%zu, left=%zu
\n
"
,
readlen
,
iframe
->
payloadleft
,
iframe
->
left
));
if
(
iframe
->
left
)
{
return
in
-
first
;
}
busy
=
1
;
rv
=
inbound_frame_compute_pad
(
iframe
);
if
(
rv
<
0
)
{
rv
=
nghttp2_session_terminate_session
(
session
,
NGHTTP2_PROTOCOL_ERROR
);
if
(
nghttp2_is_fatal
(
rv
))
{
return
rv
;
}
iframe
->
state
=
NGHTTP2_IB_IGN_PAYLOAD
;
break
;
}
iframe
->
padlen
=
rv
;
if
(
iframe
->
frame
.
hd
.
type
==
NGHTTP2_HEADERS
)
{
iframe
->
frame
.
headers
.
padlen
+=
rv
;
}
else
{
iframe
->
frame
.
push_promise
.
padlen
+=
rv
;
}
if
(
iframe
->
state
==
NGHTTP2_IB_READ_PAD_CONTINUATION
)
{
iframe
->
state
=
NGHTTP2_IB_READ_HEADER_BLOCK
;
}
else
{
iframe
->
state
=
NGHTTP2_IB_IGN_HEADER_BLOCK
;
}
break
;
case
NGHTTP2_IB_READ_DATA
:
DEBUGF
(
fprintf
(
stderr
,
"[IB_READ_DATA]
\n
"
));
readlen
=
inbound_frame_payload_readlen
(
iframe
,
in
,
last
);
...
...
@@ -3779,7 +3951,7 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
DEBUGF
(
fprintf
(
stderr
,
"readlen=%zu, payloadleft=%zu
\n
"
,
readlen
,
iframe
->
payloadleft
));
if
(
readlen
>
0
)
{
s
ize_t
data_readlen
=
readlen
;
s
size_t
data_
readlen
;
rv
=
nghttp2_session_update_recv_connection_window_size
(
session
,
readlen
);
if
(
nghttp2_is_fatal
(
rv
))
{
...
...
@@ -3798,17 +3970,8 @@ ssize_t nghttp2_session_mem_recv(nghttp2_session *session,
}
}
}
if
(
nghttp2_frame_data_trail_padlen
(
&
iframe
->
frame
.
data
)
>
iframe
->
payloadleft
)
{
size_t
trail_padlen
;
trail_padlen
=
nghttp2_frame_data_trail_padlen
(
&
iframe
->
frame
.
data
)
-
iframe
->
payloadleft
;
if
(
readlen
<
trail_padlen
)
{
data_readlen
=
0
;
}
else
{
data_readlen
-=
trail_padlen
;
}
}
data_readlen
=
inbound_frame_effective_readlen
(
iframe
,
iframe
->
payloadleft
,
readlen
);
DEBUGF
(
fprintf
(
stderr
,
"data_readlen=%zu
\n
"
,
data_readlen
));
if
(
data_readlen
>
0
&&
session
->
callbacks
.
on_data_chunk_recv_callback
)
{
rv
=
session
->
callbacks
.
on_data_chunk_recv_callback
...
...
@@ -4066,11 +4229,11 @@ ssize_t nghttp2_session_pack_data(nghttp2_session *session,
frame
->
hd
.
flags
&=
~
(
NGHTTP2_FLAG_PAD_HIGH
|
NGHTTP2_FLAG_PAD_LOW
);
flags
=
0
;
if
(
(
session
->
opt_flags
&
NGHTTP2_OPTMASK_NO_DATA_PADDING
)
==
0
&&
if
(
session
->
pad_alignment
&&
payloadlen
>
0
&&
(
size_t
)
payloadlen
<
datamax
)
{
rv
=
nghttp2_frame_add_pad
(
buf_ptr
,
buflen_ptr
,
bufoff_ptr
,
&
flags
,
payloadlen
,
datamax
,
session
->
data_
pad_alignment
);
session
->
pad_alignment
);
if
(
rv
<
0
)
{
return
rv
;
}
...
...
lib/nghttp2_session.h
View file @
1db21953
...
...
@@ -44,10 +44,7 @@
*/
typedef
enum
{
NGHTTP2_OPTMASK_NO_AUTO_STREAM_WINDOW_UPDATE
=
1
<<
0
,
NGHTTP2_OPTMASK_NO_AUTO_CONNECTION_WINDOW_UPDATE
=
1
<<
1
,
/* Option to disable DATA frame padding, which is currently hidden
from outside, but provided for ease of testing */
NGHTTP2_OPTMASK_NO_DATA_PADDING
=
1
<<
2
,
NGHTTP2_OPTMASK_NO_AUTO_CONNECTION_WINDOW_UPDATE
=
1
<<
1
}
nghttp2_optmask
;
typedef
struct
{
...
...
@@ -89,6 +86,8 @@ typedef enum {
NGHTTP2_IB_READ_GOAWAY_DEBUG
,
NGHTTP2_IB_EXPECT_CONTINUATION
,
NGHTTP2_IB_IGN_CONTINUATION
,
NGHTTP2_IB_READ_PAD_CONTINUATION
,
NGHTTP2_IB_IGN_PAD_CONTINUATION
,
NGHTTP2_IB_READ_DATA
,
NGHTTP2_IB_IGN_DATA
}
nghttp2_inbound_state
;
...
...
@@ -105,6 +104,8 @@ typedef struct {
size_t
left
;
/* How many bytes we still need to receive for current frame */
size_t
payloadleft
;
/* padding length for the current frame */
size_t
padlen
;
nghttp2_inbound_state
state
;
/* TODO, remove this. Error code */
int
error_code
;
...
...
@@ -152,8 +153,8 @@ struct nghttp2_session {
size_t
num_incoming_streams
;
/* The number of bytes allocated for nvbuf */
size_t
nvbuflen
;
/*
DATA padding alignemnt. See NGHTTP2_OPT_DATA
_PAD_ALIGNMENT. */
size_t
data_
pad_alignment
;
/*
padding alignemnt. See NGHTTP2_OPT
_PAD_ALIGNMENT. */
size_t
pad_alignment
;
/* Next Stream ID. Made unsigned int to detect >= (1 << 31). */
uint32_t
next_stream_id
;
/* The largest stream ID received so far */
...
...
src/HttpServer.cc
View file @
1db21953
...
...
@@ -66,7 +66,7 @@ const std::string NGHTTPD_SERVER = "nghttpd nghttp2/" NGHTTP2_VERSION;
Config
::
Config
()
:
data_ptr
(
nullptr
),
output_upper_thres
(
1024
*
1024
),
data_pad_alignment
(
NGHTTP2_DATA
_PAD_ALIGNMENT
),
pad_alignment
(
NGHTTP2
_PAD_ALIGNMENT
),
header_table_size
(
-
1
),
port
(
0
),
verbose
(
false
),
...
...
@@ -365,11 +365,11 @@ int Http2Handler::on_connect()
nghttp2_opt_set
opt_set
;
memset
(
&
opt_set
,
0
,
sizeof
(
opt_set
));
opt_set
.
data_pad_alignment
=
sessions_
->
get_config
()
->
data_
pad_alignment
;
opt_set
.
pad_alignment
=
sessions_
->
get_config
()
->
pad_alignment
;
fill_callback
(
callbacks
,
sessions_
->
get_config
());
r
=
nghttp2_session_server_new2
(
&
session_
,
&
callbacks
,
this
,
NGHTTP2_OPT_
DATA_
PAD_ALIGNMENT
,
&
opt_set
);
NGHTTP2_OPT_PAD_ALIGNMENT
,
&
opt_set
);
if
(
r
!=
0
)
{
return
r
;
}
...
...
src/HttpServer.h
View file @
1db21953
...
...
@@ -56,7 +56,7 @@ struct Config {
std
::
string
cert_file
;
void
*
data_ptr
;
size_t
output_upper_thres
;
size_t
data_
pad_alignment
;
size_t
pad_alignment
;
ssize_t
header_table_size
;
uint16_t
port
;
bool
verbose
;
...
...
src/app_helper.cc
View file @
1db21953
...
...
@@ -244,6 +244,18 @@ void print_flags(const nghttp2_frame_hd& hd)
}
s
+=
"PRIORITY"
;
}
if
(
hd
.
flags
&
NGHTTP2_FLAG_PAD_LOW
)
{
if
(
!
s
.
empty
())
{
s
+=
" | "
;
}
s
+=
"PAD_LOW"
;
}
if
(
hd
.
flags
&
NGHTTP2_FLAG_PAD_HIGH
)
{
if
(
!
s
.
empty
())
{
s
+=
" | "
;
}
s
+=
"PAD_HIGH"
;
}
break
;
case
NGHTTP2_SETTINGS
:
if
(
hd
.
flags
&
NGHTTP2_FLAG_ACK
)
{
...
...
@@ -254,6 +266,18 @@ void print_flags(const nghttp2_frame_hd& hd)
if
(
hd
.
flags
&
NGHTTP2_FLAG_END_PUSH_PROMISE
)
{
s
+=
"END_PUSH_PROMISE"
;
}
if
(
hd
.
flags
&
NGHTTP2_FLAG_PAD_LOW
)
{
if
(
!
s
.
empty
())
{
s
+=
" | "
;
}
s
+=
"PAD_LOW"
;
}
if
(
hd
.
flags
&
NGHTTP2_FLAG_PAD_HIGH
)
{
if
(
!
s
.
empty
())
{
s
+=
" | "
;
}
s
+=
"PAD_HIGH"
;
}
break
;
case
NGHTTP2_PING
:
if
(
hd
.
flags
&
NGHTTP2_FLAG_ACK
)
{
...
...
@@ -297,10 +321,9 @@ void print_frame(print_type ptype, const nghttp2_frame *frame)
}
break
;
case
NGHTTP2_HEADERS
:
if
(
frame
->
hd
.
flags
&
NGHTTP2_FLAG_PRIORITY
)
{
print_frame_attr_indent
();
printf
(
"(pri=%d)
\n
"
,
frame
->
headers
.
pri
);
}
printf
(
"(pri=%d, padlen=%zu)
\n
"
,
frame
->
headers
.
pri
,
frame
->
headers
.
padlen
);
switch
(
frame
->
headers
.
cat
)
{
case
NGHTTP2_HCAT_REQUEST
:
print_frame_attr_indent
();
...
...
@@ -342,8 +365,9 @@ void print_frame(print_type ptype, const nghttp2_frame *frame)
break
;
case
NGHTTP2_PUSH_PROMISE
:
print_frame_attr_indent
();
printf
(
"(promised_stream_id=%d)
\n
"
,
frame
->
push_promise
.
promised_stream_id
);
printf
(
"(promised_stream_id=%d, padlen=%zu)
\n
"
,
frame
->
push_promise
.
promised_stream_id
,
frame
->
push_promise
.
padlen
);
print_nv
(
frame
->
push_promise
.
nva
,
frame
->
push_promise
.
nvlen
);
break
;
case
NGHTTP2_PING
:
...
...
src/nghttp.cc
View file @
1db21953
...
...
@@ -82,7 +82,7 @@ struct Config {
std
::
string
keyfile
;
std
::
string
datafile
;
size_t
output_upper_thres
;
size_t
data_
pad_alignment
;
size_t
pad_alignment
;
ssize_t
peer_max_concurrent_streams
;
ssize_t
header_table_size
;
int32_t
pri
;
...
...
@@ -100,7 +100,7 @@ struct Config {
bool
continuation
;
Config
()
:
output_upper_thres
(
1024
*
1024
),
data_pad_alignment
(
NGHTTP2_DATA
_PAD_ALIGNMENT
),
pad_alignment
(
NGHTTP2
_PAD_ALIGNMENT
),
peer_max_concurrent_streams
(
NGHTTP2_INITIAL_MAX_CONCURRENT_STREAMS
),
header_table_size
(
-
1
),
pri
(
NGHTTP2_PRI_DEFAULT
),
...
...
@@ -716,10 +716,10 @@ struct HttpClient {
}
nghttp2_opt_set
opt_set
;
opt_set
.
peer_max_concurrent_streams
=
config
.
peer_max_concurrent_streams
;
opt_set
.
data_pad_alignment
=
config
.
data_
pad_alignment
;
opt_set
.
pad_alignment
=
config
.
pad_alignment
;
rv
=
nghttp2_session_client_new2
(
&
session
,
callbacks
,
this
,
NGHTTP2_OPT_PEER_MAX_CONCURRENT_STREAMS
|
NGHTTP2_OPT_
DATA_
PAD_ALIGNMENT
,
NGHTTP2_OPT_PAD_ALIGNMENT
,
&
opt_set
);
if
(
rv
!=
0
)
{
return
-
1
;
...
...
@@ -1710,8 +1710,8 @@ void print_help(std::ostream& out)
<<
" is large enough as it is seen as unlimited.
\n
"
<<
" -c, --header-table-size=<N>
\n
"
<<
" Specify decoder header table size.
\n
"
<<
" -b, --
data-
pad=<ALIGNMENT>
\n
"
<<
" Alignment of
DATA frame
padding.
\n
"
<<
" -b, --pad=<ALIGNMENT>
\n
"
<<
" Alignment of
frame payload
padding.
\n
"
<<
" --color Force colored log output.
\n
"
<<
" --continuation Send large header to test CONTINUATION.
\n
"
<<
std
::
endl
;
...
...
@@ -1766,7 +1766,7 @@ int main(int argc, char **argv)
print_help
(
std
::
cout
);
exit
(
EXIT_SUCCESS
);
case
'b'
:
config
.
data_
pad_alignment
=
strtol
(
optarg
,
nullptr
,
10
);
config
.
pad_alignment
=
strtol
(
optarg
,
nullptr
,
10
);
break
;
case
'n'
:
config
.
null_out
=
true
;
...
...
src/nghttpd.cc
View file @
1db21953
...
...
@@ -115,8 +115,8 @@ void print_help(std::ostream& out)
<<
" -p/=/foo.png -p/doc=/bar.css
\n
"
<<
" PATH and PUSH_PATHs are relative to document
\n
"
<<
" root. See --htdocs option.
\n
"
<<
" -b, --
data-
pad=<ALIGNMENT>
\n
"
<<
" Alignment of
DATA frame
padding.
\n
"
<<
" -b, --pad=<ALIGNMENT>
\n
"
<<
" Alignment of
frame payload
padding.
\n
"
<<
" -h, --help Print this help.
\n
"
<<
std
::
endl
;
}
...
...
@@ -155,7 +155,7 @@ int main(int argc, char **argv)
config
.
verify_client
=
true
;
break
;
case
'b'
:
config
.
data_
pad_alignment
=
strtol
(
optarg
,
nullptr
,
10
);
config
.
pad_alignment
=
strtol
(
optarg
,
nullptr
,
10
);
break
;
case
'd'
:
config
.
htdocs
=
optarg
;
...
...
tests/nghttp2_frame_test.c
View file @
1db21953
...
...
@@ -74,6 +74,7 @@ void test_nghttp2_frame_pack_headers()
nghttp2_headers
frame
,
oframe
;
uint8_t
*
buf
=
NULL
;
size_t
buflen
=
0
;
size_t
bufoff
;
ssize_t
framelen
;
nghttp2_nv
*
nva
;
ssize_t
nvlen
;
...
...
@@ -89,17 +90,21 @@ void test_nghttp2_frame_pack_headers()
NGHTTP2_FLAG_END_STREAM
|
NGHTTP2_FLAG_END_HEADERS
,
1000000007
,
1
<<
20
,
nva
,
nvlen
);
framelen
=
nghttp2_frame_pack_headers
(
&
buf
,
&
buflen
,
&
frame
,
&
deflater
);
framelen
=
nghttp2_frame_pack_headers
(
&
buf
,
&
buflen
,
&
bufoff
,
&
frame
,
&
deflater
,
0
);
CU_ASSERT
(
0
==
unpack_frame
((
nghttp2_frame
*
)
&
oframe
,
buf
,
framelen
));
check_frame_header
(
framelen
-
NGHTTP2_FRAME_HEAD_LENGTH
,
NGHTTP2_HEADERS
,
CU_ASSERT
(
0
==
unpack_frame
((
nghttp2_frame
*
)
&
oframe
,
buf
+
bufoff
,
framelen
-
bufoff
));
check_frame_header
(
framelen
-
bufoff
-
NGHTTP2_FRAME_HEAD_LENGTH
,
NGHTTP2_HEADERS
,
NGHTTP2_FLAG_END_STREAM
|
NGHTTP2_FLAG_END_HEADERS
,
1000000007
,
&
oframe
.
hd
);
/* We didn't include PRIORITY flag so priority is not packed */
CU_ASSERT
(
1
<<
30
==
oframe
.
pri
);
CU_ASSERT
(
framelen
-
8
==
inflate_hd
(
&
inflater
,
&
out
,
buf
+
8
,
framelen
-
8
));
CU_ASSERT
(
framelen
-
(
ssize_t
)
bufoff
-
8
==
inflate_hd
(
&
inflater
,
&
out
,
buf
+
bufoff
+
8
,
framelen
-
bufoff
-
8
));
CU_ASSERT
(
7
==
out
.
nvlen
);
CU_ASSERT
(
nvnameeq
(
"method"
,
&
out
.
nva
[
0
]));
...
...
@@ -111,10 +116,13 @@ void test_nghttp2_frame_pack_headers()
memset
(
&
oframe
,
0
,
sizeof
(
oframe
));
/* Next, include PRIORITY flag */
frame
.
hd
.
flags
|=
NGHTTP2_FLAG_PRIORITY
;
framelen
=
nghttp2_frame_pack_headers
(
&
buf
,
&
buflen
,
&
frame
,
&
deflater
);
framelen
=
nghttp2_frame_pack_headers
(
&
buf
,
&
buflen
,
&
bufoff
,
&
frame
,
&
deflater
,
0
);
CU_ASSERT
(
0
==
unpack_frame
((
nghttp2_frame
*
)
&
oframe
,
buf
,
framelen
));
check_frame_header
(
framelen
-
NGHTTP2_FRAME_HEAD_LENGTH
,
NGHTTP2_HEADERS
,
CU_ASSERT
(
0
==
unpack_frame
((
nghttp2_frame
*
)
&
oframe
,
buf
+
bufoff
,
framelen
-
bufoff
));
check_frame_header
(
framelen
-
bufoff
-
NGHTTP2_FRAME_HEAD_LENGTH
,
NGHTTP2_HEADERS
,
NGHTTP2_FLAG_END_STREAM
|
NGHTTP2_FLAG_END_HEADERS
|
NGHTTP2_FLAG_PRIORITY
,
1000000007
,
&
oframe
.
hd
);
...
...
@@ -140,6 +148,7 @@ void test_nghttp2_frame_pack_headers_frame_too_large(void)
nghttp2_headers
frame
;
uint8_t
*
buf
=
NULL
;
size_t
buflen
=
0
;
size_t
bufoff
;
ssize_t
framelen
;
nghttp2_nv
*
nva
;
ssize_t
nvlen
;
...
...
@@ -163,7 +172,8 @@ void test_nghttp2_frame_pack_headers_frame_too_large(void)
NGHTTP2_FLAG_END_STREAM
|
NGHTTP2_FLAG_END_HEADERS
,
1000000007
,
0
,
nva
,
nvlen
);
framelen
=
nghttp2_frame_pack_headers
(
&
buf
,
&
buflen
,
&
frame
,
&
deflater
);
framelen
=
nghttp2_frame_pack_headers
(
&
buf
,
&
buflen
,
&
bufoff
,
&
frame
,
&
deflater
,
0
);
CU_ASSERT_EQUAL
(
NGHTTP2_ERR_HEADER_COMP
,
framelen
);
nghttp2_frame_headers_free
(
&
frame
);
...
...
tests/nghttp2_session_test.c
View file @
1db21953
...
...
@@ -336,9 +336,10 @@ void test_nghttp2_session_recv(void)
};
uint8_t
*
framedata
=
NULL
;
size_t
framedatalen
=
0
;
size_t
bufoff
;
ssize_t
framelen
;
nghttp2_frame
frame
;
in
t
i
;
size_
t
i
;
nghttp2_outbound_item
*
item
;
nghttp2_nv
*
nva
;
ssize_t
nvlen
;
...
...
@@ -355,13 +356,13 @@ void test_nghttp2_session_recv(void)
nvlen
=
nghttp2_nv_array_copy
(
&
nva
,
nv
,
ARRLEN
(
nv
));
nghttp2_frame_headers_init
(
&
frame
.
headers
,
NGHTTP2_FLAG_END_HEADERS
,
1
,
NGHTTP2_PRI_DEFAULT
,
nva
,
nvlen
);
framelen
=
nghttp2_frame_pack_headers
(
&
framedata
,
&
framedatalen
,
framelen
=
nghttp2_frame_pack_headers
(
&
framedata
,
&
framedatalen
,
&
bufoff
,
&
frame
.
headers
,
&
deflater
);
&
deflater
,
0
);
scripted_data_feed_init
(
&
df
,
framedata
,
framelen
);
scripted_data_feed_init
(
&
df
,
framedata
+
bufoff
,
framelen
-
bufoff
);
/* Send 1 byte per each read */
for
(
i
=
0
;
i
<
framelen
;
++
i
)
{
for
(
i
=
0
;
i
<
framelen
-
bufoff
;
++
i
)
{
df
.
feedseq
[
i
]
=
1
;
}
nghttp2_frame_headers_free
(
&
frame
.
headers
);
...
...
@@ -375,13 +376,13 @@ void test_nghttp2_session_recv(void)
/* Received HEADERS without header block, which is valid */
nghttp2_frame_headers_init
(
&
frame
.
headers
,
NGHTTP2_FLAG_END_HEADERS
,
5
,
NGHTTP2_PRI_DEFAULT
,
NULL
,
0
);
framelen
=
nghttp2_frame_pack_headers
(
&
framedata
,
&
framedatalen
,
framelen
=
nghttp2_frame_pack_headers
(
&
framedata
,
&
framedatalen
,
&
bufoff
,
&
frame
.
headers
,
&
deflater
);
&
deflater
,
0
);
nghttp2_frame_headers_free
(
&
frame
.
headers
);
scripted_data_feed_init
(
&
df
,
framedata
,
framelen
);
scripted_data_feed_init
(
&
df
,
framedata
+
bufoff
,
framelen
-
bufoff
);
user_data
.
frame_recv_cb_called
=
0
;
CU_ASSERT
(
0
==
nghttp2_session_recv
(
session
));
CU_ASSERT
(
1
==
user_data
.
frame_recv_cb_called
);
...
...
@@ -421,6 +422,7 @@ void test_nghttp2_session_recv_invalid_stream_id(void)
my_user_data
user_data
;
uint8_t
*
framedata
=
NULL
;
size_t
framedatalen
=
0
;
size_t
bufoff
;
ssize_t
framelen
;
nghttp2_frame
frame
;
nghttp2_hd_deflater
deflater
;
...
...
@@ -436,11 +438,11 @@ void test_nghttp2_session_recv_invalid_stream_id(void)
nghttp2_frame_headers_init
(
&
frame
.
headers
,
NGHTTP2_FLAG_END_HEADERS
,
2
,
NGHTTP2_PRI_DEFAULT
,
NULL
,
0
);
framelen
=
nghttp2_frame_pack_headers
(
&
framedata
,
&
framedatalen
,
framelen
=
nghttp2_frame_pack_headers
(
&
framedata
,
&
framedatalen
,
&
bufoff
,
&
frame
.
headers
,
&
deflater
);
&
deflater
,
0
);
scripted_data_feed_init
(
&
df
,
framedata
,
framelen
);
scripted_data_feed_init
(
&
df
,
framedata
+
bufoff
,
framelen
-
bufoff
);
nghttp2_frame_headers_free
(
&
frame
.
headers
);
CU_ASSERT
(
0
==
nghttp2_session_recv
(
session
));
...
...
@@ -462,6 +464,7 @@ void test_nghttp2_session_recv_invalid_frame(void)
};
uint8_t
*
framedata
=
NULL
;
size_t
framedatalen
=
0
;
size_t
bufoff
;
ssize_t
framelen
;
nghttp2_frame
frame
;
nghttp2_nv
*
nva
;
...
...
@@ -480,11 +483,11 @@ void test_nghttp2_session_recv_invalid_frame(void)
nvlen
=
nghttp2_nv_array_copy
(
&
nva
,
nv
,
ARRLEN
(
nv
));
nghttp2_frame_headers_init
(
&
frame
.
headers
,
NGHTTP2_FLAG_END_HEADERS
,
1
,
NGHTTP2_PRI_DEFAULT
,
nva
,
nvlen
);
framelen
=
nghttp2_frame_pack_headers
(
&
framedata
,
&
framedatalen
,
framelen
=
nghttp2_frame_pack_headers
(
&
framedata
,
&
framedatalen
,
&
bufoff
,
&
frame
.
headers
,
&
deflater
);
&
deflater
,
0
);
scripted_data_feed_init
(
&
df
,
framedata
,
framelen
);
scripted_data_feed_init
(
&
df
,
framedata
+
bufoff
,
framelen
-
bufoff
);
CU_ASSERT
(
0
==
nghttp2_session_recv
(
session
));
CU_ASSERT
(
0
==
nghttp2_session_send
(
session
));
...
...
@@ -492,7 +495,7 @@ void test_nghttp2_session_recv_invalid_frame(void)
/* Receive exactly same bytes of HEADERS is treated as subsequent
HEADERS (e.g., trailers */
scripted_data_feed_init
(
&
df
,
framedata
,
framelen
);
scripted_data_feed_init
(
&
df
,
framedata
+
bufoff
,
framelen
-
bufoff
);
CU_ASSERT
(
0
==
nghttp2_session_recv
(
session
));
CU_ASSERT
(
0
==
nghttp2_session_send
(
session
));
...
...
@@ -660,6 +663,7 @@ void test_nghttp2_session_recv_continuation(void)
uint8_t
*
framedata
=
NULL
;
size_t
framedatacap
=
0
;
size_t
framedatalen
;
size_t
bufoff
;
size_t
framedataoff
;
ssize_t
rv
;
my_user_data
ud
;
...
...
@@ -681,13 +685,14 @@ void test_nghttp2_session_recv_continuation(void)
nghttp2_frame_headers_init
(
&
frame
.
headers
,
NGHTTP2_FLAG_NONE
,
1
,
NGHTTP2_PRI_DEFAULT
,
nva
,
nvlen
);
framedatalen
=
nghttp2_frame_pack_headers
(
&
framedata
,
&
framedatacap
,
&
bufoff
,
&
frame
.
headers
,
&
deflater
);
&
deflater
,
0
);
nghttp2_frame_headers_free
(
&
frame
.
headers
);
memcpy
(
data
,
framedata
,
9
);
memcpy
(
data
,
framedata
+
bufoff
,
9
);
datalen
=
9
;
framedataoff
=
NGHTTP2_FRAME_HEAD_LENGTH
+
1
;
framedataoff
=
bufoff
+
NGHTTP2_FRAME_HEAD_LENGTH
+
1
;
nghttp2_put_uint16be
(
data
,
1
);
...
...
@@ -735,12 +740,12 @@ void test_nghttp2_session_recv_continuation(void)
nvlen
=
nghttp2_nv_array_copy
(
&
nva
,
nv1
,
ARRLEN
(
nv1
));
nghttp2_frame_headers_init
(
&
frame
.
headers
,
NGHTTP2_FLAG_NONE
,
1
,
NGHTTP2_PRI_DEFAULT
,
nva
,
nvlen
);
framedatalen
=
nghttp2_frame_pack_headers
(
&
framedata
,
&
framedatacap
,
framedatalen
=
nghttp2_frame_pack_headers
(
&
framedata
,
&
framedatacap
,
&
bufoff
,
&
frame
.
headers
,
&
deflater
);
&
deflater
,
0
);
nghttp2_frame_headers_free
(
&
frame
.
headers
);
memcpy
(
data
,
framedata
,
framedatalen
);
datalen
=
framedatalen
;
memcpy
(
data
,
framedata
+
bufoff
,
framedatalen
-
bufoff
);
datalen
=
framedatalen
-
bufoff
;
/* Followed by PRIORITY */
nghttp2_frame_priority_init
(
&
frame
.
priority
,
1
,
0
);
...
...
@@ -782,6 +787,7 @@ void test_nghttp2_session_continue(void)
uint8_t
buffer
[
4096
];
uint8_t
*
bufp
=
buffer
;
size_t
buflen
;
size_t
bufoff
;
nghttp2_frame
frame
;
nghttp2_nv
*
nva
;
ssize_t
nvlen
;
...
...
@@ -804,22 +810,24 @@ void test_nghttp2_session_continue(void)
nvlen
=
nghttp2_nv_array_copy
(
&
nva
,
nv1
,
ARRLEN
(
nv1
));
nghttp2_frame_headers_init
(
&
frame
.
headers
,
NGHTTP2_FLAG_END_HEADERS
,
1
,
NGHTTP2_PRI_DEFAULT
,
nva
,
nvlen
);
framelen1
=
nghttp2_frame_pack_headers
(
&
framedata
,
&
framedatalen
,
framelen1
=
nghttp2_frame_pack_headers
(
&
framedata
,
&
framedatalen
,
&
bufoff
,
&
frame
.
headers
,
&
deflater
);
&
deflater
,
0
);
nghttp2_frame_headers_free
(
&
frame
.
headers
);
memcpy
(
buffer
,
framedata
,
framelen1
);
memcpy
(
buffer
,
framedata
+
bufoff
,
framelen1
-
bufoff
);
framelen1
-=
bufoff
;
nvlen
=
nghttp2_nv_array_copy
(
&
nva
,
nv2
,
ARRLEN
(
nv2
));
nghttp2_frame_headers_init
(
&
frame
.
headers
,
NGHTTP2_FLAG_END_HEADERS
,
3
,
NGHTTP2_PRI_DEFAULT
,
nva
,
nvlen
);
framelen2
=
nghttp2_frame_pack_headers
(
&
framedata
,
&
framedatalen
,
framelen2
=
nghttp2_frame_pack_headers
(
&
framedata
,
&
framedatalen
,
&
bufoff
,
&
frame
.
headers
,
&
deflater
);
&
deflater
,
0
);
nghttp2_frame_headers_free
(
&
frame
.
headers
);
memcpy
(
buffer
+
framelen1
,
framedata
,
framelen2
);
memcpy
(
buffer
+
framelen1
,
framedata
+
bufoff
,
framelen2
-
bufoff
);
framelen2
-=
bufoff
;
buflen
=
framelen1
+
framelen2
;
/* Receive 1st HEADERS and pause */
...
...
@@ -955,6 +963,7 @@ void test_nghttp2_session_add_frame(void)
acc
.
length
=
0
;
user_data
.
acc
=
&
acc
;
CU_ASSERT
(
0
==
nghttp2_session_client_new
(
&
session
,
&
callbacks
,
&
user_data
));
session_disable_pad
(
session
);
frame
=
malloc
(
sizeof
(
nghttp2_frame
));
nvlen
=
nghttp2_nv_array_copy
(
&
nva
,
nv
,
ARRLEN
(
nv
));
...
...
@@ -2173,6 +2182,7 @@ void test_nghttp2_submit_request_without_data(void)
memset
(
&
callbacks
,
0
,
sizeof
(
nghttp2_session_callbacks
));
callbacks
.
send_callback
=
accumulator_send_callback
;
CU_ASSERT
(
0
==
nghttp2_session_client_new
(
&
session
,
&
callbacks
,
&
ud
));
session_disable_pad
(
session
);
nghttp2_hd_inflate_init
(
&
inflater
,
NGHTTP2_HD_SIDE_REQUEST
);
CU_ASSERT
(
0
==
nghttp2_submit_request
(
session
,
NGHTTP2_PRI_DEFAULT
,
nva
,
ARRLEN
(
nva
),
&
data_prd
,
NULL
));
...
...
@@ -2244,6 +2254,7 @@ void test_nghttp2_submit_response_without_data(void)
memset
(
&
callbacks
,
0
,
sizeof
(
nghttp2_session_callbacks
));
callbacks
.
send_callback
=
accumulator_send_callback
;
CU_ASSERT
(
0
==
nghttp2_session_server_new
(
&
session
,
&
callbacks
,
&
ud
));
session_disable_pad
(
session
);
nghttp2_hd_inflate_init
(
&
inflater
,
NGHTTP2_HD_SIDE_RESPONSE
);
nghttp2_session_open_stream
(
session
,
1
,
NGHTTP2_FLAG_END_STREAM
,
NGHTTP2_PRI_DEFAULT
,
...
...
@@ -2415,6 +2426,7 @@ void test_nghttp2_submit_headers(void)
callbacks
.
on_frame_send_callback
=
on_frame_send_callback
;
CU_ASSERT
(
0
==
nghttp2_session_client_new
(
&
session
,
&
callbacks
,
&
ud
));
session_disable_pad
(
session
);
nghttp2_hd_inflate_init
(
&
inflater
,
NGHTTP2_HD_SIDE_REQUEST
);
CU_ASSERT
(
0
==
nghttp2_submit_headers
(
session
,
NGHTTP2_FLAG_END_STREAM
,
...
...
@@ -3858,7 +3870,7 @@ void test_nghttp2_session_pack_data_with_padding(void)
data_prd
.
read_callback
=
fixed_length_data_source_read_callback
;
nghttp2_session_client_new
(
&
session
,
&
callbacks
,
&
ud
);
session
->
data_
pad_alignment
=
512
;
session
->
pad_alignment
=
512
;
nghttp2_submit_request
(
session
,
NGHTTP2_PRI_DEFAULT
,
NULL
,
0
,
&
data_prd
,
NULL
);
...
...
@@ -3869,7 +3881,7 @@ void test_nghttp2_session_pack_data_with_padding(void)
CU_ASSERT
(
NGHTTP2_HEADERS
==
ud
.
sent_frame_type
);
frame
=
OB_DATA
(
session
->
aob
.
item
);
CU_ASSERT
(
session
->
data_
pad_alignment
-
datalen
==
frame
->
padlen
);
CU_ASSERT
(
session
->
pad_alignment
-
datalen
==
frame
->
padlen
);
CU_ASSERT
(
frame
->
hd
.
flags
&
NGHTTP2_FLAG_PAD_LOW
);
CU_ASSERT
(
frame
->
hd
.
flags
&
NGHTTP2_FLAG_PAD_HIGH
);
...
...
@@ -3893,7 +3905,7 @@ void test_nghttp2_session_pack_data_with_padding(void)
CU_ASSERT
(
NGHTTP2_HEADERS
==
ud
.
sent_frame_type
);
frame
=
OB_DATA
(
session
->
aob
.
item
);
CU_ASSERT
(
session
->
data_
pad_alignment
-
datalen
==
frame
->
padlen
);
CU_ASSERT
(
session
->
pad_alignment
-
datalen
==
frame
->
padlen
);
CU_ASSERT
(
frame
->
hd
.
flags
&
NGHTTP2_FLAG_PAD_LOW
);
CU_ASSERT
(
0
==
(
frame
->
hd
.
flags
&
NGHTTP2_FLAG_PAD_HIGH
));
...
...
tests/nghttp2_test_helper.c
View file @
1db21953
...
...
@@ -159,3 +159,8 @@ ssize_t inflate_hd(nghttp2_hd_inflater *inflater, nva_out *out,
nghttp2_hd_inflate_end_headers
(
inflater
);
return
initial
-
buflen
;
}
void
session_disable_pad
(
nghttp2_session
*
session
)
{
session
->
pad_alignment
=
0
;
}
tests/nghttp2_test_helper.h
View file @
1db21953
...
...
@@ -29,6 +29,7 @@
# include <config.h>
#endif
/* HAVE_CONFIG_H */
#include "nghttp2_session.h"
#include "nghttp2_frame.h"
#include "nghttp2_hd.h"
...
...
@@ -57,4 +58,6 @@ void add_out(nva_out *out, nghttp2_nv *nv);
ssize_t
inflate_hd
(
nghttp2_hd_inflater
*
inflater
,
nva_out
*
out
,
uint8_t
*
buf
,
size_t
buflen
);
void
session_disable_pad
(
nghttp2_session
*
session
);
#endif
/* NGHTTP2_TEST_HELPER_H */
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