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
d46e50b1
Commit
d46e50b1
authored
Mar 12, 2015
by
Tatsuhiro Tsujikawa
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
nghttpx: Refactor DownstreamQueue to avoid expensive std::map
parent
0f87cedc
Changes
9
Hide whitespace changes
Inline
Side-by-side
Showing
9 changed files
with
240 additions
and
233 deletions
+240
-233
src/shrpx_downstream.cc
src/shrpx_downstream.cc
+38
-11
src/shrpx_downstream.h
src/shrpx_downstream.h
+23
-0
src/shrpx_downstream_queue.cc
src/shrpx_downstream_queue.cc
+50
-110
src/shrpx_downstream_queue.h
src/shrpx_downstream_queue.h
+33
-37
src/shrpx_http2_upstream.cc
src/shrpx_http2_upstream.cc
+49
-43
src/shrpx_http2_upstream.h
src/shrpx_http2_upstream.h
+3
-2
src/shrpx_spdy_upstream.cc
src/shrpx_spdy_upstream.cc
+33
-28
src/shrpx_spdy_upstream.h
src/shrpx_spdy_upstream.h
+1
-2
src/template.h
src/template.h
+10
-0
No files found.
src/shrpx_downstream.cc
View file @
d46e50b1
...
@@ -33,6 +33,7 @@
...
@@ -33,6 +33,7 @@
#include "shrpx_config.h"
#include "shrpx_config.h"
#include "shrpx_error.h"
#include "shrpx_error.h"
#include "shrpx_downstream_connection.h"
#include "shrpx_downstream_connection.h"
#include "shrpx_downstream_queue.h"
#include "util.h"
#include "util.h"
#include "http2.h"
#include "http2.h"
...
@@ -106,24 +107,27 @@ void downstream_wtimeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
...
@@ -106,24 +107,27 @@ void downstream_wtimeoutcb(struct ev_loop *loop, ev_timer *w, int revents) {
// upstream could be nullptr for unittests
// upstream could be nullptr for unittests
Downstream
::
Downstream
(
Upstream
*
upstream
,
int32_t
stream_id
,
int32_t
priority
)
Downstream
::
Downstream
(
Upstream
*
upstream
,
int32_t
stream_id
,
int32_t
priority
)
:
request_start_time_
(
std
::
chrono
::
high_resolution_clock
::
now
()),
:
dlnext
(
nullptr
),
dlprev
(
nullptr
),
request_start_time_
(
std
::
chrono
::
high_resolution_clock
::
now
()),
request_buf_
(
upstream
?
upstream
->
get_mcpool
()
:
nullptr
),
request_buf_
(
upstream
?
upstream
->
get_mcpool
()
:
nullptr
),
response_buf_
(
upstream
?
upstream
->
get_mcpool
()
:
nullptr
),
response_buf_
(
upstream
?
upstream
->
get_mcpool
()
:
nullptr
),
request_bodylen_
(
0
),
response_bodylen_
(
0
),
response_sent_bodylen_
(
0
),
request_bodylen_
(
0
),
response_bodylen_
(
0
),
response_sent_bodylen_
(
0
),
request_content_length_
(
-
1
),
response_content_length_
(
-
1
),
request_content_length_
(
-
1
),
response_content_length_
(
-
1
),
upstream_
(
upstream
),
request_headers_sum_
(
0
),
response_headers_sum_
(
0
),
upstream_
(
upstream
),
blocked_link_
(
nullptr
),
request_headers_sum_
(
0
),
request_datalen_
(
0
),
response_datalen_
(
0
),
num_retry_
(
0
),
response_headers_sum_
(
0
),
request_datalen_
(
0
),
response_datalen_
(
0
),
stream_id_
(
stream_id
),
priority_
(
priority
),
downstream_stream_id_
(
-
1
),
num_retry_
(
0
),
stream_id_
(
stream_id
),
priority_
(
priority
),
downstream_stream_id_
(
-
1
),
response_rst_stream_error_code_
(
NGHTTP2_NO_ERROR
),
response_rst_stream_error_code_
(
NGHTTP2_NO_ERROR
),
request_state_
(
INITIAL
),
request_major_
(
1
),
request_minor_
(
1
),
request_state_
(
INITIAL
),
request_major_
(
1
),
request_minor_
(
1
),
response_state_
(
INITIAL
),
response_http_status_
(
0
),
response_major_
(
1
),
response_state_
(
INITIAL
),
response_http_status_
(
0
),
response_major_
(
1
),
response_minor_
(
1
),
upgrade_request_
(
false
),
upgraded_
(
false
),
response_minor_
(
1
),
dispatch_state_
(
DISPATCH_NONE
),
http2_upgrade_seen_
(
false
),
chunked_request_
(
false
),
upgrade_request_
(
false
),
upgraded_
(
false
),
http2_upgrade_seen_
(
false
),
request_connection_close_
(
false
),
request_header_key_prev_
(
false
),
chunked_request_
(
false
),
request_connection_close_
(
false
),
request_trailer_key_prev_
(
false
),
request_http2_expect_body_
(
false
),
request_header_key_prev_
(
false
),
request_trailer_key_prev_
(
false
),
chunked_response_
(
false
),
response_connection_close_
(
false
),
request_http2_expect_body_
(
false
),
chunked_response_
(
false
),
response_header_key_prev_
(
false
),
response_trailer_key_prev_
(
false
),
response_connection_close_
(
false
),
response_header_key_prev_
(
false
),
expect_final_response_
(
false
),
request_pending_
(
false
)
{
response_trailer_key_prev_
(
false
),
expect_final_response_
(
false
),
request_pending_
(
false
)
{
ev_timer_init
(
&
upstream_rtimer_
,
&
upstream_rtimeoutcb
,
0.
,
ev_timer_init
(
&
upstream_rtimer_
,
&
upstream_rtimeoutcb
,
0.
,
get_config
()
->
stream_read_timeout
);
get_config
()
->
stream_read_timeout
);
...
@@ -148,6 +152,10 @@ Downstream::~Downstream() {
...
@@ -148,6 +152,10 @@ Downstream::~Downstream() {
DLOG
(
INFO
,
this
)
<<
"Deleting"
;
DLOG
(
INFO
,
this
)
<<
"Deleting"
;
}
}
if
(
blocked_link_
)
{
detach_blocked_link
(
blocked_link_
);
}
// check nullptr for unittest
// check nullptr for unittest
if
(
upstream_
)
{
if
(
upstream_
)
{
auto
loop
=
upstream_
->
get_client_handler
()
->
get_loop
();
auto
loop
=
upstream_
->
get_client_handler
()
->
get_loop
();
...
@@ -1176,4 +1184,23 @@ bool Downstream::request_submission_ready() const {
...
@@ -1176,4 +1184,23 @@ bool Downstream::request_submission_ready() const {
request_pending_
&&
response_state_
==
Downstream
::
INITIAL
;
request_pending_
&&
response_state_
==
Downstream
::
INITIAL
;
}
}
int
Downstream
::
get_dispatch_state
()
const
{
return
dispatch_state_
;
}
void
Downstream
::
set_dispatch_state
(
int
s
)
{
dispatch_state_
=
s
;
}
void
Downstream
::
attach_blocked_link
(
BlockedLink
*
l
)
{
assert
(
!
blocked_link_
);
l
->
downstream
=
this
;
blocked_link_
=
l
;
}
void
Downstream
::
detach_blocked_link
(
BlockedLink
*
l
)
{
assert
(
blocked_link_
);
assert
(
l
->
downstream
==
this
);
l
->
downstream
=
nullptr
;
blocked_link_
=
nullptr
;
}
}
// namespace shrpx
}
// namespace shrpx
src/shrpx_downstream.h
View file @
d46e50b1
...
@@ -48,6 +48,7 @@ namespace shrpx {
...
@@ -48,6 +48,7 @@ namespace shrpx {
class
Upstream
;
class
Upstream
;
class
DownstreamConnection
;
class
DownstreamConnection
;
struct
BlockedLink
;
class
Downstream
{
class
Downstream
{
public:
public:
...
@@ -319,11 +320,27 @@ public:
...
@@ -319,11 +320,27 @@ public:
// true if retry attempt should not be done.
// true if retry attempt should not be done.
bool
no_more_retry
()
const
;
bool
no_more_retry
()
const
;
int
get_dispatch_state
()
const
;
void
set_dispatch_state
(
int
s
);
void
attach_blocked_link
(
BlockedLink
*
l
);
void
detach_blocked_link
(
BlockedLink
*
l
);
enum
{
enum
{
EVENT_ERROR
=
0x1
,
EVENT_ERROR
=
0x1
,
EVENT_TIMEOUT
=
0x2
,
EVENT_TIMEOUT
=
0x2
,
};
};
enum
{
DISPATCH_NONE
,
DISPATCH_PENDING
,
DISPATCH_BLOCKED
,
DISPATCH_ACTIVE
,
DISPATCH_FAILURE
,
};
Downstream
*
dlnext
,
*
dlprev
;
private:
private:
Headers
request_headers_
;
Headers
request_headers_
;
Headers
response_headers_
;
Headers
response_headers_
;
...
@@ -370,6 +387,9 @@ private:
...
@@ -370,6 +387,9 @@ private:
Upstream
*
upstream_
;
Upstream
*
upstream_
;
std
::
unique_ptr
<
DownstreamConnection
>
dconn_
;
std
::
unique_ptr
<
DownstreamConnection
>
dconn_
;
// only used by HTTP/2 or SPDY upstream
BlockedLink
*
blocked_link_
;
size_t
request_headers_sum_
;
size_t
request_headers_sum_
;
size_t
response_headers_sum_
;
size_t
response_headers_sum_
;
...
@@ -396,6 +416,9 @@ private:
...
@@ -396,6 +416,9 @@ private:
int
response_major_
;
int
response_major_
;
int
response_minor_
;
int
response_minor_
;
// only used by HTTP/2 or SPDY upstream
int
dispatch_state_
;
http2
::
HeaderIndex
request_hdidx_
;
http2
::
HeaderIndex
request_hdidx_
;
http2
::
HeaderIndex
response_hdidx_
;
http2
::
HeaderIndex
response_hdidx_
;
...
...
src/shrpx_downstream_queue.cc
View file @
d46e50b1
...
@@ -39,16 +39,21 @@ DownstreamQueue::DownstreamQueue(size_t conn_max_per_host, bool unified_host)
...
@@ -39,16 +39,21 @@ DownstreamQueue::DownstreamQueue(size_t conn_max_per_host, bool unified_host)
:
conn_max_per_host
),
:
conn_max_per_host
),
unified_host_
(
unified_host
)
{}
unified_host_
(
unified_host
)
{}
DownstreamQueue
::~
DownstreamQueue
()
{}
DownstreamQueue
::~
DownstreamQueue
()
{
dlist_delete_all
(
downstreams_
);
for
(
auto
&
p
:
host_entries_
)
{
auto
&
ent
=
p
.
second
;
dlist_delete_all
(
ent
.
blocked
);
}
}
void
DownstreamQueue
::
add_pending
(
std
::
unique_ptr
<
Downstream
>
downstream
)
{
void
DownstreamQueue
::
add_pending
(
std
::
unique_ptr
<
Downstream
>
downstream
)
{
auto
stream_id
=
downstream
->
get_stream_id
(
);
downstream
->
set_dispatch_state
(
Downstream
::
DISPATCH_PENDING
);
pending_downstreams_
[
stream_id
]
=
std
::
move
(
downstream
);
downstreams_
.
append
(
downstream
.
release
()
);
}
}
void
DownstreamQueue
::
add_failure
(
std
::
unique_ptr
<
Downstream
>
downstream
)
{
void
DownstreamQueue
::
mark_failure
(
Downstream
*
downstream
)
{
auto
stream_id
=
downstream
->
get_stream_id
();
downstream
->
set_dispatch_state
(
Downstream
::
DISPATCH_FAILURE
);
failure_downstreams_
[
stream_id
]
=
std
::
move
(
downstream
);
}
}
DownstreamQueue
::
HostEntry
&
DownstreamQueue
::
HostEntry
&
...
@@ -76,19 +81,21 @@ DownstreamQueue::make_host_key(Downstream *downstream) const {
...
@@ -76,19 +81,21 @@ DownstreamQueue::make_host_key(Downstream *downstream) const {
return
make_host_key
(
downstream
->
get_request_http2_authority
());
return
make_host_key
(
downstream
->
get_request_http2_authority
());
}
}
void
DownstreamQueue
::
add_active
(
std
::
unique_ptr
<
Downstream
>
downstream
)
{
void
DownstreamQueue
::
mark_active
(
Downstream
*
downstream
)
{
auto
&
ent
=
find_host_entry
(
make_host_key
(
downstream
.
get
()
));
auto
&
ent
=
find_host_entry
(
make_host_key
(
downstream
));
++
ent
.
num_active
;
++
ent
.
num_active
;
auto
stream_id
=
downstream
->
get_stream_id
();
downstream
->
set_dispatch_state
(
Downstream
::
DISPATCH_ACTIVE
);
active_downstreams_
[
stream_id
]
=
std
::
move
(
downstream
);
}
}
void
DownstreamQueue
::
add_blocked
(
std
::
unique_ptr
<
Downstream
>
downstream
)
{
void
DownstreamQueue
::
mark_blocked
(
Downstream
*
downstream
)
{
auto
&
ent
=
find_host_entry
(
make_host_key
(
downstream
.
get
()));
auto
&
ent
=
find_host_entry
(
make_host_key
(
downstream
));
auto
stream_id
=
downstream
->
get_stream_id
();
ent
.
blocked
.
insert
(
stream_id
);
downstream
->
set_dispatch_state
(
Downstream
::
DISPATCH_BLOCKED
);
blocked_downstreams_
[
stream_id
]
=
std
::
move
(
downstream
);
auto
link
=
new
BlockedLink
{};
downstream
->
attach_blocked_link
(
link
);
ent
.
blocked
.
append
(
link
);
}
}
bool
DownstreamQueue
::
can_activate
(
const
std
::
string
&
host
)
const
{
bool
DownstreamQueue
::
can_activate
(
const
std
::
string
&
host
)
const
{
...
@@ -100,16 +107,6 @@ bool DownstreamQueue::can_activate(const std::string &host) const {
...
@@ -100,16 +107,6 @@ bool DownstreamQueue::can_activate(const std::string &host) const {
return
ent
.
num_active
<
conn_max_per_host_
;
return
ent
.
num_active
<
conn_max_per_host_
;
}
}
namespace
{
std
::
unique_ptr
<
Downstream
>
pop_downstream
(
DownstreamQueue
::
DownstreamMap
::
iterator
i
,
DownstreamQueue
::
DownstreamMap
&
downstreams
)
{
auto
downstream
=
std
::
move
((
*
i
).
second
);
downstreams
.
erase
(
i
);
return
downstream
;
}
}
// namespace
namespace
{
namespace
{
bool
remove_host_entry_if_empty
(
const
DownstreamQueue
::
HostEntry
&
ent
,
bool
remove_host_entry_if_empty
(
const
DownstreamQueue
::
HostEntry
&
ent
,
DownstreamQueue
::
HostEntryMap
&
host_entries
,
DownstreamQueue
::
HostEntryMap
&
host_entries
,
...
@@ -122,106 +119,49 @@ bool remove_host_entry_if_empty(const DownstreamQueue::HostEntry &ent,
...
@@ -122,106 +119,49 @@ bool remove_host_entry_if_empty(const DownstreamQueue::HostEntry &ent,
}
}
}
// namespace
}
// namespace
std
::
unique_ptr
<
Downstream
>
DownstreamQueue
::
pop_pending
(
int32_t
stream_id
)
{
Downstream
*
DownstreamQueue
::
remove_and_get_blocked
(
Downstream
*
downstream
)
{
auto
itr
=
pending_downstreams_
.
find
(
stream_id
);
// Delete downstream when this function returns.
if
(
itr
==
std
::
end
(
pending_downstreams_
))
{
auto
delptr
=
std
::
unique_ptr
<
Downstream
>
(
downstream
);
return
nullptr
;
}
return
pop_downstream
(
itr
,
pending_downstreams_
);
}
std
::
unique_ptr
<
Downstream
>
DownstreamQueue
::
remove_and_pop_blocked
(
int32_t
stream_id
)
{
auto
kv
=
active_downstreams_
.
find
(
stream_id
);
if
(
kv
!=
std
::
end
(
active_downstreams_
))
{
auto
downstream
=
pop_downstream
(
kv
,
active_downstreams_
);
auto
&
host
=
make_host_key
(
downstream
.
get
());
auto
&
ent
=
find_host_entry
(
host
);
--
ent
.
num_active
;
if
(
remove_host_entry_if_empty
(
ent
,
host_entries_
,
host
))
{
return
nullptr
;
}
if
(
ent
.
blocked
.
empty
()
||
ent
.
num_active
>=
conn_max_per_host_
)
{
return
nullptr
;
}
auto
next_stream_id
=
*
std
::
begin
(
ent
.
blocked
);
ent
.
blocked
.
erase
(
std
::
begin
(
ent
.
blocked
));
auto
itr
=
blocked_downstreams_
.
find
(
next_stream_id
);
assert
(
itr
!=
std
::
end
(
blocked_downstreams_
));
auto
next_downstream
=
pop_downstream
(
itr
,
blocked_downstreams_
);
remove_host_entry_if_empty
(
ent
,
host_entries_
,
host
);
return
next_downstream
;
}
kv
=
blocked_downstreams_
.
find
(
stream_id
);
if
(
kv
!=
std
::
end
(
blocked_downstreams_
))
{
auto
downstream
=
pop_downstream
(
kv
,
blocked_downstreams_
);
auto
&
host
=
make_host_key
(
downstream
.
get
());
auto
&
ent
=
find_host_entry
(
host
);
ent
.
blocked
.
erase
(
stream_id
);
remove_host_entry_if_empty
(
ent
,
host_entries_
,
host
);
if
(
downstream
->
get_dispatch_state
()
!=
Downstream
::
DISPATCH_ACTIVE
)
{
assert
(
downstream
->
get_dispatch_state
()
!=
Downstream
::
DISPATCH_NONE
);
downstreams_
.
remove
(
downstream
);
return
nullptr
;
return
nullptr
;
}
}
kv
=
pending_downstreams_
.
find
(
stream_id
);
downstreams_
.
remove
(
downstream
);
if
(
kv
!=
std
::
end
(
pending_downstreams_
))
{
pop_downstream
(
kv
,
pending_downstreams_
);
return
nullptr
;
}
kv
=
failure_downstreams_
.
find
(
stream_id
);
auto
&
host
=
make_host_key
(
downstream
);
auto
&
ent
=
find_host_entry
(
host
);
--
ent
.
num_active
;
if
(
kv
!=
std
::
end
(
failure_downstreams_
))
{
if
(
remove_host_entry_if_empty
(
ent
,
host_entries_
,
host
))
{
pop_downstream
(
kv
,
failure_downstreams_
);
return
nullptr
;
return
nullptr
;
}
}
return
nullptr
;
if
(
ent
.
num_active
>=
conn_max_per_host_
)
{
}
return
nullptr
;
Downstream
*
DownstreamQueue
::
find
(
int32_t
stream_id
)
{
auto
kv
=
active_downstreams_
.
find
(
stream_id
);
if
(
kv
!=
std
::
end
(
active_downstreams_
))
{
return
(
*
kv
).
second
.
get
();
}
kv
=
blocked_downstreams_
.
find
(
stream_id
);
if
(
kv
!=
std
::
end
(
blocked_downstreams_
))
{
return
(
*
kv
).
second
.
get
();
}
kv
=
pending_downstreams_
.
find
(
stream_id
);
if
(
kv
!=
std
::
end
(
pending_downstreams_
))
{
return
(
*
kv
).
second
.
get
();
}
}
kv
=
failure_downstreams_
.
find
(
stream_id
);
for
(
auto
link
=
ent
.
blocked
.
head
;
link
;)
{
auto
next
=
link
->
dlnext
;
if
(
kv
!=
std
::
end
(
failure_downstreams_
))
{
if
(
!
link
->
downstream
)
{
return
(
*
kv
).
second
.
get
();
ent
.
blocked
.
remove
(
link
);
link
=
next
;
continue
;
}
auto
next_downstream
=
link
->
downstream
;
next_downstream
->
detach_blocked_link
(
link
);
ent
.
blocked
.
remove
(
link
);
delete
link
;
remove_host_entry_if_empty
(
ent
,
host_entries_
,
host
);
return
next_downstream
;
}
}
return
nullptr
;
return
nullptr
;
}
}
const
DownstreamQueue
::
DownstreamMap
&
Downstream
*
DownstreamQueue
::
get_downstreams
()
const
{
DownstreamQueue
::
get_active_downstreams
()
const
{
return
downstreams_
.
head
;
return
active_downstreams_
;
}
}
}
// namespace shrpx
}
// namespace shrpx
src/shrpx_downstream_queue.h
View file @
d46e50b1
...
@@ -33,17 +33,27 @@
...
@@ -33,17 +33,27 @@
#include <set>
#include <set>
#include <memory>
#include <memory>
#include "template.h"
using
namespace
nghttp2
;
namespace
shrpx
{
namespace
shrpx
{
class
Downstream
;
class
Downstream
;
// Link entry in HostEntry.blocked and downstream because downstream
// could be deleted in anytime and we'd like to find Downstream in
// O(1). Downstream has field to link back to this object.
struct
BlockedLink
{
Downstream
*
downstream
;
BlockedLink
*
dlnext
,
*
dlprev
;
};
class
DownstreamQueue
{
class
DownstreamQueue
{
public:
public:
typedef
std
::
map
<
int32_t
,
std
::
unique_ptr
<
Downstream
>>
DownstreamMap
;
struct
HostEntry
{
struct
HostEntry
{
// Set of stream ID that blocked by conn_max_per_host_.
// Set of stream ID that blocked by conn_max_per_host_.
std
::
set
<
int32_t
>
blocked
;
DList
<
BlockedLink
>
blocked
;
// The number of connections currently made to this host.
// The number of connections currently made to this host.
size_t
num_active
;
size_t
num_active
;
HostEntry
();
HostEntry
();
...
@@ -54,52 +64,38 @@ public:
...
@@ -54,52 +64,38 @@ public:
// conn_max_per_host == 0 means no limit for downstream connection.
// conn_max_per_host == 0 means no limit for downstream connection.
DownstreamQueue
(
size_t
conn_max_per_host
=
0
,
bool
unified_host
=
true
);
DownstreamQueue
(
size_t
conn_max_per_host
=
0
,
bool
unified_host
=
true
);
~
DownstreamQueue
();
~
DownstreamQueue
();
// Add |downstream| to this queue. This is entry point for
// Downstream object.
void
add_pending
(
std
::
unique_ptr
<
Downstream
>
downstream
);
void
add_pending
(
std
::
unique_ptr
<
Downstream
>
downstream
);
void
add_failure
(
std
::
unique_ptr
<
Downstream
>
downstream
);
// Set |downstream| to failure state, which means that downstream
// Adds |downstream| to active_downstreams_, which means that
// failed to connect to backend.
// downstream connection has been started.
void
mark_failure
(
Downstream
*
downstream
);
void
add_active
(
std
::
unique_ptr
<
Downstream
>
downstream
);
// Set |downstream| to active state, which means that downstream
// Adds |downstream| to blocked_downstreams_, which means that
// connection has started.
// download connection was blocked because conn_max_per_host_ limit.
void
mark_active
(
Downstream
*
downstream
);
void
add_blocked
(
std
::
unique_ptr
<
Downstream
>
downstream
);
// Set |downstream| to blocked state, which means that download
// connection was blocked because conn_max_per_host_ limit.
void
mark_blocked
(
Downstream
*
downstream
);
// Returns true if we can make downstream connection to given
// Returns true if we can make downstream connection to given
// |host|.
// |host|.
bool
can_activate
(
const
std
::
string
&
host
)
const
;
bool
can_activate
(
const
std
::
string
&
host
)
const
;
// Removes pending Downstream object whose stream ID is |stream_id|
// Removes and frees |downstream| object. If |downstream| is in
// from pending_downstreams_ and returns it.
// Downstream::DISPATCH_ACTIVE, this function may return Downstream
std
::
unique_ptr
<
Downstream
>
pop_pending
(
int32_t
stream_id
);
// object with the same target host in Downstream::DISPATCH_BLOCKED
// Removes Downstream object whose stream ID is |stream_id| from
// if its connection is now not blocked by conn_max_per_host_ limit.
// either pending_downstreams_, active_downstreams_,
Downstream
*
remove_and_get_blocked
(
Downstream
*
downstream
);
// blocked_downstreams_ or failure_downstreams_. If a Downstream
Downstream
*
get_downstreams
()
const
;
// object is removed from active_downstreams_, this function may
// return Downstream object with the same target host in
// blocked_downstreams_ if its connection is now not blocked by
// conn_max_per_host_ limit.
std
::
unique_ptr
<
Downstream
>
remove_and_pop_blocked
(
int32_t
stream_id
);
// Finds Downstream object denoted by |stream_id| either in
// pending_downstreams_, active_downstreams_, blocked_downstreams_
// or failure_downstreams_.
Downstream
*
find
(
int32_t
stream_id
);
const
DownstreamMap
&
get_active_downstreams
()
const
;
HostEntry
&
find_host_entry
(
const
std
::
string
&
host
);
HostEntry
&
find_host_entry
(
const
std
::
string
&
host
);
const
std
::
string
&
make_host_key
(
const
std
::
string
&
host
)
const
;
const
std
::
string
&
make_host_key
(
const
std
::
string
&
host
)
const
;
const
std
::
string
&
make_host_key
(
Downstream
*
downstream
)
const
;
const
std
::
string
&
make_host_key
(
Downstream
*
downstream
)
const
;
// Maximum number of concurrent connections to the same host.
size_t
conn_max_per_host_
;
private:
private:
// Per target host structure to keep track of the number of
// Per target host structure to keep track of the number of
// connections to the same host.
// connections to the same host.
std
::
map
<
std
::
string
,
HostEntry
>
host_entries_
;
std
::
map
<
std
::
string
,
HostEntry
>
host_entries_
;
// Downstream objects, not processed yet
DList
<
Downstream
>
downstreams_
;
DownstreamMap
pending_downstreams_
;
// Maximum number of concurrent connections to the same host.
// Downstream objects, failed to connect to downstream server
size_t
conn_max_per_host_
;
DownstreamMap
failure_downstreams_
;
// Downstream objects, downstream connection started
DownstreamMap
active_downstreams_
;
// Downstream objects, blocked by conn_max_per_host_
DownstreamMap
blocked_downstreams_
;
// true if downstream host is treated as the same. Used for reverse
// true if downstream host is treated as the same. Used for reverse
// proxying.
// proxying.
bool
unified_host_
;
bool
unified_host_
;
...
...
src/shrpx_http2_upstream.cc
View file @
d46e50b1
...
@@ -55,7 +55,8 @@ int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
...
@@ -55,7 +55,8 @@ int on_stream_close_callback(nghttp2_session *session, int32_t stream_id,
<<
" is being closed"
;
<<
" is being closed"
;
}
}
auto
downstream
=
upstream
->
find_downstream
(
stream_id
);
auto
downstream
=
static_cast
<
Downstream
*>
(
nghttp2_session_get_stream_user_data
(
session
,
stream_id
));
if
(
!
downstream
)
{
if
(
!
downstream
)
{
return
0
;
return
0
;
...
@@ -161,7 +162,9 @@ int Http2Upstream::upgrade_upstream(HttpsUpstream *http) {
...
@@ -161,7 +162,9 @@ int Http2Upstream::upgrade_upstream(HttpsUpstream *http) {
downstream
->
set_request_http2_authority
(
authority
);
downstream
->
set_request_http2_authority
(
authority
);
downstream
->
set_request_http2_scheme
(
scheme
);
downstream
->
set_request_http2_scheme
(
scheme
);
downstream_queue_
.
add_active
(
std
::
move
(
downstream
));
auto
ptr
=
downstream
.
get
();
downstream_queue_
.
add_pending
(
std
::
move
(
downstream
));
downstream_queue_
.
mark_active
(
ptr
);
if
(
LOG_ENABLED
(
INFO
))
{
if
(
LOG_ENABLED
(
INFO
))
{
ULOG
(
INFO
,
this
)
<<
"Connection upgraded to HTTP/2"
;
ULOG
(
INFO
,
this
)
<<
"Connection upgraded to HTTP/2"
;
...
@@ -191,7 +194,8 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
...
@@ -191,7 +194,8 @@ int on_header_callback(nghttp2_session *session, const nghttp2_frame *frame,
return
0
;
return
0
;
}
}
auto
upstream
=
static_cast
<
Http2Upstream
*>
(
user_data
);
auto
upstream
=
static_cast
<
Http2Upstream
*>
(
user_data
);
auto
downstream
=
upstream
->
find_downstream
(
frame
->
hd
.
stream_id
);
auto
downstream
=
static_cast
<
Downstream
*>
(
nghttp2_session_get_stream_user_data
(
session
,
frame
->
hd
.
stream_id
));
if
(
!
downstream
)
{
if
(
!
downstream
)
{
return
0
;
return
0
;
}
}
...
@@ -254,6 +258,8 @@ int on_begin_headers_callback(nghttp2_session *session,
...
@@ -254,6 +258,8 @@ int on_begin_headers_callback(nghttp2_session *session,
// TODO Use priority 0 for now
// TODO Use priority 0 for now
auto
downstream
=
make_unique
<
Downstream
>
(
upstream
,
frame
->
hd
.
stream_id
,
0
);
auto
downstream
=
make_unique
<
Downstream
>
(
upstream
,
frame
->
hd
.
stream_id
,
0
);
nghttp2_session_set_stream_user_data
(
session
,
frame
->
hd
.
stream_id
,
downstream
.
get
());
downstream
->
reset_upstream_rtimer
();
downstream
->
reset_upstream_rtimer
();
...
@@ -268,9 +274,8 @@ int on_begin_headers_callback(nghttp2_session *session,
...
@@ -268,9 +274,8 @@ int on_begin_headers_callback(nghttp2_session *session,
}
}
}
// namespace
}
// namespace
namespace
{
int
Http2Upstream
::
on_request_headers
(
Downstream
*
downstream
,
int
on_request_headers
(
Http2Upstream
*
upstream
,
Downstream
*
downstream
,
const
nghttp2_frame
*
frame
)
{
nghttp2_session
*
session
,
const
nghttp2_frame
*
frame
)
{
if
(
downstream
->
get_response_state
()
==
Downstream
::
MSG_COMPLETE
)
{
if
(
downstream
->
get_response_state
()
==
Downstream
::
MSG_COMPLETE
)
{
return
0
;
return
0
;
}
}
...
@@ -282,8 +287,8 @@ int on_request_headers(Http2Upstream *upstream, Downstream *downstream,
...
@@ -282,8 +287,8 @@ int on_request_headers(Http2Upstream *upstream, Downstream *downstream,
for
(
auto
&
nv
:
nva
)
{
for
(
auto
&
nv
:
nva
)
{
ss
<<
TTY_HTTP_HD
<<
nv
.
name
<<
TTY_RST
<<
": "
<<
nv
.
value
<<
"
\n
"
;
ss
<<
TTY_HTTP_HD
<<
nv
.
name
<<
TTY_RST
<<
": "
<<
nv
.
value
<<
"
\n
"
;
}
}
ULOG
(
INFO
,
upstream
)
<<
"HTTP request headers. stream_id="
ULOG
(
INFO
,
this
)
<<
"HTTP request headers. stream_id="
<<
downstream
->
get_stream_id
()
<<
"
\n
"
<<
ss
.
str
();
<<
downstream
->
get_stream_id
()
<<
"
\n
"
<<
ss
.
str
();
}
}
if
(
get_config
()
->
http2_upstream_dump_request_header
)
{
if
(
get_config
()
->
http2_upstream_dump_request_header
)
{
...
@@ -299,7 +304,7 @@ int on_request_headers(Http2Upstream *upstream, Downstream *downstream,
...
@@ -299,7 +304,7 @@ int on_request_headers(Http2Upstream *upstream, Downstream *downstream,
// For HTTP/2 proxy, we request :authority.
// For HTTP/2 proxy, we request :authority.
if
(
method
->
value
!=
"CONNECT"
&&
get_config
()
->
http2_proxy
&&
!
authority
)
{
if
(
method
->
value
!=
"CONNECT"
&&
get_config
()
->
http2_proxy
&&
!
authority
)
{
upstream
->
rst_stream
(
downstream
,
NGHTTP2_PROTOCOL_ERROR
);
rst_stream
(
downstream
,
NGHTTP2_PROTOCOL_ERROR
);
return
0
;
return
0
;
}
}
...
@@ -321,57 +326,51 @@ int on_request_headers(Http2Upstream *upstream, Downstream *downstream,
...
@@ -321,57 +326,51 @@ int on_request_headers(Http2Upstream *upstream, Downstream *downstream,
downstream
->
set_request_state
(
Downstream
::
MSG_COMPLETE
);
downstream
->
set_request_state
(
Downstream
::
MSG_COMPLETE
);
}
}
upstream
->
start_downstream
(
downstream
);
start_downstream
(
downstream
);
return
0
;
return
0
;
}
}
}
// namespace
void
Http2Upstream
::
start_downstream
(
Downstream
*
downstream
)
{
void
Http2Upstream
::
start_downstream
(
Downstream
*
downstream
)
{
auto
next_downstream
=
downstream_queue_
.
pop_pending
(
downstream
->
get_stream_id
());
assert
(
next_downstream
);
if
(
downstream_queue_
.
can_activate
(
if
(
downstream_queue_
.
can_activate
(
downstream
->
get_request_http2_authority
()))
{
downstream
->
get_request_http2_authority
()))
{
initiate_downstream
(
std
::
move
(
next_downstream
)
);
initiate_downstream
(
downstream
);
return
;
return
;
}
}
downstream_queue_
.
add_blocked
(
std
::
move
(
next_downstream
)
);
downstream_queue_
.
mark_blocked
(
downstream
);
}
}
void
void
Http2Upstream
::
initiate_downstream
(
Downstream
*
downstream
)
{
Http2Upstream
::
initiate_downstream
(
std
::
unique_ptr
<
Downstream
>
downstream
)
{
int
rv
;
int
rv
;
rv
=
downstream
->
attach_downstream_connection
(
rv
=
downstream
->
attach_downstream_connection
(
handler_
->
get_downstream_connection
());
handler_
->
get_downstream_connection
());
if
(
rv
!=
0
)
{
if
(
rv
!=
0
)
{
// downstream connection fails, send error page
// downstream connection fails, send error page
if
(
error_reply
(
downstream
.
get
()
,
503
)
!=
0
)
{
if
(
error_reply
(
downstream
,
503
)
!=
0
)
{
rst_stream
(
downstream
.
get
()
,
NGHTTP2_INTERNAL_ERROR
);
rst_stream
(
downstream
,
NGHTTP2_INTERNAL_ERROR
);
}
}
downstream
->
set_request_state
(
Downstream
::
CONNECT_FAIL
);
downstream
->
set_request_state
(
Downstream
::
CONNECT_FAIL
);
downstream_queue_
.
add_failure
(
std
::
move
(
downstream
)
);
downstream_queue_
.
mark_failure
(
downstream
);
return
;
return
;
}
}
rv
=
downstream
->
push_request_headers
();
rv
=
downstream
->
push_request_headers
();
if
(
rv
!=
0
)
{
if
(
rv
!=
0
)
{
if
(
error_reply
(
downstream
.
get
()
,
503
)
!=
0
)
{
if
(
error_reply
(
downstream
,
503
)
!=
0
)
{
rst_stream
(
downstream
.
get
()
,
NGHTTP2_INTERNAL_ERROR
);
rst_stream
(
downstream
,
NGHTTP2_INTERNAL_ERROR
);
}
}
downstream_queue_
.
add_failure
(
std
::
move
(
downstream
)
);
downstream_queue_
.
mark_failure
(
downstream
);
return
;
return
;
}
}
downstream_queue_
.
add_active
(
std
::
move
(
downstream
)
);
downstream_queue_
.
mark_active
(
downstream
);
return
;
return
;
}
}
...
@@ -386,7 +385,8 @@ int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame,
...
@@ -386,7 +385,8 @@ int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame,
switch
(
frame
->
hd
.
type
)
{
switch
(
frame
->
hd
.
type
)
{
case
NGHTTP2_DATA
:
{
case
NGHTTP2_DATA
:
{
auto
downstream
=
upstream
->
find_downstream
(
frame
->
hd
.
stream_id
);
auto
downstream
=
static_cast
<
Downstream
*>
(
nghttp2_session_get_stream_user_data
(
session
,
frame
->
hd
.
stream_id
));
if
(
!
downstream
)
{
if
(
!
downstream
)
{
return
0
;
return
0
;
}
}
...
@@ -401,7 +401,8 @@ int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame,
...
@@ -401,7 +401,8 @@ int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame,
return
0
;
return
0
;
}
}
case
NGHTTP2_HEADERS
:
{
case
NGHTTP2_HEADERS
:
{
auto
downstream
=
upstream
->
find_downstream
(
frame
->
hd
.
stream_id
);
auto
downstream
=
static_cast
<
Downstream
*>
(
nghttp2_session_get_stream_user_data
(
session
,
frame
->
hd
.
stream_id
));
if
(
!
downstream
)
{
if
(
!
downstream
)
{
return
0
;
return
0
;
}
}
...
@@ -409,7 +410,7 @@ int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame,
...
@@ -409,7 +410,7 @@ int on_frame_recv_callback(nghttp2_session *session, const nghttp2_frame *frame,
if
(
frame
->
headers
.
cat
==
NGHTTP2_HCAT_REQUEST
)
{
if
(
frame
->
headers
.
cat
==
NGHTTP2_HCAT_REQUEST
)
{
downstream
->
reset_upstream_rtimer
();
downstream
->
reset_upstream_rtimer
();
return
on_request_headers
(
upstream
,
downstream
,
session
,
frame
);
return
upstream
->
on_request_headers
(
downstream
,
frame
);
}
}
if
(
frame
->
hd
.
flags
&
NGHTTP2_FLAG_END_STREAM
)
{
if
(
frame
->
hd
.
flags
&
NGHTTP2_FLAG_END_STREAM
)
{
...
@@ -449,7 +450,8 @@ int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
...
@@ -449,7 +450,8 @@ int on_data_chunk_recv_callback(nghttp2_session *session, uint8_t flags,
int32_t
stream_id
,
const
uint8_t
*
data
,
int32_t
stream_id
,
const
uint8_t
*
data
,
size_t
len
,
void
*
user_data
)
{
size_t
len
,
void
*
user_data
)
{
auto
upstream
=
static_cast
<
Http2Upstream
*>
(
user_data
);
auto
upstream
=
static_cast
<
Http2Upstream
*>
(
user_data
);
auto
downstream
=
upstream
->
find_downstream
(
stream_id
);
auto
downstream
=
static_cast
<
Downstream
*>
(
nghttp2_session_get_stream_user_data
(
session
,
stream_id
));
if
(
!
downstream
||
!
downstream
->
get_downstream_connection
())
{
if
(
!
downstream
||
!
downstream
->
get_downstream_connection
())
{
if
(
upstream
->
consume
(
stream_id
,
len
)
!=
0
)
{
if
(
upstream
->
consume
(
stream_id
,
len
)
!=
0
)
{
...
@@ -566,7 +568,8 @@ int on_frame_not_send_callback(nghttp2_session *session,
...
@@ -566,7 +568,8 @@ int on_frame_not_send_callback(nghttp2_session *session,
lib_error_code
!=
NGHTTP2_ERR_STREAM_CLOSED
&&
lib_error_code
!=
NGHTTP2_ERR_STREAM_CLOSED
&&
lib_error_code
!=
NGHTTP2_ERR_STREAM_CLOSING
)
{
lib_error_code
!=
NGHTTP2_ERR_STREAM_CLOSING
)
{
// To avoid stream hanging around, issue RST_STREAM.
// To avoid stream hanging around, issue RST_STREAM.
auto
downstream
=
upstream
->
find_downstream
(
frame
->
hd
.
stream_id
);
auto
downstream
=
static_cast
<
Downstream
*>
(
nghttp2_session_get_stream_user_data
(
session
,
frame
->
hd
.
stream_id
));
if
(
downstream
)
{
if
(
downstream
)
{
upstream
->
rst_stream
(
downstream
,
NGHTTP2_INTERNAL_ERROR
);
upstream
->
rst_stream
(
downstream
,
NGHTTP2_INTERNAL_ERROR
);
}
}
...
@@ -1188,18 +1191,16 @@ void Http2Upstream::remove_downstream(Downstream *downstream) {
...
@@ -1188,18 +1191,16 @@ void Http2Upstream::remove_downstream(Downstream *downstream) {
handler_
->
write_accesslog
(
downstream
);
handler_
->
write_accesslog
(
downstream
);
}
}
auto
next_downstream
=
nghttp2_session_set_stream_user_data
(
session_
,
downstream
->
get_stream_id
(),
downstream_queue_
.
remove_and_pop_blocked
(
downstream
->
get_stream_id
());
nullptr
);
auto
next_downstream
=
downstream_queue_
.
remove_and_get_blocked
(
downstream
);
if
(
next_downstream
)
{
if
(
next_downstream
)
{
initiate_downstream
(
std
::
move
(
next_downstream
)
);
initiate_downstream
(
next_downstream
);
}
}
}
}
Downstream
*
Http2Upstream
::
find_downstream
(
int32_t
stream_id
)
{
return
downstream_queue_
.
find
(
stream_id
);
}
// WARNING: Never call directly or indirectly nghttp2_session_send or
// WARNING: Never call directly or indirectly nghttp2_session_send or
// nghttp2_session_recv. These calls may delete downstream.
// nghttp2_session_recv. These calls may delete downstream.
int
Http2Upstream
::
on_downstream_header_complete
(
Downstream
*
downstream
)
{
int
Http2Upstream
::
on_downstream_header_complete
(
Downstream
*
downstream
)
{
...
@@ -1447,9 +1448,10 @@ int Http2Upstream::on_timeout(Downstream *downstream) {
...
@@ -1447,9 +1448,10 @@ int Http2Upstream::on_timeout(Downstream *downstream) {
}
}
void
Http2Upstream
::
on_handler_delete
()
{
void
Http2Upstream
::
on_handler_delete
()
{
for
(
auto
&
ent
:
downstream_queue_
.
get_active_downstreams
())
{
for
(
auto
d
=
downstream_queue_
.
get_downstreams
();
d
;
d
=
d
->
dlnext
)
{
if
(
ent
.
second
->
accesslog_ready
())
{
if
(
d
->
get_dispatch_state
()
==
Downstream
::
DISPATCH_ACTIVE
&&
handler_
->
write_accesslog
(
ent
.
second
.
get
());
d
->
accesslog_ready
())
{
handler_
->
write_accesslog
(
d
);
}
}
}
}
}
}
...
@@ -1457,8 +1459,12 @@ void Http2Upstream::on_handler_delete() {
...
@@ -1457,8 +1459,12 @@ void Http2Upstream::on_handler_delete() {
int
Http2Upstream
::
on_downstream_reset
(
bool
no_retry
)
{
int
Http2Upstream
::
on_downstream_reset
(
bool
no_retry
)
{
int
rv
;
int
rv
;
for
(
auto
&
ent
:
downstream_queue_
.
get_active_downstreams
())
{
for
(
auto
downstream
=
downstream_queue_
.
get_downstreams
();
downstream
;
auto
downstream
=
ent
.
second
.
get
();
downstream
=
downstream
->
dlnext
)
{
if
(
downstream
->
get_dispatch_state
()
!=
Downstream
::
DISPATCH_ACTIVE
)
{
continue
;
}
if
(
!
downstream
->
request_submission_ready
())
{
if
(
!
downstream
->
request_submission_ready
())
{
rst_stream
(
downstream
,
NGHTTP2_INTERNAL_ERROR
);
rst_stream
(
downstream
,
NGHTTP2_INTERNAL_ERROR
);
downstream
->
pop_downstream_connection
();
downstream
->
pop_downstream_connection
();
...
...
src/shrpx_http2_upstream.h
View file @
d46e50b1
...
@@ -62,7 +62,6 @@ public:
...
@@ -62,7 +62,6 @@ public:
void
add_pending_downstream
(
std
::
unique_ptr
<
Downstream
>
downstream
);
void
add_pending_downstream
(
std
::
unique_ptr
<
Downstream
>
downstream
);
void
remove_downstream
(
Downstream
*
downstream
);
void
remove_downstream
(
Downstream
*
downstream
);
Downstream
*
find_downstream
(
int32_t
stream_id
);
int
rst_stream
(
Downstream
*
downstream
,
uint32_t
error_code
);
int
rst_stream
(
Downstream
*
downstream
,
uint32_t
error_code
);
int
terminate_session
(
uint32_t
error_code
);
int
terminate_session
(
uint32_t
error_code
);
...
@@ -93,7 +92,7 @@ public:
...
@@ -93,7 +92,7 @@ public:
void
log_response_headers
(
Downstream
*
downstream
,
void
log_response_headers
(
Downstream
*
downstream
,
const
std
::
vector
<
nghttp2_nv
>
&
nva
)
const
;
const
std
::
vector
<
nghttp2_nv
>
&
nva
)
const
;
void
start_downstream
(
Downstream
*
downstream
);
void
start_downstream
(
Downstream
*
downstream
);
void
initiate_downstream
(
std
::
unique_ptr
<
Downstream
>
downstream
);
void
initiate_downstream
(
Downstream
*
downstream
);
void
submit_goaway
();
void
submit_goaway
();
void
check_shutdown
();
void
check_shutdown
();
...
@@ -101,6 +100,8 @@ public:
...
@@ -101,6 +100,8 @@ public:
int
prepare_push_promise
(
Downstream
*
downstream
);
int
prepare_push_promise
(
Downstream
*
downstream
);
int
submit_push_promise
(
const
std
::
string
&
path
,
Downstream
*
downstream
);
int
submit_push_promise
(
const
std
::
string
&
path
,
Downstream
*
downstream
);
int
on_request_headers
(
Downstream
*
downstream
,
const
nghttp2_frame
*
frame
);
private:
private:
// must be put before downstream_queue_
// must be put before downstream_queue_
std
::
unique_ptr
<
HttpsUpstream
>
pre_upstream_
;
std
::
unique_ptr
<
HttpsUpstream
>
pre_upstream_
;
...
...
src/shrpx_spdy_upstream.cc
View file @
d46e50b1
...
@@ -92,7 +92,8 @@ void on_stream_close_callback(spdylay_session *session, int32_t stream_id,
...
@@ -92,7 +92,8 @@ void on_stream_close_callback(spdylay_session *session, int32_t stream_id,
ULOG
(
INFO
,
upstream
)
<<
"Stream stream_id="
<<
stream_id
ULOG
(
INFO
,
upstream
)
<<
"Stream stream_id="
<<
stream_id
<<
" is being closed"
;
<<
" is being closed"
;
}
}
auto
downstream
=
upstream
->
find_downstream
(
stream_id
);
auto
downstream
=
static_cast
<
Downstream
*>
(
spdylay_session_get_stream_user_data
(
session
,
stream_id
));
if
(
!
downstream
)
{
if
(
!
downstream
)
{
return
;
return
;
}
}
...
@@ -223,41 +224,37 @@ void on_ctrl_recv_callback(spdylay_session *session, spdylay_frame_type type,
...
@@ -223,41 +224,37 @@ void on_ctrl_recv_callback(spdylay_session *session, spdylay_frame_type type,
}
// namespace
}
// namespace
void
SpdyUpstream
::
start_downstream
(
Downstream
*
downstream
)
{
void
SpdyUpstream
::
start_downstream
(
Downstream
*
downstream
)
{
auto
next_downstream
=
downstream_queue_
.
pop_pending
(
downstream
->
get_stream_id
());
assert
(
next_downstream
);
if
(
downstream_queue_
.
can_activate
(
if
(
downstream_queue_
.
can_activate
(
downstream
->
get_request_http2_authority
()))
{
downstream
->
get_request_http2_authority
()))
{
initiate_downstream
(
std
::
move
(
next_downstream
)
);
initiate_downstream
(
downstream
);
return
;
return
;
}
}
downstream_queue_
.
add_blocked
(
std
::
move
(
next_downstream
)
);
downstream_queue_
.
mark_blocked
(
downstream
);
}
}
void
SpdyUpstream
::
initiate_downstream
(
std
::
unique_ptr
<
Downstream
>
downstream
)
{
void
SpdyUpstream
::
initiate_downstream
(
Downstream
*
downstream
)
{
int
rv
=
downstream
->
attach_downstream_connection
(
int
rv
=
downstream
->
attach_downstream_connection
(
handler_
->
get_downstream_connection
());
handler_
->
get_downstream_connection
());
if
(
rv
!=
0
)
{
if
(
rv
!=
0
)
{
// If downstream connection fails, issue RST_STREAM.
// If downstream connection fails, issue RST_STREAM.
rst_stream
(
downstream
.
get
()
,
SPDYLAY_INTERNAL_ERROR
);
rst_stream
(
downstream
,
SPDYLAY_INTERNAL_ERROR
);
downstream
->
set_request_state
(
Downstream
::
CONNECT_FAIL
);
downstream
->
set_request_state
(
Downstream
::
CONNECT_FAIL
);
downstream_queue_
.
add_failure
(
std
::
move
(
downstream
)
);
downstream_queue_
.
mark_failure
(
downstream
);
return
;
return
;
}
}
rv
=
downstream
->
push_request_headers
();
rv
=
downstream
->
push_request_headers
();
if
(
rv
!=
0
)
{
if
(
rv
!=
0
)
{
rst_stream
(
downstream
.
get
()
,
SPDYLAY_INTERNAL_ERROR
);
rst_stream
(
downstream
,
SPDYLAY_INTERNAL_ERROR
);
downstream_queue_
.
add_failure
(
std
::
move
(
downstream
)
);
downstream_queue_
.
mark_failure
(
downstream
);
return
;
return
;
}
}
downstream_queue_
.
add_active
(
std
::
move
(
downstream
)
);
downstream_queue_
.
mark_active
(
downstream
);
}
}
namespace
{
namespace
{
...
@@ -265,7 +262,8 @@ void on_data_chunk_recv_callback(spdylay_session *session, uint8_t flags,
...
@@ -265,7 +262,8 @@ void on_data_chunk_recv_callback(spdylay_session *session, uint8_t flags,
int32_t
stream_id
,
const
uint8_t
*
data
,
int32_t
stream_id
,
const
uint8_t
*
data
,
size_t
len
,
void
*
user_data
)
{
size_t
len
,
void
*
user_data
)
{
auto
upstream
=
static_cast
<
SpdyUpstream
*>
(
user_data
);
auto
upstream
=
static_cast
<
SpdyUpstream
*>
(
user_data
);
auto
downstream
=
upstream
->
find_downstream
(
stream_id
);
auto
downstream
=
static_cast
<
Downstream
*>
(
spdylay_session_get_stream_user_data
(
session
,
stream_id
));
if
(
!
downstream
)
{
if
(
!
downstream
)
{
upstream
->
consume
(
stream_id
,
len
);
upstream
->
consume
(
stream_id
,
len
);
...
@@ -323,7 +321,8 @@ namespace {
...
@@ -323,7 +321,8 @@ namespace {
void
on_data_recv_callback
(
spdylay_session
*
session
,
uint8_t
flags
,
void
on_data_recv_callback
(
spdylay_session
*
session
,
uint8_t
flags
,
int32_t
stream_id
,
int32_t
length
,
void
*
user_data
)
{
int32_t
stream_id
,
int32_t
length
,
void
*
user_data
)
{
auto
upstream
=
static_cast
<
SpdyUpstream
*>
(
user_data
);
auto
upstream
=
static_cast
<
SpdyUpstream
*>
(
user_data
);
auto
downstream
=
upstream
->
find_downstream
(
stream_id
);
auto
downstream
=
static_cast
<
Downstream
*>
(
spdylay_session_get_stream_user_data
(
session
,
stream_id
));
if
(
downstream
&&
(
flags
&
SPDYLAY_DATA_FLAG_FIN
))
{
if
(
downstream
&&
(
flags
&
SPDYLAY_DATA_FLAG_FIN
))
{
if
(
!
downstream
->
validate_request_bodylen
())
{
if
(
!
downstream
->
validate_request_bodylen
())
{
upstream
->
rst_stream
(
downstream
,
SPDYLAY_PROTOCOL_ERROR
);
upstream
->
rst_stream
(
downstream
,
SPDYLAY_PROTOCOL_ERROR
);
...
@@ -351,7 +350,9 @@ void on_ctrl_not_send_callback(spdylay_session *session,
...
@@ -351,7 +350,9 @@ void on_ctrl_not_send_callback(spdylay_session *session,
error_code
!=
SPDYLAY_ERR_STREAM_CLOSING
)
{
error_code
!=
SPDYLAY_ERR_STREAM_CLOSING
)
{
// To avoid stream hanging around, issue RST_STREAM.
// To avoid stream hanging around, issue RST_STREAM.
auto
stream_id
=
frame
->
syn_reply
.
stream_id
;
auto
stream_id
=
frame
->
syn_reply
.
stream_id
;
auto
downstream
=
upstream
->
find_downstream
(
stream_id
);
// TODO Could be always nullptr
auto
downstream
=
static_cast
<
Downstream
*>
(
spdylay_session_get_stream_user_data
(
session
,
stream_id
));
if
(
downstream
)
{
if
(
downstream
)
{
upstream
->
rst_stream
(
downstream
,
SPDYLAY_INTERNAL_ERROR
);
upstream
->
rst_stream
(
downstream
,
SPDYLAY_INTERNAL_ERROR
);
}
}
...
@@ -797,6 +798,7 @@ int SpdyUpstream::error_reply(Downstream *downstream,
...
@@ -797,6 +798,7 @@ int SpdyUpstream::error_reply(Downstream *downstream,
Downstream
*
SpdyUpstream
::
add_pending_downstream
(
int32_t
stream_id
,
Downstream
*
SpdyUpstream
::
add_pending_downstream
(
int32_t
stream_id
,
int32_t
priority
)
{
int32_t
priority
)
{
auto
downstream
=
make_unique
<
Downstream
>
(
this
,
stream_id
,
priority
);
auto
downstream
=
make_unique
<
Downstream
>
(
this
,
stream_id
,
priority
);
spdylay_session_set_stream_user_data
(
session_
,
stream_id
,
downstream
.
get
());
auto
res
=
downstream
.
get
();
auto
res
=
downstream
.
get
();
downstream_queue_
.
add_pending
(
std
::
move
(
downstream
));
downstream_queue_
.
add_pending
(
std
::
move
(
downstream
));
...
@@ -809,18 +811,16 @@ void SpdyUpstream::remove_downstream(Downstream *downstream) {
...
@@ -809,18 +811,16 @@ void SpdyUpstream::remove_downstream(Downstream *downstream) {
handler_
->
write_accesslog
(
downstream
);
handler_
->
write_accesslog
(
downstream
);
}
}
auto
next_downstream
=
spdylay_session_set_stream_user_data
(
session_
,
downstream
->
get_stream_id
(),
downstream_queue_
.
remove_and_pop_blocked
(
downstream
->
get_stream_id
());
nullptr
);
auto
next_downstream
=
downstream_queue_
.
remove_and_get_blocked
(
downstream
);
if
(
next_downstream
)
{
if
(
next_downstream
)
{
initiate_downstream
(
std
::
move
(
next_downstream
)
);
initiate_downstream
(
next_downstream
);
}
}
}
}
Downstream
*
SpdyUpstream
::
find_downstream
(
int32_t
stream_id
)
{
return
downstream_queue_
.
find
(
stream_id
);
}
// WARNING: Never call directly or indirectly spdylay_session_send or
// WARNING: Never call directly or indirectly spdylay_session_send or
// spdylay_session_recv. These calls may delete downstream.
// spdylay_session_recv. These calls may delete downstream.
int
SpdyUpstream
::
on_downstream_header_complete
(
Downstream
*
downstream
)
{
int
SpdyUpstream
::
on_downstream_header_complete
(
Downstream
*
downstream
)
{
...
@@ -1026,9 +1026,10 @@ int SpdyUpstream::on_timeout(Downstream *downstream) {
...
@@ -1026,9 +1026,10 @@ int SpdyUpstream::on_timeout(Downstream *downstream) {
}
}
void
SpdyUpstream
::
on_handler_delete
()
{
void
SpdyUpstream
::
on_handler_delete
()
{
for
(
auto
&
ent
:
downstream_queue_
.
get_active_downstreams
())
{
for
(
auto
d
=
downstream_queue_
.
get_downstreams
();
d
;
d
=
d
->
dlnext
)
{
if
(
ent
.
second
->
accesslog_ready
())
{
if
(
d
->
get_dispatch_state
()
==
Downstream
::
DISPATCH_ACTIVE
&&
handler_
->
write_accesslog
(
ent
.
second
.
get
());
d
->
accesslog_ready
())
{
handler_
->
write_accesslog
(
d
);
}
}
}
}
}
}
...
@@ -1036,8 +1037,12 @@ void SpdyUpstream::on_handler_delete() {
...
@@ -1036,8 +1037,12 @@ void SpdyUpstream::on_handler_delete() {
int
SpdyUpstream
::
on_downstream_reset
(
bool
no_retry
)
{
int
SpdyUpstream
::
on_downstream_reset
(
bool
no_retry
)
{
int
rv
;
int
rv
;
for
(
auto
&
ent
:
downstream_queue_
.
get_active_downstreams
())
{
for
(
auto
downstream
=
downstream_queue_
.
get_downstreams
();
downstream
;
auto
downstream
=
ent
.
second
.
get
();
downstream
=
downstream
->
dlnext
)
{
if
(
downstream
->
get_dispatch_state
()
!=
Downstream
::
DISPATCH_ACTIVE
)
{
continue
;
}
if
(
!
downstream
->
request_submission_ready
())
{
if
(
!
downstream
->
request_submission_ready
())
{
rst_stream
(
downstream
,
SPDYLAY_INTERNAL_ERROR
);
rst_stream
(
downstream
,
SPDYLAY_INTERNAL_ERROR
);
downstream
->
pop_downstream_connection
();
downstream
->
pop_downstream_connection
();
...
...
src/shrpx_spdy_upstream.h
View file @
d46e50b1
...
@@ -58,7 +58,6 @@ public:
...
@@ -58,7 +58,6 @@ public:
virtual
int
downstream_error
(
DownstreamConnection
*
dconn
,
int
events
);
virtual
int
downstream_error
(
DownstreamConnection
*
dconn
,
int
events
);
Downstream
*
add_pending_downstream
(
int32_t
stream_id
,
int32_t
priority
);
Downstream
*
add_pending_downstream
(
int32_t
stream_id
,
int32_t
priority
);
void
remove_downstream
(
Downstream
*
downstream
);
void
remove_downstream
(
Downstream
*
downstream
);
Downstream
*
find_downstream
(
int32_t
stream_id
);
int
rst_stream
(
Downstream
*
downstream
,
int
status_code
);
int
rst_stream
(
Downstream
*
downstream
,
int
status_code
);
int
error_reply
(
Downstream
*
downstream
,
unsigned
int
status_code
);
int
error_reply
(
Downstream
*
downstream
,
unsigned
int
status_code
);
...
@@ -82,7 +81,7 @@ public:
...
@@ -82,7 +81,7 @@ public:
int
consume
(
int32_t
stream_id
,
size_t
len
);
int
consume
(
int32_t
stream_id
,
size_t
len
);
void
start_downstream
(
Downstream
*
downstream
);
void
start_downstream
(
Downstream
*
downstream
);
void
initiate_downstream
(
std
::
unique_ptr
<
Downstream
>
downstream
);
void
initiate_downstream
(
Downstream
*
downstream
);
private:
private:
// must be put before downstream_queue_
// must be put before downstream_queue_
...
...
src/template.h
View file @
d46e50b1
...
@@ -132,9 +132,19 @@ template <typename T> struct DList {
...
@@ -132,9 +132,19 @@ template <typename T> struct DList {
t
->
dlprev
=
t
->
dlnext
=
nullptr
;
t
->
dlprev
=
t
->
dlnext
=
nullptr
;
}
}
bool
empty
()
const
{
return
head
==
nullptr
;
}
T
*
head
,
*
tail
;
T
*
head
,
*
tail
;
};
};
template
<
typename
T
>
void
dlist_delete_all
(
DList
<
T
>
&
dl
)
{
for
(
auto
e
=
dl
.
head
;
e
;)
{
auto
next
=
e
->
dlnext
;
delete
e
;
e
=
next
;
}
}
}
// namespace nghttp2
}
// namespace nghttp2
#endif // TEMPLATE_H
#endif // TEMPLATE_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