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
a46ccdb1
Commit
a46ccdb1
authored
Oct 27, 2013
by
Tatsuhiro Tsujikawa
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Apply initiated SETTINGS changes on reception of ACK
parent
2afa9f75
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
343 additions
and
89 deletions
+343
-89
lib/includes/nghttp2/nghttp2.h
lib/includes/nghttp2/nghttp2.h
+14
-2
lib/nghttp2_frame.c
lib/nghttp2_frame.c
+2
-3
lib/nghttp2_frame.h
lib/nghttp2_frame.h
+1
-1
lib/nghttp2_session.c
lib/nghttp2_session.c
+188
-11
lib/nghttp2_session.h
lib/nghttp2_session.h
+37
-4
lib/nghttp2_submit.c
lib/nghttp2_submit.c
+1
-33
src/app_helper.cc
src/app_helper.cc
+14
-5
tests/nghttp2_frame_test.c
tests/nghttp2_frame_test.c
+4
-3
tests/nghttp2_session_test.c
tests/nghttp2_session_test.c
+82
-27
No files found.
lib/includes/nghttp2/nghttp2.h
View file @
a46ccdb1
...
...
@@ -127,6 +127,13 @@ typedef struct {
*/
#define NGHTTP2_INITIAL_CONNECTION_WINDOW_SIZE ((1 << 16) - 1)
/**
* @macro
*
* The maximum header table size.
*/
#define NGHTTP2_MAX_HEADER_TABLE_SIZE (1 << 16)
/**
* @macro
*
...
...
@@ -262,6 +269,11 @@ typedef enum {
* Callback was paused by the application
*/
NGHTTP2_ERR_PAUSE
=
-
526
,
/**
* There are too many in-flight SETTING frame and no more
* transmission of SETTINGS is allowed.
*/
NGHTTP2_ERR_TOO_MANY_INFLIGHT_SETTINGS
=
-
527
,
/**
* The errors < :enum:`NGHTTP2_ERR_FATAL` mean that the library is
* under unexpected condition and cannot process any further data
...
...
@@ -379,9 +391,9 @@ typedef enum {
*/
NGHTTP2_FLAG_END_PUSH_PROMISE
=
0x4
,
/**
* The
PONG
flag.
* The
ACK
flag.
*/
NGHTTP2_FLAG_
PONG
=
0x1
NGHTTP2_FLAG_
ACK
=
0x1
}
nghttp2_flag
;
/**
...
...
lib/nghttp2_frame.c
View file @
a46ccdb1
...
...
@@ -106,12 +106,11 @@ void nghttp2_frame_rst_stream_free(nghttp2_rst_stream *frame)
{}
void
nghttp2_frame_settings_init
(
nghttp2_settings
*
frame
,
void
nghttp2_frame_settings_init
(
nghttp2_settings
*
frame
,
uint8_t
flags
,
nghttp2_settings_entry
*
iv
,
size_t
niv
)
{
memset
(
frame
,
0
,
sizeof
(
nghttp2_settings
));
nghttp2_frame_set_hd
(
&
frame
->
hd
,
niv
*
8
,
NGHTTP2_SETTINGS
,
NGHTTP2_FLAG_NONE
,
0
);
nghttp2_frame_set_hd
(
&
frame
->
hd
,
niv
*
8
,
NGHTTP2_SETTINGS
,
flags
,
0
);
frame
->
niv
=
niv
;
frame
->
iv
=
iv
;
}
...
...
lib/nghttp2_frame.h
View file @
a46ccdb1
...
...
@@ -470,7 +470,7 @@ void nghttp2_frame_push_promise_free(nghttp2_push_promise *frame);
* ownership of |iv|, so caller must not free it. The |flags| are
* bitwise-OR of one or more of nghttp2_settings_flag.
*/
void
nghttp2_frame_settings_init
(
nghttp2_settings
*
frame
,
void
nghttp2_frame_settings_init
(
nghttp2_settings
*
frame
,
uint8_t
flags
,
nghttp2_settings_entry
*
iv
,
size_t
niv
);
void
nghttp2_frame_settings_free
(
nghttp2_settings
*
frame
);
...
...
lib/nghttp2_session.c
View file @
a46ccdb1
...
...
@@ -191,6 +191,8 @@ static int nghttp2_session_new(nghttp2_session **session_ptr,
(
*
session_ptr
)
->
goaway_flags
=
NGHTTP2_GOAWAY_NONE
;
(
*
session_ptr
)
->
last_stream_id
=
0
;
(
*
session_ptr
)
->
inflight_niv
=
-
1
;
if
(
server
)
{
(
*
session_ptr
)
->
server
=
1
;
side_deflate
=
NGHTTP2_HD_SIDE_RESPONSE
;
...
...
@@ -341,6 +343,7 @@ void nghttp2_session_del(nghttp2_session *session)
if
(
session
==
NULL
)
{
return
;
}
free
(
session
->
inflight_iv
);
nghttp2_inbound_frame_reset
(
session
);
nghttp2_map_each_free
(
&
session
->
streams
,
nghttp2_free_streams
,
NULL
);
nghttp2_session_ob_pq_free
(
&
session
->
ob_pq
);
...
...
@@ -923,6 +926,27 @@ static int nghttp2_session_predicate_window_update_send
return
0
;
}
/*
* This function checks SETTINGS can be sent at this time.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_TOO_MANY_INFLIGHT_SETTINGS
* There is already another in-flight SETTINGS. Note that the
* current implementation only allows 1 in-flight SETTINGS frame
* without ACK flag set.
*/
static
int
nghttp2_session_predicate_settings_send
(
nghttp2_session
*
session
,
nghttp2_frame
*
frame
)
{
if
((
frame
->
hd
.
flags
&
NGHTTP2_FLAG_ACK
)
==
0
&&
session
->
inflight_niv
!=
-
1
)
{
return
NGHTTP2_ERR_TOO_MANY_INFLIGHT_SETTINGS
;
}
return
0
;
}
/*
* Returns the maximum length of next data read. If the
* connection-level and/or stream-wise flow control are enabled, the
...
...
@@ -1102,7 +1126,12 @@ static ssize_t nghttp2_session_prep_frame(nghttp2_session *session,
return
framebuflen
;
}
break
;
case
NGHTTP2_SETTINGS
:
case
NGHTTP2_SETTINGS
:
{
int
r
;
r
=
nghttp2_session_predicate_settings_send
(
session
,
frame
);
if
(
r
!=
0
)
{
return
r
;
}
framebuflen
=
nghttp2_frame_pack_settings
(
&
session
->
aob
.
framebuf
,
&
session
->
aob
.
framebufmax
,
&
frame
->
settings
);
...
...
@@ -1110,6 +1139,7 @@ static ssize_t nghttp2_session_prep_frame(nghttp2_session *session,
return
framebuflen
;
}
break
;
}
case
NGHTTP2_PUSH_PROMISE
:
{
int
r
;
nghttp2_stream
*
stream
;
...
...
@@ -1412,9 +1442,29 @@ static int nghttp2_session_after_frame_sent(nghttp2_session *session)
}
r
=
0
;
break
;
case
NGHTTP2_SETTINGS
:
/* nothing to do */
case
NGHTTP2_SETTINGS
:
{
size_t
i
;
if
(
frame
->
hd
.
flags
&
NGHTTP2_FLAG_ACK
)
{
break
;
}
/* Only update max concurrent stream here. Applying it without
ACK is safe because we can respond to the exceeding streams
with REFUSED_STREAM and client will retry later. */
for
(
i
=
frame
->
settings
.
niv
;
i
>
0
;
--
i
)
{
if
(
frame
->
settings
.
iv
[
i
-
1
].
settings_id
==
NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS
)
{
session
->
local_settings
[
NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS
]
=
frame
->
settings
.
iv
[
i
-
1
].
value
;
break
;
}
}
assert
(
session
->
inflight_niv
==
-
1
);
session
->
inflight_iv
=
frame
->
settings
.
iv
;
session
->
inflight_niv
=
frame
->
settings
.
niv
;
frame
->
settings
.
iv
=
NULL
;
frame
->
settings
.
niv
=
0
;
break
;
}
case
NGHTTP2_PUSH_PROMISE
:
/* nothing to do */
break
;
...
...
@@ -2187,6 +2237,10 @@ static int nghttp2_disable_remote_flow_control_func(nghttp2_map_entry *entry,
/*
* Disable remote side connection-level flow control and stream-level
* flow control of existing streams.
*
* This function returns 0 if it succeeds, or one of negative error codes.
*
* The error code is always FATAL.
*/
static
int
nghttp2_session_disable_remote_flow_control
(
nghttp2_session
*
session
)
...
...
@@ -2219,6 +2273,20 @@ static void nghttp2_session_disable_local_flow_control
assert
(
rv
==
0
);
}
/*
* Apply SETTINGS values |iv| having |niv| elements to the local
* settings. SETTINGS_MAX_CONCURRENT_STREAMS is not applied here
* because it has been already applied on transmission of SETTINGS
* frame.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_HEADER_COMP
* The header table size is out of range
* NGHTTP2_ERR_NOMEM
* Out of memory
*/
int
nghttp2_session_update_local_settings
(
nghttp2_session
*
session
,
nghttp2_settings_entry
*
iv
,
size_t
niv
)
...
...
@@ -2229,12 +2297,32 @@ int nghttp2_session_update_local_settings(nghttp2_session *session,
session
->
local_settings
[
NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS
];
uint8_t
new_flow_control
=
old_flow_control
;
int32_t
new_initial_window_size
=
-
1
;
int32_t
header_table_size
=
-
1
;
uint8_t
header_table_size_seen
=
0
;
/* Use the value last seen. */
for
(
i
=
0
;
i
<
niv
;
++
i
)
{
if
(
iv
[
i
].
settings_id
==
NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE
)
{
switch
(
iv
[
i
].
settings_id
)
{
case
NGHTTP2_SETTINGS_HEADER_TABLE_SIZE
:
header_table_size_seen
=
1
;
header_table_size
=
iv
[
i
].
value
;
break
;
case
NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE
:
new_initial_window_size
=
iv
[
i
].
value
;
}
else
if
(
iv
[
i
].
settings_id
==
NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS
)
{
break
;
case
NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS
:
new_flow_control
=
iv
[
i
].
value
;
break
;
}
}
if
(
header_table_size_seen
)
{
if
(
header_table_size
<
0
||
header_table_size
>
NGHTTP2_MAX_HEADER_TABLE_SIZE
)
{
return
NGHTTP2_ERR_HEADER_COMP
;
}
rv
=
nghttp2_hd_change_table_size
(
&
session
->
hd_inflater
,
header_table_size
);
if
(
rv
!=
0
)
{
return
rv
;
}
}
if
(
!
old_flow_control
&&
!
new_flow_control
&&
new_initial_window_size
!=
-
1
)
{
...
...
@@ -2247,7 +2335,10 @@ int nghttp2_session_update_local_settings(nghttp2_session *session,
}
}
for
(
i
=
0
;
i
<
niv
;
++
i
)
{
if
(
iv
[
i
].
settings_id
>
0
&&
iv
[
i
].
settings_id
<=
NGHTTP2_SETTINGS_MAX
)
{
/* SETTINGS_MAX_CONCURRENT_STREAMS has already been applied on
transmission of the SETTINGS frame. */
if
(
iv
[
i
].
settings_id
>
0
&&
iv
[
i
].
settings_id
<=
NGHTTP2_SETTINGS_MAX
&&
iv
[
i
].
settings_id
!=
NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS
)
{
session
->
local_settings
[
iv
[
i
].
settings_id
]
=
iv
[
i
].
value
;
}
}
...
...
@@ -2259,7 +2350,8 @@ int nghttp2_session_update_local_settings(nghttp2_session *session,
}
int
nghttp2_session_on_settings_received
(
nghttp2_session
*
session
,
nghttp2_frame
*
frame
)
nghttp2_frame
*
frame
,
int
noack
)
{
int
rv
;
int
i
;
...
...
@@ -2268,6 +2360,33 @@ int nghttp2_session_on_settings_received(nghttp2_session *session,
return
nghttp2_session_handle_invalid_connection
(
session
,
frame
,
NGHTTP2_PROTOCOL_ERROR
);
}
if
(
frame
->
hd
.
flags
&
NGHTTP2_FLAG_ACK
)
{
if
(
frame
->
settings
.
niv
!=
0
)
{
return
nghttp2_session_handle_invalid_connection
(
session
,
frame
,
NGHTTP2_FRAME_TOO_LARGE
);
}
if
(
session
->
inflight_niv
==
-
1
)
{
return
nghttp2_session_handle_invalid_connection
(
session
,
frame
,
NGHTTP2_PROTOCOL_ERROR
);
}
rv
=
nghttp2_session_update_local_settings
(
session
,
session
->
inflight_iv
,
session
->
inflight_niv
);
free
(
session
->
inflight_iv
);
session
->
inflight_iv
=
NULL
;
session
->
inflight_niv
=
-
1
;
if
(
rv
!=
0
)
{
nghttp2_error_code
error_code
=
NGHTTP2_INTERNAL_ERROR
;
if
(
nghttp2_is_fatal
(
rv
))
{
return
rv
;
}
if
(
rv
==
NGHTTP2_ERR_HEADER_COMP
)
{
error_code
=
NGHTTP2_COMPRESSION_ERROR
;
}
return
nghttp2_session_handle_invalid_connection
(
session
,
frame
,
error_code
);
}
return
nghttp2_session_call_on_frame_received
(
session
,
frame
);
}
/* Check ID/value pairs and persist them if necessary. */
memset
(
check
,
0
,
sizeof
(
check
));
for
(
i
=
(
int
)
frame
->
settings
.
niv
-
1
;
i
>=
0
;
--
i
)
{
...
...
@@ -2282,6 +2401,21 @@ int nghttp2_session_on_settings_received(nghttp2_session *session,
}
check
[
entry
->
settings_id
]
=
1
;
switch
(
entry
->
settings_id
)
{
case
NGHTTP2_SETTINGS_HEADER_TABLE_SIZE
:
if
(
entry
->
value
>
NGHTTP2_MAX_HEADER_TABLE_SIZE
)
{
return
nghttp2_session_handle_invalid_connection
(
session
,
frame
,
NGHTTP2_COMPRESSION_ERROR
);
}
rv
=
nghttp2_hd_change_table_size
(
&
session
->
hd_deflater
,
entry
->
value
);
if
(
rv
!=
0
)
{
if
(
nghttp2_is_fatal
(
rv
))
{
return
rv
;
}
else
{
return
nghttp2_session_handle_invalid_connection
(
session
,
frame
,
NGHTTP2_COMPRESSION_ERROR
);
}
}
break
;
case
NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE
:
/* Update the initial window size of the all active streams */
/* Check that initial_window_size < (1u << 31) */
...
...
@@ -2306,6 +2440,8 @@ int nghttp2_session_on_settings_received(nghttp2_session *session,
if
(
session
->
remote_settings
[
entry
->
settings_id
]
==
0
)
{
rv
=
nghttp2_session_disable_remote_flow_control
(
session
);
if
(
rv
!=
0
)
{
/* FATAL */
assert
(
rv
<
NGHTTP2_ERR_FATAL
);
return
rv
;
}
}
...
...
@@ -2319,6 +2455,16 @@ int nghttp2_session_on_settings_received(nghttp2_session *session,
}
session
->
remote_settings
[
entry
->
settings_id
]
=
entry
->
value
;
}
if
(
!
noack
)
{
rv
=
nghttp2_session_add_settings
(
session
,
NGHTTP2_FLAG_ACK
,
NULL
,
0
);
if
(
rv
!=
0
)
{
if
(
nghttp2_is_fatal
(
rv
))
{
return
rv
;
}
return
nghttp2_session_handle_invalid_connection
(
session
,
frame
,
NGHTTP2_INTERNAL_ERROR
);
}
}
return
nghttp2_session_call_on_frame_received
(
session
,
frame
);
}
...
...
@@ -2401,9 +2547,9 @@ int nghttp2_session_on_ping_received(nghttp2_session *session,
return
nghttp2_session_handle_invalid_connection
(
session
,
frame
,
NGHTTP2_PROTOCOL_ERROR
);
}
if
((
frame
->
hd
.
flags
&
NGHTTP2_FLAG_
PONG
)
==
0
)
{
if
((
frame
->
hd
.
flags
&
NGHTTP2_FLAG_
ACK
)
==
0
)
{
/* Peer sent ping, so ping it back */
r
=
nghttp2_session_add_ping
(
session
,
NGHTTP2_FLAG_
PONG
,
r
=
nghttp2_session_add_ping
(
session
,
NGHTTP2_FLAG_
ACK
,
frame
->
ping
.
opaque_data
);
if
(
r
!=
0
)
{
return
r
;
...
...
@@ -2645,7 +2791,7 @@ static int nghttp2_session_process_ctrl_frame(nghttp2_session *session)
session
->
iframe
.
buf
,
session
->
iframe
.
buflen
);
if
(
r
==
0
)
{
r
=
nghttp2_session_on_settings_received
(
session
,
frame
);
r
=
nghttp2_session_on_settings_received
(
session
,
frame
,
0
/* ACK */
);
if
(
r
!=
NGHTTP2_ERR_PAUSE
)
{
nghttp2_frame_settings_free
(
&
frame
->
settings
);
}
...
...
@@ -3328,6 +3474,37 @@ int nghttp2_session_add_window_update(nghttp2_session *session, uint8_t flags,
return
r
;
}
int
nghttp2_session_add_settings
(
nghttp2_session
*
session
,
uint8_t
flags
,
const
nghttp2_settings_entry
*
iv
,
size_t
niv
)
{
nghttp2_frame
*
frame
;
nghttp2_settings_entry
*
iv_copy
;
int
r
;
if
(
!
nghttp2_iv_check
(
iv
,
niv
,
session
->
local_settings
[
NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS
]))
{
return
NGHTTP2_ERR_INVALID_ARGUMENT
;
}
frame
=
malloc
(
sizeof
(
nghttp2_frame
));
if
(
frame
==
NULL
)
{
return
NGHTTP2_ERR_NOMEM
;
}
iv_copy
=
nghttp2_frame_iv_copy
(
iv
,
niv
);
if
(
iv_copy
==
NULL
)
{
free
(
frame
);
return
NGHTTP2_ERR_NOMEM
;
}
nghttp2_frame_settings_init
(
&
frame
->
settings
,
flags
,
iv_copy
,
niv
);
r
=
nghttp2_session_add_frame
(
session
,
NGHTTP2_CAT_CTRL
,
frame
,
NULL
);
if
(
r
!=
0
)
{
/* The only expected error is fatal one */
assert
(
r
<
NGHTTP2_ERR_FATAL
);
nghttp2_frame_settings_free
(
&
frame
->
settings
);
free
(
frame
);
}
return
r
;
}
ssize_t
nghttp2_session_pack_data
(
nghttp2_session
*
session
,
uint8_t
**
buf_ptr
,
size_t
*
buflen_ptr
,
size_t
datamax
,
...
...
@@ -3481,7 +3658,7 @@ int nghttp2_session_upgrade(nghttp2_session *session,
memset
(
&
frame
.
hd
,
0
,
sizeof
(
frame
.
hd
));
frame
.
settings
.
iv
=
iv
;
frame
.
settings
.
niv
=
niv
;
rv
=
nghttp2_session_on_settings_received
(
session
,
&
frame
);
rv
=
nghttp2_session_on_settings_received
(
session
,
&
frame
,
1
/* No ACK */
);
}
else
{
rv
=
nghttp2_submit_settings
(
session
,
NGHTTP2_FLAG_NONE
,
iv
,
niv
);
}
...
...
lib/nghttp2_session.h
View file @
a46ccdb1
...
...
@@ -188,6 +188,13 @@ struct nghttp2_session {
/* Settings value of the local endpoint. */
uint32_t
local_settings
[
NGHTTP2_SETTINGS_MAX
+
1
];
/* In-flight SETTINGS values. NULL does not necessarily mean there
is no in-flight SETTINGS. */
nghttp2_settings_entry
*
inflight_iv
;
/* The number of entries in |inflight_iv|. -1 if there is no
in-flight SETTINGS. */
ssize_t
inflight_niv
;
/* Option flags. This is bitwise-OR of 0 or more of nghttp2_optmask. */
uint32_t
opt_flags
;
...
...
@@ -295,6 +302,18 @@ int nghttp2_session_add_window_update(nghttp2_session *session, uint8_t flags,
int32_t
stream_id
,
int32_t
window_size_increment
);
/*
* Adds SETTINGS frame.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory.
*/
int
nghttp2_session_add_settings
(
nghttp2_session
*
session
,
uint8_t
flags
,
const
nghttp2_settings_entry
*
iv
,
size_t
niv
);
/*
* Creates new stream in |session| with stream ID |stream_id|,
* priority |pri| and flags |flags|. NGHTTP2_FLAG_END_STREAM flag is
...
...
@@ -386,19 +405,33 @@ int nghttp2_session_on_priority_received(nghttp2_session *session,
* Called when RST_STREAM is received, assuming |frame| is properly
* initialized.
*
* This function returns 0 and never fail.
* This function returns 0 if it succeeds, or one the following
* negative error codes:
*
* TBD
*/
int
nghttp2_session_on_rst_stream_received
(
nghttp2_session
*
session
,
nghttp2_frame
*
frame
);
/*
* Called when SETTINGS is received, assuming |frame| is properly
* initialized.
* initialized. If |noack| is non-zero, SETTINGS with ACK will not be
* submitted. If |frame| has NGHTTP2_FLAG_ACK flag set, no SETTINGS
* with ACK will not be submitted regardless of |noack|.
*
* This function returns 0 and never fail.
* This function returns 0 if it succeeds, or one the following
* negative error codes:
*
* NGHTTP2_ERR_NOMEM
* Out of memory
* NGHTTP2_ERR_PAUSE
* Callback function returns NGHTTP2_ERR_PAUSE
* NGHTTP2_ERR_CALLBACK_FAILURE
* The read_callback failed
*/
int
nghttp2_session_on_settings_received
(
nghttp2_session
*
session
,
nghttp2_frame
*
frame
);
nghttp2_frame
*
frame
,
int
noack
);
/*
* Called when PUSH_PROMISE is received, assuming |frame| is properly
...
...
lib/nghttp2_submit.c
View file @
a46ccdb1
...
...
@@ -209,39 +209,7 @@ int nghttp2_submit_goaway(nghttp2_session *session, uint8_t flags,
int
nghttp2_submit_settings
(
nghttp2_session
*
session
,
uint8_t
flags
,
const
nghttp2_settings_entry
*
iv
,
size_t
niv
)
{
nghttp2_frame
*
frame
;
nghttp2_settings_entry
*
iv_copy
;
int
r
;
if
(
!
nghttp2_iv_check
(
iv
,
niv
,
session
->
local_settings
[
NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS
]))
{
return
NGHTTP2_ERR_INVALID_ARGUMENT
;
}
frame
=
malloc
(
sizeof
(
nghttp2_frame
));
if
(
frame
==
NULL
)
{
return
NGHTTP2_ERR_NOMEM
;
}
iv_copy
=
nghttp2_frame_iv_copy
(
iv
,
niv
);
if
(
iv_copy
==
NULL
)
{
free
(
frame
);
return
NGHTTP2_ERR_NOMEM
;
}
nghttp2_frame_settings_init
(
&
frame
->
settings
,
iv_copy
,
niv
);
r
=
nghttp2_session_update_local_settings
(
session
,
iv_copy
,
niv
);
if
(
r
!=
0
)
{
nghttp2_frame_settings_free
(
&
frame
->
settings
);
free
(
frame
);
return
r
;
}
r
=
nghttp2_session_add_frame
(
session
,
NGHTTP2_CAT_CTRL
,
frame
,
NULL
);
if
(
r
!=
0
)
{
/* The only expected error is fatal one */
assert
(
r
<
NGHTTP2_ERR_FATAL
);
nghttp2_frame_settings_free
(
&
frame
->
settings
);
free
(
frame
);
}
return
r
;
return
nghttp2_session_add_settings
(
session
,
NGHTTP2_FLAG_NONE
,
iv
,
niv
);
}
int
nghttp2_submit_push_promise
(
nghttp2_session
*
session
,
uint8_t
flags
,
...
...
src/app_helper.cc
View file @
a46ccdb1
...
...
@@ -80,12 +80,16 @@ namespace {
const
char
*
strsettingsid
(
int32_t
id
)
{
switch
(
id
)
{
case
NGHTTP2_SETTINGS_HEADER_TABLE_SIZE
:
return
"SETTINGS_HEADER_TABLE_SIZE"
;
case
NGHTTP2_SETTINGS_ENABLE_PUSH
:
return
"SETTINGS_ENABLE_PUSH"
;
case
NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS
:
return
"MAX_CONCURRENT_STREAMS"
;
return
"
SETTINGS_
MAX_CONCURRENT_STREAMS"
;
case
NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE
:
return
"INITIAL_WINDOW_SIZE"
;
return
"
SETTINGS_
INITIAL_WINDOW_SIZE"
;
case
NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS
:
return
"FLOW_CONTROL_OPTIONS"
;
return
"
SETTINGS_
FLOW_CONTROL_OPTIONS"
;
default:
return
"UNKNOWN"
;
}
...
...
@@ -208,14 +212,19 @@ void print_flags(const nghttp2_frame_hd& hd)
s
+=
"PRIORITY"
;
}
break
;
case
NGHTTP2_SETTINGS
:
if
(
hd
.
flags
&
NGHTTP2_FLAG_ACK
)
{
s
+=
"ACK"
;
}
break
;
case
NGHTTP2_PUSH_PROMISE
:
if
(
hd
.
flags
&
NGHTTP2_FLAG_END_PUSH_PROMISE
)
{
s
+=
"END_PUSH_PROMISE"
;
}
break
;
case
NGHTTP2_PING
:
if
(
hd
.
flags
&
NGHTTP2_FLAG_
PONG
)
{
s
+=
"
PONG
"
;
if
(
hd
.
flags
&
NGHTTP2_FLAG_
ACK
)
{
s
+=
"
ACK
"
;
}
break
;
}
...
...
tests/nghttp2_frame_test.c
View file @
a46ccdb1
...
...
@@ -223,7 +223,8 @@ void test_nghttp2_frame_pack_settings()
iv
[
2
].
settings_id
=
NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS
;
iv
[
2
].
value
=
1
;
nghttp2_frame_settings_init
(
&
frame
,
nghttp2_frame_iv_copy
(
iv
,
3
),
3
);
nghttp2_frame_settings_init
(
&
frame
,
NGHTTP2_FLAG_NONE
,
nghttp2_frame_iv_copy
(
iv
,
3
),
3
);
framelen
=
nghttp2_frame_pack_settings
(
&
buf
,
&
buflen
,
&
frame
);
CU_ASSERT
(
NGHTTP2_FRAME_HEAD_LENGTH
+
3
*
8
==
framelen
);
...
...
@@ -290,14 +291,14 @@ void test_nghttp2_frame_pack_ping(void)
size_t
buflen
=
0
;
ssize_t
framelen
;
const
uint8_t
opaque_data
[]
=
"01234567"
;
nghttp2_frame_ping_init
(
&
frame
,
NGHTTP2_FLAG_
PONG
,
opaque_data
);
nghttp2_frame_ping_init
(
&
frame
,
NGHTTP2_FLAG_
ACK
,
opaque_data
);
framelen
=
nghttp2_frame_pack_ping
(
&
buf
,
&
buflen
,
&
frame
);
CU_ASSERT
(
0
==
nghttp2_frame_unpack_ping
(
&
oframe
,
&
buf
[
0
],
NGHTTP2_FRAME_HEAD_LENGTH
,
&
buf
[
NGHTTP2_FRAME_HEAD_LENGTH
],
framelen
-
NGHTTP2_FRAME_HEAD_LENGTH
));
check_frame_header
(
8
,
NGHTTP2_PING
,
NGHTTP2_FLAG_
PONG
,
0
,
&
oframe
.
hd
);
check_frame_header
(
8
,
NGHTTP2_PING
,
NGHTTP2_FLAG_
ACK
,
0
,
&
oframe
.
hd
);
CU_ASSERT
(
memcmp
(
opaque_data
,
oframe
.
opaque_data
,
sizeof
(
opaque_data
)
-
1
)
==
0
);
free
(
buf
);
...
...
tests/nghttp2_session_test.c
View file @
a46ccdb1
...
...
@@ -1134,6 +1134,7 @@ void test_nghttp2_session_on_settings_received(void)
nghttp2_frame
frame
;
const
size_t
niv
=
5
;
nghttp2_settings_entry
iv
[
255
];
nghttp2_outbound_item
*
item
;
iv
[
0
].
settings_id
=
NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS
;
iv
[
0
].
value
=
50
;
...
...
@@ -1166,9 +1167,10 @@ void test_nghttp2_session_on_settings_received(void)
stream1
->
remote_window_size
=
16
*
1024
;
stream2
->
remote_window_size
=
-
48
*
1024
;
nghttp2_frame_settings_init
(
&
frame
.
settings
,
dup_iv
(
iv
,
niv
),
niv
);
nghttp2_frame_settings_init
(
&
frame
.
settings
,
NGHTTP2_FLAG_NONE
,
dup_iv
(
iv
,
niv
),
niv
);
CU_ASSERT
(
0
==
nghttp2_session_on_settings_received
(
session
,
&
frame
));
CU_ASSERT
(
0
==
nghttp2_session_on_settings_received
(
session
,
&
frame
,
0
));
CU_ASSERT
(
1000000009
==
session
->
remote_settings
[
NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS
]);
CU_ASSERT
(
64
*
1024
==
...
...
@@ -1181,7 +1183,7 @@ void test_nghttp2_session_on_settings_received(void)
frame
.
settings
.
iv
[
2
].
value
=
16
*
1024
;
CU_ASSERT
(
0
==
nghttp2_session_on_settings_received
(
session
,
&
frame
));
CU_ASSERT
(
0
==
nghttp2_session_on_settings_received
(
session
,
&
frame
,
0
));
CU_ASSERT
(
16
*
1024
==
stream1
->
remote_window_size
);
CU_ASSERT
(
-
48
*
1024
==
stream2
->
remote_window_size
);
...
...
@@ -1193,6 +1195,37 @@ void test_nghttp2_session_on_settings_received(void)
nghttp2_frame_settings_free
(
&
frame
.
settings
);
nghttp2_session_del
(
session
);
/* Check ACK with niv > 0 */
nghttp2_session_server_new
(
&
session
,
&
callbacks
,
NULL
);
nghttp2_frame_settings_init
(
&
frame
.
settings
,
NGHTTP2_FLAG_ACK
,
dup_iv
(
iv
,
1
),
1
);
/* Specify inflight_iv deliberately */
session
->
inflight_iv
=
frame
.
settings
.
iv
;
session
->
inflight_niv
=
frame
.
settings
.
niv
;
CU_ASSERT
(
0
==
nghttp2_session_on_settings_received
(
session
,
&
frame
,
0
));
item
=
nghttp2_session_get_next_ob_item
(
session
);
CU_ASSERT
(
item
!=
NULL
);
CU_ASSERT
(
NGHTTP2_GOAWAY
==
OB_CTRL_TYPE
(
item
));
session
->
inflight_iv
=
NULL
;
session
->
inflight_niv
=
-
1
;
nghttp2_frame_settings_free
(
&
frame
.
settings
);
nghttp2_session_del
(
session
);
/* Check ACK against no inflight SETTINGS */
nghttp2_session_server_new
(
&
session
,
&
callbacks
,
NULL
);
nghttp2_frame_settings_init
(
&
frame
.
settings
,
NGHTTP2_FLAG_ACK
,
NULL
,
0
);
CU_ASSERT
(
0
==
nghttp2_session_on_settings_received
(
session
,
&
frame
,
0
));
item
=
nghttp2_session_get_next_ob_item
(
session
);
CU_ASSERT
(
item
!=
NULL
);
CU_ASSERT
(
NGHTTP2_GOAWAY
==
OB_CTRL_TYPE
(
item
));
nghttp2_frame_settings_free
(
&
frame
.
settings
);
nghttp2_session_del
(
session
);
}
void
test_nghttp2_session_on_push_promise_received
(
void
)
...
...
@@ -1346,7 +1379,7 @@ void test_nghttp2_session_on_ping_received(void)
callbacks
.
on_invalid_frame_recv_callback
=
on_invalid_frame_recv_callback
;
nghttp2_session_client_new
(
&
session
,
&
callbacks
,
&
user_data
);
nghttp2_frame_ping_init
(
&
frame
.
ping
,
NGHTTP2_FLAG_
PONG
,
opaque_data
);
nghttp2_frame_ping_init
(
&
frame
.
ping
,
NGHTTP2_FLAG_
ACK
,
opaque_data
);
CU_ASSERT
(
0
==
nghttp2_session_on_ping_received
(
session
,
&
frame
));
CU_ASSERT
(
1
==
user_data
.
frame_recv_cb_called
);
...
...
@@ -1362,7 +1395,7 @@ void test_nghttp2_session_on_ping_received(void)
CU_ASSERT
(
2
==
user_data
.
frame_recv_cb_called
);
top
=
nghttp2_session_get_ob_pq_top
(
session
);
CU_ASSERT
(
NGHTTP2_PING
==
OB_CTRL_TYPE
(
top
));
CU_ASSERT
(
NGHTTP2_FLAG_
PONG
==
OB_CTRL
(
top
)
->
hd
.
flags
);
CU_ASSERT
(
NGHTTP2_FLAG_
ACK
==
OB_CTRL
(
top
)
->
hd
.
flags
);
CU_ASSERT
(
memcmp
(
opaque_data
,
OB_CTRL
(
top
)
->
ping
.
opaque_data
,
8
)
==
0
);
nghttp2_frame_ping_free
(
&
frame
.
ping
);
...
...
@@ -2260,6 +2293,7 @@ void test_nghttp2_submit_settings(void)
nghttp2_outbound_item
*
item
;
nghttp2_frame
*
frame
;
nghttp2_settings_entry
iv
[
5
];
nghttp2_frame
ack_frame
;
iv
[
0
].
settings_id
=
NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS
;
iv
[
0
].
value
=
5
;
...
...
@@ -2296,15 +2330,6 @@ void test_nghttp2_submit_settings(void)
/* Now sends without 5th one */
CU_ASSERT
(
0
==
nghttp2_submit_settings
(
session
,
NGHTTP2_FLAG_NONE
,
iv
,
4
));
/* Make sure that local settings are changed */
CU_ASSERT
(
50
==
session
->
local_settings
[
NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS
]);
CU_ASSERT
(
16
*
1024
==
session
->
local_settings
[
NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE
]);
CU_ASSERT
(
1
==
session
->
local_settings
[
NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS
]);
CU_ASSERT
(
0
==
session
->
local_flow_control
);
item
=
nghttp2_session_get_next_ob_item
(
session
);
CU_ASSERT
(
NGHTTP2_SETTINGS
==
OB_CTRL_TYPE
(
item
));
...
...
@@ -2323,6 +2348,20 @@ void test_nghttp2_submit_settings(void)
CU_ASSERT
(
0
==
nghttp2_session_send
(
session
));
CU_ASSERT
(
1
==
ud
.
frame_send_cb_called
);
/* Only SETTINGS_MAX_CONCURRENT_STREAMS is applied on transmission */
CU_ASSERT
(
50
==
session
->
local_settings
[
NGHTTP2_SETTINGS_MAX_CONCURRENT_STREAMS
]);
nghttp2_frame_settings_init
(
&
ack_frame
.
settings
,
NGHTTP2_FLAG_ACK
,
NULL
,
0
);
CU_ASSERT
(
0
==
nghttp2_session_on_settings_received
(
session
,
&
ack_frame
,
0
));
nghttp2_frame_settings_free
(
&
ack_frame
.
settings
);
CU_ASSERT
(
16
*
1024
==
session
->
local_settings
[
NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE
]);
CU_ASSERT
(
1
==
session
->
local_settings
[
NGHTTP2_SETTINGS_FLOW_CONTROL_OPTIONS
]);
CU_ASSERT
(
0
==
session
->
local_flow_control
);
nghttp2_session_del
(
session
);
}
...
...
@@ -2333,7 +2372,9 @@ void test_nghttp2_submit_settings_update_local_window_size(void)
nghttp2_outbound_item
*
item
;
nghttp2_settings_entry
iv
[
4
];
nghttp2_stream
*
stream
;
my_user_data
ud
;
nghttp2_frame
ack_frame
;
nghttp2_frame_settings_init
(
&
ack_frame
.
settings
,
NGHTTP2_FLAG_ACK
,
NULL
,
0
);
iv
[
0
].
settings_id
=
NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE
;
iv
[
0
].
value
=
16
*
1024
;
...
...
@@ -2342,9 +2383,9 @@ void test_nghttp2_submit_settings_update_local_window_size(void)
iv
[
1
].
value
=
1
;
memset
(
&
callbacks
,
0
,
sizeof
(
nghttp2_session_callbacks
));
callbacks
.
send_callback
=
block_count
_send_callback
;
callbacks
.
send_callback
=
null
_send_callback
;
nghttp2_session_server_new
(
&
session
,
&
callbacks
,
&
ud
);
nghttp2_session_server_new
(
&
session
,
&
callbacks
,
NULL
);
stream
=
nghttp2_session_open_stream
(
session
,
1
,
NGHTTP2_FLAG_NONE
,
NGHTTP2_PRI_DEFAULT
,
...
...
@@ -2358,6 +2399,8 @@ void test_nghttp2_submit_settings_update_local_window_size(void)
stream
->
local_flow_control
=
0
;
CU_ASSERT
(
0
==
nghttp2_submit_settings
(
session
,
NGHTTP2_FLAG_NONE
,
iv
,
1
));
CU_ASSERT
(
0
==
nghttp2_session_send
(
session
));
CU_ASSERT
(
0
==
nghttp2_session_on_settings_received
(
session
,
&
ack_frame
,
0
));
stream
=
nghttp2_session_get_stream
(
session
,
1
);
CU_ASSERT
(
0
==
stream
->
recv_window_size
);
...
...
@@ -2366,9 +2409,6 @@ void test_nghttp2_submit_settings_update_local_window_size(void)
stream
=
nghttp2_session_get_stream
(
session
,
3
);
CU_ASSERT
(
NGHTTP2_INITIAL_WINDOW_SIZE
==
stream
->
local_window_size
);
/* Setting block_count = 0 will pop first entry SETTINGS */
ud
.
block_count
=
0
;
CU_ASSERT
(
0
==
nghttp2_session_send
(
session
));
item
=
nghttp2_session_get_next_ob_item
(
session
);
CU_ASSERT
(
NGHTTP2_WINDOW_UPDATE
==
OB_CTRL_TYPE
(
item
));
CU_ASSERT
(
32768
==
OB_CTRL
(
item
)
->
window_update
.
window_size_increment
);
...
...
@@ -2376,28 +2416,35 @@ void test_nghttp2_submit_settings_update_local_window_size(void)
nghttp2_session_del
(
session
);
/* Check flow control disabled case */
nghttp2_session_server_new
(
&
session
,
&
callbacks
,
&
ud
);
nghttp2_session_server_new
(
&
session
,
&
callbacks
,
NULL
);
stream
=
nghttp2_session_open_stream
(
session
,
1
,
NGHTTP2_FLAG_NONE
,
NGHTTP2_PRI_DEFAULT
,
NGHTTP2_STREAM_OPENED
,
NULL
);
CU_ASSERT
(
0
==
nghttp2_submit_settings
(
session
,
NGHTTP2_FLAG_NONE
,
iv
,
2
));
CU_ASSERT
(
0
==
nghttp2_session_send
(
session
));
CU_ASSERT
(
0
==
nghttp2_session_on_settings_received
(
session
,
&
ack_frame
,
0
));
CU_ASSERT
(
NGHTTP2_INITIAL_WINDOW_SIZE
==
stream
->
local_window_size
);
nghttp2_session_del
(
session
);
/* Check overflow case */
iv
[
0
].
value
=
128
*
1024
;
nghttp2_session_server_new
(
&
session
,
&
callbacks
,
&
ud
);
nghttp2_session_server_new
(
&
session
,
&
callbacks
,
NULL
);
stream
=
nghttp2_session_open_stream
(
session
,
1
,
NGHTTP2_FLAG_NONE
,
NGHTTP2_PRI_DEFAULT
,
NGHTTP2_STREAM_OPENED
,
NULL
);
stream
->
local_window_size
=
NGHTTP2_MAX_WINDOW_SIZE
;
CU_ASSERT
(
0
==
nghttp2_submit_settings
(
session
,
NGHTTP2_FLAG_NONE
,
iv
,
1
));
CU_ASSERT
(
0
==
nghttp2_session_send
(
session
));
CU_ASSERT
(
0
==
nghttp2_session_on_settings_received
(
session
,
&
ack_frame
,
0
));
CU_ASSERT
(
NGHTTP2_STREAM_CLOSING
==
stream
->
state
);
nghttp2_session_del
(
session
);
nghttp2_frame_settings_free
(
&
ack_frame
.
settings
);
}
void
test_nghttp2_submit_push_promise
(
void
)
...
...
@@ -3068,8 +3115,9 @@ void test_nghttp2_session_flow_control(void)
iv
[
0
].
settings_id
=
NGHTTP2_SETTINGS_INITIAL_WINDOW_SIZE
;
iv
[
0
].
value
=
32
*
1024
;
nghttp2_frame_settings_init
(
&
settings_frame
.
settings
,
dup_iv
(
iv
,
1
),
1
);
nghttp2_session_on_settings_received
(
session
,
&
settings_frame
);
nghttp2_frame_settings_init
(
&
settings_frame
.
settings
,
NGHTTP2_FLAG_NONE
,
dup_iv
(
iv
,
1
),
1
);
nghttp2_session_on_settings_received
(
session
,
&
settings_frame
,
1
);
nghttp2_frame_settings_free
(
&
settings_frame
.
settings
);
/* Sends another 8KiB data */
...
...
@@ -3119,8 +3167,9 @@ void test_nghttp2_session_flow_control_disable_remote(void)
CU_ASSERT
(
data_size
-
NGHTTP2_INITIAL_WINDOW_SIZE
==
ud
.
data_source_length
);
/* Disable flow control entirely */
nghttp2_frame_settings_init
(
&
frame
.
settings
,
dup_iv
(
&
iv
,
1
),
1
);
nghttp2_session_on_settings_received
(
session
,
&
frame
);
nghttp2_frame_settings_init
(
&
frame
.
settings
,
NGHTTP2_FLAG_NONE
,
dup_iv
(
&
iv
,
1
),
1
);
nghttp2_session_on_settings_received
(
session
,
&
frame
,
1
);
/* Check both connection and stream-level remote_flow_control is
disabled */
...
...
@@ -3141,7 +3190,9 @@ void test_nghttp2_session_flow_control_disable_local(void)
nghttp2_session_callbacks
callbacks
;
nghttp2_stream
*
stream
;
nghttp2_settings_entry
iv
[
1
];
nghttp2_frame
ack_frame
;
nghttp2_frame_settings_init
(
&
ack_frame
.
settings
,
NGHTTP2_FLAG_ACK
,
NULL
,
0
);
memset
(
&
callbacks
,
0
,
sizeof
(
nghttp2_session_callbacks
));
callbacks
.
send_callback
=
null_send_callback
;
...
...
@@ -3155,11 +3206,15 @@ void test_nghttp2_session_flow_control_disable_local(void)
iv
[
0
].
value
=
1
;
CU_ASSERT
(
0
==
nghttp2_submit_settings
(
session
,
NGHTTP2_FLAG_NONE
,
iv
,
sizeof
(
iv
)
/
sizeof
(
iv
[
0
])));
ARRLEN
(
iv
)));
CU_ASSERT
(
0
==
nghttp2_session_send
(
session
));
CU_ASSERT
(
0
==
nghttp2_session_on_settings_received
(
session
,
&
ack_frame
,
0
));
CU_ASSERT
(
0
==
stream
->
local_flow_control
);
CU_ASSERT
(
0
==
session
->
local_flow_control
);
nghttp2_session_del
(
session
);
nghttp2_frame_settings_free
(
&
ack_frame
.
settings
);
}
void
test_nghttp2_session_flow_control_data_recv
(
void
)
...
...
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