nghttpx: Use std::unique_ptr for Downstream object
This commit is contained in:
parent
500c5eea56
commit
273d9f4f7d
|
@ -38,7 +38,7 @@
|
||||||
|
|
||||||
namespace shrpx {
|
namespace shrpx {
|
||||||
|
|
||||||
Downstream::Downstream(Upstream *upstream, int stream_id, int priority)
|
Downstream::Downstream(Upstream *upstream, int32_t stream_id, int32_t priority)
|
||||||
: request_bodylen_(0),
|
: request_bodylen_(0),
|
||||||
response_bodylen_(0),
|
response_bodylen_(0),
|
||||||
upstream_(upstream),
|
upstream_(upstream),
|
||||||
|
|
|
@ -49,7 +49,7 @@ class DownstreamConnection;
|
||||||
|
|
||||||
class Downstream {
|
class Downstream {
|
||||||
public:
|
public:
|
||||||
Downstream(Upstream *upstream, int stream_id, int priority);
|
Downstream(Upstream *upstream, int32_t stream_id, int32_t priority);
|
||||||
~Downstream();
|
~Downstream();
|
||||||
void reset_upstream(Upstream *upstream);
|
void reset_upstream(Upstream *upstream);
|
||||||
Upstream* get_upstream() const;
|
Upstream* get_upstream() const;
|
||||||
|
|
|
@ -34,40 +34,53 @@ DownstreamQueue::DownstreamQueue()
|
||||||
{}
|
{}
|
||||||
|
|
||||||
DownstreamQueue::~DownstreamQueue()
|
DownstreamQueue::~DownstreamQueue()
|
||||||
|
{}
|
||||||
|
|
||||||
|
void DownstreamQueue::add_pending(std::unique_ptr<Downstream> downstream)
|
||||||
{
|
{
|
||||||
for(auto& kv : pending_downstreams_) {
|
auto stream_id = downstream->get_stream_id();
|
||||||
delete kv.second;
|
pending_downstreams_[stream_id] = std::move(downstream);
|
||||||
}
|
}
|
||||||
|
|
||||||
for(auto& kv : active_downstreams_) {
|
void DownstreamQueue::add_failure(std::unique_ptr<Downstream> downstream)
|
||||||
delete kv.second;
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto& kv : failure_downstreams_) {
|
|
||||||
delete kv.second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void DownstreamQueue::add_pending(Downstream *downstream)
|
|
||||||
{
|
{
|
||||||
pending_downstreams_[downstream->get_stream_id()] = downstream;
|
auto stream_id = downstream->get_stream_id();
|
||||||
|
failure_downstreams_[stream_id] = std::move(downstream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownstreamQueue::add_failure(Downstream *downstream)
|
void DownstreamQueue::add_active(std::unique_ptr<Downstream> downstream)
|
||||||
{
|
{
|
||||||
failure_downstreams_[downstream->get_stream_id()] = downstream;
|
auto stream_id = downstream->get_stream_id();
|
||||||
|
active_downstreams_[stream_id] = std::move(downstream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownstreamQueue::add_active(Downstream *downstream)
|
std::unique_ptr<Downstream> DownstreamQueue::remove(int32_t stream_id)
|
||||||
{
|
{
|
||||||
active_downstreams_[downstream->get_stream_id()] = downstream;
|
auto kv = pending_downstreams_.find(stream_id);
|
||||||
|
|
||||||
|
if(kv != std::end(pending_downstreams_)) {
|
||||||
|
auto downstream = std::move((*kv).second);
|
||||||
|
pending_downstreams_.erase(kv);
|
||||||
|
return downstream;
|
||||||
}
|
}
|
||||||
|
|
||||||
void DownstreamQueue::remove(Downstream *downstream)
|
kv = active_downstreams_.find(stream_id);
|
||||||
{
|
|
||||||
pending_downstreams_.erase(downstream->get_stream_id());
|
if(kv != std::end(active_downstreams_)) {
|
||||||
active_downstreams_.erase(downstream->get_stream_id());
|
auto downstream = std::move((*kv).second);
|
||||||
failure_downstreams_.erase(downstream->get_stream_id());
|
active_downstreams_.erase(kv);
|
||||||
|
return downstream;
|
||||||
|
}
|
||||||
|
|
||||||
|
kv = failure_downstreams_.find(stream_id);
|
||||||
|
|
||||||
|
if(kv != std::end(failure_downstreams_)) {
|
||||||
|
auto downstream = std::move((*kv).second);
|
||||||
|
failure_downstreams_.erase(kv);
|
||||||
|
return downstream;
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Downstream* DownstreamQueue::find(int32_t stream_id)
|
Downstream* DownstreamQueue::find(int32_t stream_id)
|
||||||
|
@ -75,25 +88,25 @@ Downstream* DownstreamQueue::find(int32_t stream_id)
|
||||||
auto kv = pending_downstreams_.find(stream_id);
|
auto kv = pending_downstreams_.find(stream_id);
|
||||||
|
|
||||||
if(kv != std::end(pending_downstreams_)) {
|
if(kv != std::end(pending_downstreams_)) {
|
||||||
return (*kv).second;
|
return (*kv).second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
kv = active_downstreams_.find(stream_id);
|
kv = active_downstreams_.find(stream_id);
|
||||||
|
|
||||||
if(kv != std::end(active_downstreams_)) {
|
if(kv != std::end(active_downstreams_)) {
|
||||||
return (*kv).second;
|
return (*kv).second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
kv = failure_downstreams_.find(stream_id);
|
kv = failure_downstreams_.find(stream_id);
|
||||||
|
|
||||||
if(kv != std::end(failure_downstreams_)) {
|
if(kv != std::end(failure_downstreams_)) {
|
||||||
return (*kv).second;
|
return (*kv).second.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
Downstream* DownstreamQueue::pop_pending()
|
std::unique_ptr<Downstream> DownstreamQueue::pop_pending()
|
||||||
{
|
{
|
||||||
auto i = std::begin(pending_downstreams_);
|
auto i = std::begin(pending_downstreams_);
|
||||||
|
|
||||||
|
@ -101,7 +114,7 @@ Downstream* DownstreamQueue::pop_pending()
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto downstream = (*i).second;
|
auto downstream = std::move((*i).second);
|
||||||
|
|
||||||
pending_downstreams_.erase(i);
|
pending_downstreams_.erase(i);
|
||||||
|
|
||||||
|
|
|
@ -30,6 +30,7 @@
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
#include <map>
|
#include <map>
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
namespace shrpx {
|
namespace shrpx {
|
||||||
|
|
||||||
|
@ -39,12 +40,13 @@ class DownstreamQueue {
|
||||||
public:
|
public:
|
||||||
DownstreamQueue();
|
DownstreamQueue();
|
||||||
~DownstreamQueue();
|
~DownstreamQueue();
|
||||||
void add_pending(Downstream *downstream);
|
void add_pending(std::unique_ptr<Downstream> downstream);
|
||||||
void add_failure(Downstream *downstream);
|
void add_failure(std::unique_ptr<Downstream> downstream);
|
||||||
void add_active(Downstream *downstream);
|
void add_active(std::unique_ptr<Downstream> downstream);
|
||||||
// Removes |downstream| from either pending_downstreams_,
|
// Removes |downstream| from either pending_downstreams_,
|
||||||
// active_downstreams_ or failure_downstreams_.
|
// active_downstreams_ or failure_downstreams_ and returns it
|
||||||
void remove(Downstream *downstream);
|
// wrapped in std::unique_ptr.
|
||||||
|
std::unique_ptr<Downstream> remove(int32_t stream_id);
|
||||||
// Finds Downstream object denoted by |stream_id| either in
|
// Finds Downstream object denoted by |stream_id| either in
|
||||||
// pending_downstreams_, active_downstreams_ or
|
// pending_downstreams_, active_downstreams_ or
|
||||||
// failure_downstreams_.
|
// failure_downstreams_.
|
||||||
|
@ -55,14 +57,14 @@ public:
|
||||||
bool pending_empty() const;
|
bool pending_empty() const;
|
||||||
// Pops first Downstream object in pending_downstreams_ and returns
|
// Pops first Downstream object in pending_downstreams_ and returns
|
||||||
// it.
|
// it.
|
||||||
Downstream* pop_pending();
|
std::unique_ptr<Downstream> pop_pending();
|
||||||
private:
|
private:
|
||||||
// Downstream objects, not processed yet
|
// Downstream objects, not processed yet
|
||||||
std::map<int32_t, Downstream*> pending_downstreams_;
|
std::map<int32_t, std::unique_ptr<Downstream>> pending_downstreams_;
|
||||||
// Downstream objects in use, consuming downstream concurrency limit
|
// Downstream objects in use, consuming downstream concurrency limit
|
||||||
std::map<int32_t, Downstream*> active_downstreams_;
|
std::map<int32_t, std::unique_ptr<Downstream>> active_downstreams_;
|
||||||
// Downstream objects, failed to connect to downstream server
|
// Downstream objects, failed to connect to downstream server
|
||||||
std::map<int32_t, Downstream*> failure_downstreams_;
|
std::map<int32_t, std::unique_ptr<Downstream>> failure_downstreams_;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace shrpx
|
} // namespace shrpx
|
||||||
|
|
|
@ -73,8 +73,7 @@ int on_stream_close_callback
|
||||||
|
|
||||||
if(downstream->get_request_state() == Downstream::CONNECT_FAIL) {
|
if(downstream->get_request_state() == Downstream::CONNECT_FAIL) {
|
||||||
upstream->remove_downstream(downstream);
|
upstream->remove_downstream(downstream);
|
||||||
|
// downstream was deleted
|
||||||
delete downstream;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -94,8 +93,7 @@ int on_stream_close_callback
|
||||||
}
|
}
|
||||||
|
|
||||||
upstream->remove_downstream(downstream);
|
upstream->remove_downstream(downstream);
|
||||||
|
// downstream was deleted
|
||||||
delete downstream;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -105,7 +103,8 @@ int on_stream_close_callback
|
||||||
// If shrpx_downstream::push_request_headers() failed, the
|
// If shrpx_downstream::push_request_headers() failed, the
|
||||||
// error is handled here.
|
// error is handled here.
|
||||||
upstream->remove_downstream(downstream);
|
upstream->remove_downstream(downstream);
|
||||||
delete downstream;
|
// downstream was deleted
|
||||||
|
|
||||||
// How to test this case? Request sufficient large download
|
// How to test this case? Request sufficient large download
|
||||||
// and make client send RST_STREAM after it gets first DATA
|
// and make client send RST_STREAM after it gets first DATA
|
||||||
// frame chunk.
|
// frame chunk.
|
||||||
|
@ -117,9 +116,8 @@ int on_stream_close_callback
|
||||||
int Http2Upstream::upgrade_upstream(HttpsUpstream *http)
|
int Http2Upstream::upgrade_upstream(HttpsUpstream *http)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
auto downstream = http->get_downstream();
|
|
||||||
|
|
||||||
auto http2_settings = downstream->get_http2_settings();
|
auto http2_settings = http->get_downstream()->get_http2_settings();
|
||||||
util::to_base64(http2_settings);
|
util::to_base64(http2_settings);
|
||||||
|
|
||||||
auto settings_payload = base64::decode(std::begin(http2_settings),
|
auto settings_payload = base64::decode(std::begin(http2_settings),
|
||||||
|
@ -136,16 +134,17 @@ int Http2Upstream::upgrade_upstream(HttpsUpstream *http)
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
pre_upstream_.reset(http);
|
pre_upstream_.reset(http);
|
||||||
http->pop_downstream();
|
auto downstream = http->pop_downstream();
|
||||||
downstream->reset_upstream(this);
|
downstream->reset_upstream(this);
|
||||||
downstream->set_stream_id(1);
|
downstream->set_stream_id(1);
|
||||||
downstream_queue_.add_active(downstream);
|
|
||||||
downstream->init_upstream_timer();
|
downstream->init_upstream_timer();
|
||||||
downstream->reset_upstream_rtimer();
|
downstream->reset_upstream_rtimer();
|
||||||
downstream->init_response_body_buf();
|
downstream->init_response_body_buf();
|
||||||
downstream->set_stream_id(1);
|
downstream->set_stream_id(1);
|
||||||
downstream->set_priority(0);
|
downstream->set_priority(0);
|
||||||
|
|
||||||
|
downstream_queue_.add_active(std::move(downstream));
|
||||||
|
|
||||||
if(LOG_ENABLED(INFO)) {
|
if(LOG_ENABLED(INFO)) {
|
||||||
ULOG(INFO, this) << "Connection upgraded to HTTP/2";
|
ULOG(INFO, this) << "Connection upgraded to HTTP/2";
|
||||||
}
|
}
|
||||||
|
@ -272,11 +271,9 @@ int on_begin_headers_callback(nghttp2_session *session,
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO Use priority 0 for now
|
// TODO Use priority 0 for now
|
||||||
auto downstream = new Downstream(upstream,
|
auto downstream = util::make_unique<Downstream>
|
||||||
frame->hd.stream_id,
|
(upstream, frame->hd.stream_id, 0);
|
||||||
0);
|
|
||||||
|
|
||||||
upstream->add_pending_downstream(downstream);
|
|
||||||
downstream->init_upstream_timer();
|
downstream->init_upstream_timer();
|
||||||
downstream->reset_upstream_rtimer();
|
downstream->reset_upstream_rtimer();
|
||||||
downstream->init_response_body_buf();
|
downstream->init_response_body_buf();
|
||||||
|
@ -286,6 +283,8 @@ int on_begin_headers_callback(nghttp2_session *session,
|
||||||
downstream->set_request_major(2);
|
downstream->set_request_major(2);
|
||||||
downstream->set_request_minor(0);
|
downstream->set_request_minor(0);
|
||||||
|
|
||||||
|
upstream->add_pending_downstream(std::move(downstream));
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -392,40 +391,41 @@ void Http2Upstream::maintain_downstream_concurrency()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
initiate_downstream(downstream);
|
initiate_downstream(std::move(downstream));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Http2Upstream::initiate_downstream(Downstream *downstream)
|
void Http2Upstream::initiate_downstream(std::unique_ptr<Downstream> downstream)
|
||||||
{
|
{
|
||||||
int rv;
|
int rv;
|
||||||
|
|
||||||
auto dconn = handler_->get_downstream_connection();
|
auto dconn = handler_->get_downstream_connection();
|
||||||
rv = dconn->attach_downstream(downstream);
|
rv = dconn->attach_downstream(downstream.get());
|
||||||
if(rv != 0) {
|
if(rv != 0) {
|
||||||
downstream_queue_.add_failure(downstream);
|
|
||||||
|
|
||||||
// downstream connection fails, send error page
|
// downstream connection fails, send error page
|
||||||
if(error_reply(downstream, 503) != 0) {
|
if(error_reply(downstream.get(), 503) != 0) {
|
||||||
rst_stream(downstream, NGHTTP2_INTERNAL_ERROR);
|
rst_stream(downstream.get(), NGHTTP2_INTERNAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
downstream->set_request_state(Downstream::CONNECT_FAIL);
|
downstream->set_request_state(Downstream::CONNECT_FAIL);
|
||||||
|
|
||||||
|
downstream_queue_.add_failure(std::move(downstream));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rv = downstream->push_request_headers();
|
rv = downstream->push_request_headers();
|
||||||
if(rv != 0) {
|
if(rv != 0) {
|
||||||
downstream_queue_.add_failure(downstream);
|
|
||||||
|
|
||||||
if(error_reply(downstream, 503) != 0) {
|
if(error_reply(downstream.get(), 503) != 0) {
|
||||||
rst_stream(downstream, NGHTTP2_INTERNAL_ERROR);
|
rst_stream(downstream.get(), NGHTTP2_INTERNAL_ERROR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
downstream_queue_.add_failure(std::move(downstream));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
downstream_queue_.add_active(downstream);
|
downstream_queue_.add_active(std::move(downstream));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -837,7 +837,8 @@ void downstream_readcb(bufferevent *bev, void *ptr)
|
||||||
// because there is no consumer now. Downstream connection is also
|
// because there is no consumer now. Downstream connection is also
|
||||||
// closed in this case.
|
// closed in this case.
|
||||||
upstream->remove_downstream(downstream);
|
upstream->remove_downstream(downstream);
|
||||||
delete downstream;
|
// downstream was deleted
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -925,7 +926,7 @@ void downstream_eventcb(bufferevent *bev, short events, void *ptr)
|
||||||
// If stream was closed already, we don't need to send reply at
|
// If stream was closed already, we don't need to send reply at
|
||||||
// the first place. We can delete downstream.
|
// the first place. We can delete downstream.
|
||||||
upstream->remove_downstream(downstream);
|
upstream->remove_downstream(downstream);
|
||||||
delete downstream;
|
// downstream was deleted
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -981,7 +982,7 @@ void downstream_eventcb(bufferevent *bev, short events, void *ptr)
|
||||||
|
|
||||||
if(downstream->get_request_state() == Downstream::STREAM_CLOSED) {
|
if(downstream->get_request_state() == Downstream::STREAM_CLOSED) {
|
||||||
upstream->remove_downstream(downstream);
|
upstream->remove_downstream(downstream);
|
||||||
delete downstream;
|
// downstream was deleted
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
@ -1169,14 +1170,15 @@ bufferevent_event_cb Http2Upstream::get_downstream_eventcb()
|
||||||
return downstream_eventcb;
|
return downstream_eventcb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void Http2Upstream::add_pending_downstream(Downstream *downstream)
|
void Http2Upstream::add_pending_downstream
|
||||||
|
(std::unique_ptr<Downstream> downstream)
|
||||||
{
|
{
|
||||||
downstream_queue_.add_pending(downstream);
|
downstream_queue_.add_pending(std::move(downstream));
|
||||||
}
|
}
|
||||||
|
|
||||||
void Http2Upstream::remove_downstream(Downstream *downstream)
|
void Http2Upstream::remove_downstream(Downstream *downstream)
|
||||||
{
|
{
|
||||||
downstream_queue_.remove(downstream);
|
downstream_queue_.remove(downstream->get_stream_id());
|
||||||
|
|
||||||
maintain_downstream_concurrency();
|
maintain_downstream_concurrency();
|
||||||
}
|
}
|
||||||
|
|
|
@ -54,7 +54,7 @@ public:
|
||||||
virtual bufferevent_data_cb get_downstream_readcb();
|
virtual bufferevent_data_cb get_downstream_readcb();
|
||||||
virtual bufferevent_data_cb get_downstream_writecb();
|
virtual bufferevent_data_cb get_downstream_writecb();
|
||||||
virtual bufferevent_event_cb get_downstream_eventcb();
|
virtual bufferevent_event_cb get_downstream_eventcb();
|
||||||
void add_pending_downstream(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);
|
Downstream* find_downstream(int32_t stream_id);
|
||||||
|
|
||||||
|
@ -83,7 +83,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 maintain_downstream_concurrency();
|
void maintain_downstream_concurrency();
|
||||||
void initiate_downstream(Downstream *downstream);
|
void initiate_downstream(std::unique_ptr<Downstream> downstream);
|
||||||
private:
|
private:
|
||||||
DownstreamQueue downstream_queue_;
|
DownstreamQueue downstream_queue_;
|
||||||
std::unique_ptr<HttpsUpstream> pre_upstream_;
|
std::unique_ptr<HttpsUpstream> pre_upstream_;
|
||||||
|
|
|
@ -50,7 +50,6 @@ const size_t OUTBUF_MAX_THRES = 16*1024;
|
||||||
HttpsUpstream::HttpsUpstream(ClientHandler *handler)
|
HttpsUpstream::HttpsUpstream(ClientHandler *handler)
|
||||||
: handler_(handler),
|
: handler_(handler),
|
||||||
current_header_length_(0),
|
current_header_length_(0),
|
||||||
downstream_(nullptr),
|
|
||||||
ioctrl_(handler->get_bev())
|
ioctrl_(handler->get_bev())
|
||||||
{
|
{
|
||||||
http_parser_init(&htp_, HTTP_REQUEST);
|
http_parser_init(&htp_, HTTP_REQUEST);
|
||||||
|
@ -58,9 +57,7 @@ HttpsUpstream::HttpsUpstream(ClientHandler *handler)
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpsUpstream::~HttpsUpstream()
|
HttpsUpstream::~HttpsUpstream()
|
||||||
{
|
{}
|
||||||
delete downstream_;
|
|
||||||
}
|
|
||||||
|
|
||||||
void HttpsUpstream::reset_current_header_length()
|
void HttpsUpstream::reset_current_header_length()
|
||||||
{
|
{
|
||||||
|
@ -76,8 +73,7 @@ int htp_msg_begin(http_parser *htp)
|
||||||
}
|
}
|
||||||
upstream->reset_current_header_length();
|
upstream->reset_current_header_length();
|
||||||
// TODO specify 0 as priority for now
|
// TODO specify 0 as priority for now
|
||||||
auto downstream = new Downstream(upstream, 0, 0);
|
upstream->attach_downstream(util::make_unique<Downstream>(upstream, 0, 0));
|
||||||
upstream->attach_downstream(downstream);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
@ -723,28 +719,25 @@ bufferevent_event_cb HttpsUpstream::get_downstream_eventcb()
|
||||||
return https_downstream_eventcb;
|
return https_downstream_eventcb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpsUpstream::attach_downstream(Downstream *downstream)
|
void HttpsUpstream::attach_downstream(std::unique_ptr<Downstream> downstream)
|
||||||
{
|
{
|
||||||
assert(!downstream_);
|
assert(!downstream_);
|
||||||
downstream_ = downstream;
|
downstream_ = std::move(downstream);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HttpsUpstream::delete_downstream()
|
void HttpsUpstream::delete_downstream()
|
||||||
{
|
{
|
||||||
delete downstream_;
|
downstream_.reset();
|
||||||
downstream_ = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Downstream* HttpsUpstream::get_downstream() const
|
Downstream* HttpsUpstream::get_downstream() const
|
||||||
{
|
{
|
||||||
return downstream_;
|
return downstream_.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
Downstream* HttpsUpstream::pop_downstream()
|
std::unique_ptr<Downstream> HttpsUpstream::pop_downstream()
|
||||||
{
|
{
|
||||||
auto downstream = downstream_;
|
return std::unique_ptr<Downstream>(downstream_.release());
|
||||||
downstream_ = nullptr;
|
|
||||||
return downstream;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
int HttpsUpstream::on_downstream_header_complete(Downstream *downstream)
|
int HttpsUpstream::on_downstream_header_complete(Downstream *downstream)
|
||||||
|
|
|
@ -29,6 +29,8 @@
|
||||||
|
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include "http-parser/http_parser.h"
|
#include "http-parser/http_parser.h"
|
||||||
|
|
||||||
#include "shrpx_upstream.h"
|
#include "shrpx_upstream.h"
|
||||||
|
@ -50,10 +52,10 @@ public:
|
||||||
virtual bufferevent_data_cb get_downstream_readcb();
|
virtual bufferevent_data_cb get_downstream_readcb();
|
||||||
virtual bufferevent_data_cb get_downstream_writecb();
|
virtual bufferevent_data_cb get_downstream_writecb();
|
||||||
virtual bufferevent_event_cb get_downstream_eventcb();
|
virtual bufferevent_event_cb get_downstream_eventcb();
|
||||||
void attach_downstream(Downstream *downstream);
|
void attach_downstream(std::unique_ptr<Downstream> downstream);
|
||||||
void delete_downstream();
|
void delete_downstream();
|
||||||
Downstream* get_downstream() const;
|
Downstream* get_downstream() const;
|
||||||
Downstream* pop_downstream();
|
std::unique_ptr<Downstream> pop_downstream();
|
||||||
int error_reply(unsigned int status_code);
|
int error_reply(unsigned int status_code);
|
||||||
|
|
||||||
virtual void pause_read(IOCtrlReason reason);
|
virtual void pause_read(IOCtrlReason reason);
|
||||||
|
@ -70,7 +72,7 @@ private:
|
||||||
ClientHandler *handler_;
|
ClientHandler *handler_;
|
||||||
http_parser htp_;
|
http_parser htp_;
|
||||||
size_t current_header_length_;
|
size_t current_header_length_;
|
||||||
Downstream *downstream_;
|
std::unique_ptr<Downstream> downstream_;
|
||||||
IOControl ioctrl_;
|
IOControl ioctrl_;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -109,7 +109,8 @@ void on_stream_close_callback
|
||||||
|
|
||||||
if(downstream->get_request_state() == Downstream::CONNECT_FAIL) {
|
if(downstream->get_request_state() == Downstream::CONNECT_FAIL) {
|
||||||
upstream->remove_downstream(downstream);
|
upstream->remove_downstream(downstream);
|
||||||
delete downstream;
|
// downstrea was deleted
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -125,7 +126,8 @@ void on_stream_close_callback
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
upstream->remove_downstream(downstream);
|
upstream->remove_downstream(downstream);
|
||||||
delete downstream;
|
// downstrea was deleted
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -134,7 +136,8 @@ void on_stream_close_callback
|
||||||
// If shrpx_downstream::push_request_headers() failed, the
|
// If shrpx_downstream::push_request_headers() failed, the
|
||||||
// error is handled here.
|
// error is handled here.
|
||||||
upstream->remove_downstream(downstream);
|
upstream->remove_downstream(downstream);
|
||||||
delete downstream;
|
// downstrea was deleted
|
||||||
|
|
||||||
// How to test this case? Request sufficient large download
|
// How to test this case? Request sufficient large download
|
||||||
// and make client send RST_STREAM after it gets first DATA
|
// and make client send RST_STREAM after it gets first DATA
|
||||||
// frame chunk.
|
// frame chunk.
|
||||||
|
@ -153,10 +156,10 @@ void on_ctrl_recv_callback
|
||||||
ULOG(INFO, upstream) << "Received upstream SYN_STREAM stream_id="
|
ULOG(INFO, upstream) << "Received upstream SYN_STREAM stream_id="
|
||||||
<< frame->syn_stream.stream_id;
|
<< frame->syn_stream.stream_id;
|
||||||
}
|
}
|
||||||
auto downstream = new Downstream(upstream,
|
|
||||||
frame->syn_stream.stream_id,
|
auto downstream = upstream->add_pending_downstream
|
||||||
frame->syn_stream.pri);
|
(frame->syn_stream.stream_id, frame->syn_stream.pri);
|
||||||
upstream->add_downstream(downstream);
|
|
||||||
downstream->init_upstream_timer();
|
downstream->init_upstream_timer();
|
||||||
downstream->reset_upstream_rtimer();
|
downstream->reset_upstream_rtimer();
|
||||||
downstream->init_response_body_buf();
|
downstream->init_response_body_buf();
|
||||||
|
@ -256,31 +259,33 @@ void SpdyUpstream::maintain_downstream_concurrency()
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
initiate_downstream(downstream);
|
initiate_downstream(std::move(downstream));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpdyUpstream::initiate_downstream(Downstream *downstream)
|
void SpdyUpstream::initiate_downstream(std::unique_ptr<Downstream> downstream)
|
||||||
{
|
{
|
||||||
auto dconn = handler_->get_downstream_connection();
|
auto dconn = handler_->get_downstream_connection();
|
||||||
int rv = dconn->attach_downstream(downstream);
|
int rv = dconn->attach_downstream(downstream.get());
|
||||||
if(rv != 0) {
|
if(rv != 0) {
|
||||||
downstream_queue_.add_failure(downstream);
|
|
||||||
|
|
||||||
// If downstream connection fails, issue RST_STREAM.
|
// If downstream connection fails, issue RST_STREAM.
|
||||||
rst_stream(downstream, SPDYLAY_INTERNAL_ERROR);
|
rst_stream(downstream.get(), SPDYLAY_INTERNAL_ERROR);
|
||||||
downstream->set_request_state(Downstream::CONNECT_FAIL);
|
downstream->set_request_state(Downstream::CONNECT_FAIL);
|
||||||
|
|
||||||
|
downstream_queue_.add_failure(std::move(downstream));
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
rv = downstream->push_request_headers();
|
rv = downstream->push_request_headers();
|
||||||
if(rv != 0) {
|
if(rv != 0) {
|
||||||
downstream_queue_.add_failure(downstream);
|
rst_stream(downstream.get(), SPDYLAY_INTERNAL_ERROR);
|
||||||
|
|
||||||
|
downstream_queue_.add_failure(std::move(downstream));
|
||||||
|
|
||||||
rst_stream(downstream, SPDYLAY_INTERNAL_ERROR);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
downstream_queue_.add_active(downstream);
|
downstream_queue_.add_active(std::move(downstream));
|
||||||
}
|
}
|
||||||
|
|
||||||
namespace {
|
namespace {
|
||||||
|
@ -566,7 +571,8 @@ void spdy_downstream_readcb(bufferevent *bev, void *ptr)
|
||||||
// because there is no consumer now. Downstream connection is also
|
// because there is no consumer now. Downstream connection is also
|
||||||
// closed in this case.
|
// closed in this case.
|
||||||
upstream->remove_downstream(downstream);
|
upstream->remove_downstream(downstream);
|
||||||
delete downstream;
|
// downstrea was deleted
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -654,7 +660,8 @@ void spdy_downstream_eventcb(bufferevent *bev, short events, void *ptr)
|
||||||
// If stream was closed already, we don't need to send reply at
|
// If stream was closed already, we don't need to send reply at
|
||||||
// the first place. We can delete downstream.
|
// the first place. We can delete downstream.
|
||||||
upstream->remove_downstream(downstream);
|
upstream->remove_downstream(downstream);
|
||||||
delete downstream;
|
// downstrea was deleted
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -709,7 +716,8 @@ void spdy_downstream_eventcb(bufferevent *bev, short events, void *ptr)
|
||||||
}
|
}
|
||||||
if(downstream->get_request_state() == Downstream::STREAM_CLOSED) {
|
if(downstream->get_request_state() == Downstream::STREAM_CLOSED) {
|
||||||
upstream->remove_downstream(downstream);
|
upstream->remove_downstream(downstream);
|
||||||
delete downstream;
|
// downstrea was deleted
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -900,14 +908,20 @@ bufferevent_event_cb SpdyUpstream::get_downstream_eventcb()
|
||||||
return spdy_downstream_eventcb;
|
return spdy_downstream_eventcb;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpdyUpstream::add_downstream(Downstream *downstream)
|
Downstream* SpdyUpstream::add_pending_downstream
|
||||||
|
(int32_t stream_id, int32_t priority)
|
||||||
{
|
{
|
||||||
downstream_queue_.add_pending(downstream);
|
auto downstream = util::make_unique<Downstream>(this, stream_id, priority);
|
||||||
|
auto res = downstream.get();
|
||||||
|
|
||||||
|
downstream_queue_.add_pending(std::move(downstream));
|
||||||
|
|
||||||
|
return res;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SpdyUpstream::remove_downstream(Downstream *downstream)
|
void SpdyUpstream::remove_downstream(Downstream *downstream)
|
||||||
{
|
{
|
||||||
downstream_queue_.remove(downstream);
|
downstream_queue_.remove(downstream->get_stream_id());
|
||||||
|
|
||||||
maintain_downstream_concurrency();
|
maintain_downstream_concurrency();
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,6 +27,8 @@
|
||||||
|
|
||||||
#include "shrpx.h"
|
#include "shrpx.h"
|
||||||
|
|
||||||
|
#include <memory>
|
||||||
|
|
||||||
#include <spdylay/spdylay.h>
|
#include <spdylay/spdylay.h>
|
||||||
|
|
||||||
#include "shrpx_upstream.h"
|
#include "shrpx_upstream.h"
|
||||||
|
@ -52,7 +54,7 @@ public:
|
||||||
virtual bufferevent_data_cb get_downstream_readcb();
|
virtual bufferevent_data_cb get_downstream_readcb();
|
||||||
virtual bufferevent_data_cb get_downstream_writecb();
|
virtual bufferevent_data_cb get_downstream_writecb();
|
||||||
virtual bufferevent_event_cb get_downstream_eventcb();
|
virtual bufferevent_event_cb get_downstream_eventcb();
|
||||||
void add_downstream(Downstream *downstream);
|
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);
|
Downstream* find_downstream(int32_t stream_id);
|
||||||
|
|
||||||
|
@ -75,7 +77,7 @@ public:
|
||||||
int handle_ign_data_chunk(size_t len);
|
int handle_ign_data_chunk(size_t len);
|
||||||
|
|
||||||
void maintain_downstream_concurrency();
|
void maintain_downstream_concurrency();
|
||||||
void initiate_downstream(Downstream *downstream);
|
void initiate_downstream(std::unique_ptr<Downstream> downstream);
|
||||||
|
|
||||||
nghttp2::util::EvbufferBuffer sendbuf;
|
nghttp2::util::EvbufferBuffer sendbuf;
|
||||||
private:
|
private:
|
||||||
|
|
Loading…
Reference in New Issue