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
9cc7f9fb
Commit
9cc7f9fb
authored
Feb 25, 2014
by
Tatsuhiro Tsujikawa
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
nghttp: Wait for pushed resources to complete
The statistics of pushed resources are also calculated.
parent
d1c1deaf
Changes
1
Hide whitespace changes
Inline
Side-by-side
Showing
1 changed file
with
112 additions
and
17 deletions
+112
-17
src/nghttp.cc
src/nghttp.cc
+112
-17
No files found.
src/nghttp.cc
View file @
9cc7f9fb
...
...
@@ -248,6 +248,7 @@ std::string strip_fragment(const char *raw_uri)
namespace
{
struct
Request
{
Headers
res_nva
;
Headers
push_req_nva
;
// URI without fragment
std
::
string
uri
;
std
::
string
status
;
...
...
@@ -261,6 +262,7 @@ struct Request {
int32_t
pri
;
// Recursion level: 0: first entity, 1: entity linked from first entity
int
level
;
// For pushed request, |uri| is empty and |u| is zero-cleared.
Request
(
const
std
::
string
&
uri
,
const
http_parser_url
&
u
,
const
nghttp2_data_provider
*
data_prd
,
int64_t
data_length
,
int32_t
pri
,
int
level
=
0
)
...
...
@@ -1149,6 +1151,29 @@ void check_response_header(nghttp2_session *session, Request* req)
}
}
// namespace
namespace
{
int
on_begin_headers_callback
(
nghttp2_session
*
session
,
const
nghttp2_frame
*
frame
,
void
*
user_data
)
{
auto
client
=
get_session
(
user_data
);
switch
(
frame
->
hd
.
type
)
{
case
NGHTTP2_PUSH_PROMISE
:
{
auto
stream_id
=
frame
->
push_promise
.
promised_stream_id
;
http_parser_url
u
;
memset
(
&
u
,
0
,
sizeof
(
u
));
// TODO Set pri and level
auto
req
=
util
::
make_unique
<
Request
>
(
""
,
u
,
nullptr
,
0
,
0
,
0
);
nghttp2_session_set_stream_user_data
(
session
,
stream_id
,
req
.
get
());
client
->
reqvec
.
push_back
(
std
::
move
(
req
));
check_stream_id
(
session
,
stream_id
,
user_data
);
break
;
}
}
return
0
;
}
}
//namespace
namespace
{
int
on_header_callback
(
nghttp2_session
*
session
,
const
nghttp2_frame
*
frame
,
...
...
@@ -1160,17 +1185,30 @@ int on_header_callback(nghttp2_session *session,
verbose_on_header_callback
(
session
,
frame
,
name
,
namelen
,
value
,
valuelen
,
user_data
);
}
if
(
frame
->
hd
.
type
!=
NGHTTP2_HEADERS
||
frame
->
headers
.
cat
!=
NGHTTP2_HCAT_RESPONSE
)
{
return
0
;
switch
(
frame
->
hd
.
type
)
{
case
NGHTTP2_HEADERS
:
{
if
(
frame
->
headers
.
cat
!=
NGHTTP2_HCAT_RESPONSE
&&
frame
->
headers
.
cat
!=
NGHTTP2_HCAT_PUSH_RESPONSE
)
{
break
;
}
auto
req
=
(
Request
*
)
nghttp2_session_get_stream_user_data
(
session
,
frame
->
hd
.
stream_id
);
if
(
!
req
)
{
break
;
}
http2
::
split_add_header
(
req
->
res_nva
,
name
,
namelen
,
value
,
valuelen
);
break
;
}
case
NGHTTP2_PUSH_PROMISE
:
{
auto
req
=
(
Request
*
)
nghttp2_session_get_stream_user_data
(
session
,
frame
->
push_promise
.
promised_stream_id
);
if
(
!
req
)
{
break
;
}
http2
::
split_add_header
(
req
->
push_req_nva
,
name
,
namelen
,
value
,
valuelen
);
break
;
}
auto
req
=
(
Request
*
)
nghttp2_session_get_stream_user_data
(
session
,
frame
->
hd
.
stream_id
);
if
(
!
req
)
{
// Server-pushed stream does not have stream user data
return
0
;
}
http2
::
split_add_header
(
req
->
res_nva
,
name
,
namelen
,
value
,
valuelen
);
return
0
;
}
}
// namespace
...
...
@@ -1179,8 +1217,13 @@ namespace {
int
on_frame_recv_callback2
(
nghttp2_session
*
session
,
const
nghttp2_frame
*
frame
,
void
*
user_data
)
{
if
(
frame
->
hd
.
type
==
NGHTTP2_HEADERS
&&
frame
->
headers
.
cat
==
NGHTTP2_HCAT_RESPONSE
)
{
auto
client
=
get_session
(
user_data
);
switch
(
frame
->
hd
.
type
)
{
case
NGHTTP2_HEADERS
:
{
if
(
frame
->
headers
.
cat
!=
NGHTTP2_HCAT_RESPONSE
&&
frame
->
headers
.
cat
!=
NGHTTP2_HCAT_PUSH_RESPONSE
)
{
break
;
}
auto
req
=
(
Request
*
)
nghttp2_session_get_stream_user_data
(
session
,
frame
->
hd
.
stream_id
);
// If this is the HTTP Upgrade with OPTIONS method to avoid POST,
...
...
@@ -1189,14 +1232,65 @@ int on_frame_recv_callback2
req
->
record_response_time
();
check_response_header
(
session
,
req
);
}
}
else
if
(
frame
->
hd
.
type
==
NGHTTP2_SETTINGS
&&
(
frame
->
hd
.
flags
&
NGHTTP2_FLAG_ACK
))
{
auto
client
=
get_session
(
user_data
);
break
;
}
case
NGHTTP2_SETTINGS
:
if
((
frame
->
hd
.
flags
&
NGHTTP2_FLAG_ACK
)
==
0
)
{
break
;
}
if
(
client
->
settings_timerev
)
{
evtimer_del
(
client
->
settings_timerev
);
event_free
(
client
->
settings_timerev
);
client
->
settings_timerev
=
nullptr
;
}
break
;
case
NGHTTP2_PUSH_PROMISE
:
{
auto
req
=
(
Request
*
)
nghttp2_session_get_stream_user_data
(
session
,
frame
->
push_promise
.
promised_stream_id
);
if
(
!
req
)
{
break
;
}
std
::
string
scheme
,
authority
,
method
,
path
;
for
(
auto
&
nv
:
req
->
push_req_nva
)
{
if
(
nv
.
first
==
":scheme"
)
{
scheme
=
nv
.
second
;
continue
;
}
if
(
nv
.
first
==
":authority"
||
nv
.
first
==
"host"
)
{
authority
=
nv
.
second
;
continue
;
}
if
(
nv
.
first
==
":method"
)
{
method
=
nv
.
second
;
continue
;
}
if
(
nv
.
first
==
":path"
)
{
path
=
nv
.
second
;
continue
;
}
}
if
(
scheme
.
empty
()
||
authority
.
empty
()
||
method
.
empty
()
||
path
.
empty
()
||
path
[
0
]
!=
'/'
)
{
nghttp2_submit_rst_stream
(
session
,
NGHTTP2_FLAG_NONE
,
frame
->
push_promise
.
promised_stream_id
,
NGHTTP2_PROTOCOL_ERROR
);
break
;
}
std
::
string
uri
=
scheme
;
uri
+=
"://"
;
uri
+=
authority
;
uri
+=
path
;
http_parser_url
u
;
if
(
http_parser_parse_url
(
uri
.
c_str
(),
uri
.
size
(),
0
,
&
u
)
!=
0
)
{
nghttp2_submit_rst_stream
(
session
,
NGHTTP2_FLAG_NONE
,
frame
->
push_promise
.
promised_stream_id
,
NGHTTP2_PROTOCOL_ERROR
);
break
;
}
req
->
uri
=
uri
;
req
->
u
=
u
;
break
;
}
}
if
(
config
.
verbose
)
{
verbose_on_frame_recv_callback
(
session
,
frame
,
user_data
);
...
...
@@ -1216,9 +1310,9 @@ int on_stream_close_callback
update_html_parser
(
client
,
(
*
itr
).
second
,
nullptr
,
0
,
1
);
(
*
itr
).
second
->
record_complete_time
();
++
client
->
complete
;
if
(
client
->
all_requests_processed
())
{
nghttp2_session_terminate_session
(
session
,
NGHTTP2_NO_ERROR
);
}
}
if
(
client
->
all_requests_processed
())
{
nghttp2_session_terminate_session
(
session
,
NGHTTP2_NO_ERROR
);
}
return
0
;
}
...
...
@@ -1554,6 +1648,7 @@ int run(char **uris, int n)
verbose_on_unknown_frame_recv_callback
;
}
callbacks
.
on_data_chunk_recv_callback
=
on_data_chunk_recv_callback
;
callbacks
.
on_begin_headers_callback
=
on_begin_headers_callback
;
callbacks
.
on_header_callback
=
on_header_callback
;
if
(
config
.
padding
)
{
callbacks
.
select_padding_callback
=
select_padding_callback
;
...
...
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