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
27e48beb
Commit
27e48beb
authored
Oct 03, 2013
by
Tatsuhiro Tsujikawa
Browse files
Options
Browse Files
Download
Plain Diff
Merge branch 'pause-cb'
parents
f3551871
bddb4de9
Changes
6
Expand all
Hide whitespace changes
Inline
Side-by-side
Showing
6 changed files
with
412 additions
and
75 deletions
+412
-75
lib/includes/nghttp2/nghttp2.h
lib/includes/nghttp2/nghttp2.h
+62
-2
lib/nghttp2_session.c
lib/nghttp2_session.c
+215
-73
lib/nghttp2_session.h
lib/nghttp2_session.h
+1
-0
tests/main.c
tests/main.c
+1
-0
tests/nghttp2_session_test.c
tests/nghttp2_session_test.c
+132
-0
tests/nghttp2_session_test.h
tests/nghttp2_session_test.h
+1
-0
No files found.
lib/includes/nghttp2/nghttp2.h
View file @
27e48beb
...
...
@@ -258,6 +258,10 @@ typedef enum {
* Insufficient buffer size given to function.
*/
NGHTTP2_ERR_INSUFF_BUFSIZE
=
-
525
,
/**
* Callback was paused by the application
*/
NGHTTP2_ERR_PAUSE
=
-
526
,
/**
* The errors < :enum:`NGHTTP2_ERR_FATAL` mean that the library is
* under unexpected condition and cannot process any further data
...
...
@@ -827,8 +831,19 @@ typedef ssize_t (*nghttp2_recv_callback)
* argument passed in to the call to `nghttp2_session_client_new()` or
* `nghttp2_session_server_new()`.
*
* If the application uses `nghttp2_session_mem_recv()`, it can return
* :enum:`NGHTTP2_ERR_PAUSE` to make `nghttp2_session_mem_recv()`
* return without processing further input bytes. The |frame|
* parameter is retained until `nghttp2_session_continue()` is
* called. The application must retain the input bytes which was used
* to produce the |frame| parameter, because it may refer to the
* memory region included in the input bytes. The application which
* returns :enum:`NGHTTP2_ERR_PAUSE` must call
* `nghttp2_session_continue()` before `nghttp2_session_mem_recv()`.
*
* The implementation of this function must return 0 if it
* succeeds. If nonzero is returned, it is treated as fatal error and
* succeeds. It may return :enum:`NGHTTP2_ERR_PAUSE`. If the other
* nonzero value is returned, it is treated as fatal error and
* `nghttp2_session_recv()` and `nghttp2_session_send()` functions
* immediately return :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`.
*/
...
...
@@ -868,6 +883,16 @@ typedef int (*nghttp2_on_invalid_frame_recv_callback)
* third argument passed in to the call to
* `nghttp2_session_client_new()` or `nghttp2_session_server_new()`.
*
* If the application uses `nghttp2_session_mem_recv()`, it can return
* :enum:`NGHTTP2_ERR_PAUSE` to make `nghttp2_session_mem_recv()`
* return without processing further input bytes. The |frame|
* parameter is retained until `nghttp2_session_continue()` is
* called. The application must retain the input bytes which was used
* to produce the |frame| parameter, because it may refer to the
* memory region included in the input bytes. The application which
* returns :enum:`NGHTTP2_ERR_PAUSE` must call
* `nghttp2_session_continue()` before `nghttp2_session_mem_recv()`.
*
* The implementation of this function must return 0 if it
* succeeds. If nonzero is returned, it is treated as fatal error and
* `nghttp2_session_recv()` and `nghttp2_session_send()` functions
...
...
@@ -1384,17 +1409,52 @@ int nghttp2_session_recv(nghttp2_session *session);
* `nghttp2_session_recv()`.
*
* In the current implementation, this function always tries to
* processes all input data unless an error occurs.
* processes all input data unless either an error occurs or
* :enum:`NGHTTP2_ERR_PAUSE` is returned from
* :member:`nghttp2_session_callbacks.on_frame_recv_callback` or
* :member:`nghttp2_session_callbacks.on_data_chunk_recv_callback`.
* If :enum:`NGHTTP2_ERR_PAUSE` is used, the return value includes the
* number of bytes which was used to produce the data or frame for the
* callback.
*
* This function returns the number of processed bytes, or one of the
* following negative error codes:
*
* :enum:`NGHTTP2_ERR_NOMEM`
* Out of memory.
* :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`
* The callback function failed.
*/
ssize_t
nghttp2_session_mem_recv
(
nghttp2_session
*
session
,
const
uint8_t
*
in
,
size_t
inlen
);
/**
* @function
*
* Perform post-processing after `nghttp2_session_mem_recv()` was
* paused by :enum:`NGHTTP2_ERR_PAUSE` from
* :member:`nghttp2_session_callbacks.on_frame_recv_callback` or
* :member:`nghttp2_session_callbacks.on_data_chunk_recv_callback`.
*
* This function frees resources associated with paused frames. It
* may also call additional callbacks, such as
* :member:`nghttp2_session_callbacks.on_stream_close_callback`.
*
* If this function succeeds, the application can call
* `nghttp2_session_mem_recv()` again.
*
* This function returns 0 if it succeeds, or one of the following
* negative error codes:
*
*
* :enum:`NGHTTP2_ERR_NOMEM`
* Out of memory.
* :enum:`NGHTTP2_ERR_CALLBACK_FAILURE`
* The callback function failed.
*
*/
int
nghttp2_session_continue
(
nghttp2_session
*
session
);
/**
* @function
*
...
...
lib/nghttp2_session.c
View file @
27e48beb
This diff is collapsed.
Click to expand it.
lib/nghttp2_session.h
View file @
27e48beb
...
...
@@ -80,6 +80,7 @@ typedef enum {
}
nghttp2_inbound_state
;
typedef
struct
{
nghttp2_frame
frame
;
nghttp2_inbound_state
state
;
uint8_t
headbuf
[
NGHTTP2_FRAME_HEAD_LENGTH
];
/* How many bytes are filled in headbuf */
...
...
tests/main.c
View file @
27e48beb
...
...
@@ -86,6 +86,7 @@ int main(int argc, char* argv[])
test_nghttp2_session_recv_data
)
||
!
CU_add_test
(
pSuite
,
"session_recv_frame_too_large"
,
test_nghttp2_session_recv_frame_too_large
)
||
!
CU_add_test
(
pSuite
,
"session_continue"
,
test_nghttp2_session_continue
)
||
!
CU_add_test
(
pSuite
,
"session_add_frame"
,
test_nghttp2_session_add_frame
)
||
!
CU_add_test
(
pSuite
,
"session_on_request_headers_received"
,
...
...
tests/nghttp2_session_test.c
View file @
27e48beb
...
...
@@ -67,6 +67,7 @@ typedef struct {
size_t
block_count
;
int
data_chunk_recv_cb_called
;
int
data_recv_cb_called
;
const
nghttp2_frame
*
frame
;
}
my_user_data
;
static
void
scripted_data_feed_init
(
scripted_data_feed
*
df
,
...
...
@@ -135,6 +136,16 @@ static int on_frame_recv_callback(nghttp2_session *session,
return
0
;
}
static
int
pause_on_frame_recv_callback
(
nghttp2_session
*
session
,
const
nghttp2_frame
*
frame
,
void
*
user_data
)
{
my_user_data
*
ud
=
(
my_user_data
*
)
user_data
;
++
ud
->
frame_recv_cb_called
;
ud
->
frame
=
frame
;
return
NGHTTP2_ERR_PAUSE
;
}
static
int
on_invalid_frame_recv_callback
(
nghttp2_session
*
session
,
const
nghttp2_frame
*
frame
,
nghttp2_error_code
error_code
,
...
...
@@ -177,6 +188,16 @@ static int on_data_chunk_recv_callback(nghttp2_session *session,
return
0
;
}
static
int
pause_on_data_chunk_recv_callback
(
nghttp2_session
*
session
,
uint8_t
flags
,
int32_t
stream_id
,
const
uint8_t
*
data
,
size_t
len
,
void
*
user_data
)
{
my_user_data
*
ud
=
(
my_user_data
*
)
user_data
;
++
ud
->
data_chunk_recv_cb_called
;
return
NGHTTP2_ERR_PAUSE
;
}
static
int
on_data_recv_callback
(
nghttp2_session
*
session
,
uint16_t
length
,
uint8_t
flags
,
int32_t
stream_id
,
void
*
user_data
)
...
...
@@ -631,6 +652,117 @@ void test_nghttp2_session_recv_data(void)
nghttp2_session_del
(
session
);
}
void
test_nghttp2_session_continue
(
void
)
{
nghttp2_session
*
session
;
nghttp2_session_callbacks
callbacks
;
my_user_data
user_data
;
const
char
*
nv1
[]
=
{
"url"
,
"/"
,
NULL
};
const
char
*
nv2
[]
=
{
"user-agent"
,
"nghttp2/1.0.0"
,
NULL
};
uint8_t
*
framedata
=
NULL
;
size_t
framedatalen
=
0
;
ssize_t
framelen1
,
framelen2
;
ssize_t
rv
;
uint8_t
buffer
[
4096
];
size_t
buflen
;
nghttp2_frame
frame
;
nghttp2_nv
*
nva
;
ssize_t
nvlen
;
const
nghttp2_frame
*
recv_frame
;
nghttp2_nv
nvcheck
;
nghttp2_frame_hd
data_hd
;
memset
(
&
callbacks
,
0
,
sizeof
(
nghttp2_session_callbacks
));
callbacks
.
send_callback
=
null_send_callback
;
callbacks
.
on_frame_recv_callback
=
pause_on_frame_recv_callback
;
callbacks
.
on_data_chunk_recv_callback
=
pause_on_data_chunk_recv_callback
;
callbacks
.
on_data_recv_callback
=
on_data_recv_callback
;
nghttp2_session_server_new
(
&
session
,
&
callbacks
,
&
user_data
);
/* Make 2 HEADERS frames */
nvlen
=
nghttp2_nv_array_from_cstr
(
&
nva
,
nv1
);
nghttp2_frame_headers_init
(
&
frame
.
headers
,
NGHTTP2_FLAG_END_HEADERS
,
1
,
NGHTTP2_PRI_DEFAULT
,
nva
,
nvlen
);
framelen1
=
nghttp2_frame_pack_headers
(
&
framedata
,
&
framedatalen
,
&
frame
.
headers
,
&
session
->
hd_deflater
);
nghttp2_frame_headers_free
(
&
frame
.
headers
);
nghttp2_hd_end_headers
(
&
session
->
hd_deflater
);
memcpy
(
buffer
,
framedata
,
framelen1
);
nvlen
=
nghttp2_nv_array_from_cstr
(
&
nva
,
nv2
);
nghttp2_frame_headers_init
(
&
frame
.
headers
,
NGHTTP2_FLAG_END_HEADERS
,
3
,
NGHTTP2_PRI_DEFAULT
,
nva
,
nvlen
);
framelen2
=
nghttp2_frame_pack_headers
(
&
framedata
,
&
framedatalen
,
&
frame
.
headers
,
&
session
->
hd_deflater
);
nghttp2_frame_headers_free
(
&
frame
.
headers
);
nghttp2_hd_end_headers
(
&
session
->
hd_deflater
);
memcpy
(
buffer
+
framelen1
,
framedata
,
framelen2
);
buflen
=
framelen1
+
framelen2
;
/* Receive 1st HEADERS and pause */
rv
=
nghttp2_session_mem_recv
(
session
,
buffer
,
buflen
);
CU_ASSERT
(
rv
==
framelen1
);
recv_frame
=
user_data
.
frame
;
CU_ASSERT
(
NGHTTP2_HEADERS
==
recv_frame
->
hd
.
type
);
CU_ASSERT
(
framelen1
-
NGHTTP2_FRAME_HEAD_LENGTH
==
recv_frame
->
hd
.
length
);
CU_ASSERT
(
1
==
recv_frame
->
headers
.
nvlen
);
nvcheck
.
name
=
(
uint8_t
*
)
nv1
[
0
];
nvcheck
.
namelen
=
strlen
(
nv1
[
0
]);
nvcheck
.
value
=
(
uint8_t
*
)
nv1
[
1
];
nvcheck
.
valuelen
=
strlen
(
nv1
[
1
]);
CU_ASSERT
(
nghttp2_nv_equal
(
&
nvcheck
,
recv_frame
->
headers
.
nva
));
rv
=
nghttp2_session_continue
(
session
);
CU_ASSERT
(
rv
==
0
);
/* Receive 2nd HEADERS and pause */
rv
=
nghttp2_session_mem_recv
(
session
,
buffer
+
framelen1
,
buflen
-
framelen1
);
CU_ASSERT
(
rv
==
framelen2
);
recv_frame
=
user_data
.
frame
;
CU_ASSERT
(
NGHTTP2_HEADERS
==
recv_frame
->
hd
.
type
);
CU_ASSERT
(
framelen2
-
NGHTTP2_FRAME_HEAD_LENGTH
==
recv_frame
->
hd
.
length
);
CU_ASSERT
(
1
==
recv_frame
->
headers
.
nvlen
);
nvcheck
.
name
=
(
uint8_t
*
)
nv2
[
0
];
nvcheck
.
namelen
=
strlen
(
nv2
[
0
]);
nvcheck
.
value
=
(
uint8_t
*
)
nv2
[
1
];
nvcheck
.
valuelen
=
strlen
(
nv2
[
1
]);
CU_ASSERT
(
nghttp2_nv_equal
(
&
nvcheck
,
recv_frame
->
headers
.
nva
));
rv
=
nghttp2_session_continue
(
session
);
CU_ASSERT
(
rv
==
0
);
/* Receive DATA */
data_hd
.
length
=
16
;
data_hd
.
type
=
NGHTTP2_DATA
;
data_hd
.
flags
=
NGHTTP2_FLAG_NONE
;
data_hd
.
stream_id
=
1
;
nghttp2_frame_pack_frame_hd
(
buffer
,
&
data_hd
);
/* Intentionally specify larger buffer size to see pause is kicked
in. */
rv
=
nghttp2_session_mem_recv
(
session
,
buffer
,
sizeof
(
buffer
));
CU_ASSERT
(
16
+
NGHTTP2_FRAME_HEAD_LENGTH
==
rv
);
user_data
.
data_recv_cb_called
=
0
;
rv
=
nghttp2_session_continue
(
session
);
CU_ASSERT
(
rv
==
0
);
CU_ASSERT
(
1
==
user_data
.
data_recv_cb_called
);
free
(
framedata
);
nghttp2_session_del
(
session
);
}
void
test_nghttp2_session_add_frame
(
void
)
{
nghttp2_session
*
session
;
...
...
tests/nghttp2_session_test.h
View file @
27e48beb
...
...
@@ -31,6 +31,7 @@ void test_nghttp2_session_recv_invalid_frame(void);
void
test_nghttp2_session_recv_eof
(
void
);
void
test_nghttp2_session_recv_data
(
void
);
void
test_nghttp2_session_recv_frame_too_large
(
void
);
void
test_nghttp2_session_continue
(
void
);
void
test_nghttp2_session_add_frame
(
void
);
void
test_nghttp2_session_on_request_headers_received
(
void
);
void
test_nghttp2_session_on_response_headers_received
(
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