HTTPS: Flow control in request chain

This commit is contained in:
Tatsuhiro Tsujikawa 2012-06-10 00:49:33 +09:00
parent bff22fd1e9
commit c2785955ca
3 changed files with 40 additions and 6 deletions

View File

@ -215,6 +215,21 @@ void Downstream::set_request_connection_close(bool f)
request_connection_close_ = f; request_connection_close_ = f;
} }
namespace {
const size_t DOWNSTREAM_OUTPUT_UPPER_THRES = 64*1024;
} // namespace
bool Downstream::get_output_buffer_full()
{
if(dconn_) {
bufferevent *bev = dconn_->get_bev();
evbuffer *output = bufferevent_get_output(bev);
return evbuffer_get_length(output) >= DOWNSTREAM_OUTPUT_UPPER_THRES;
} else {
return false;
}
}
int Downstream::push_request_headers() int Downstream::push_request_headers()
{ {
bool xff_found = false; bool xff_found = false;
@ -281,6 +296,10 @@ int Downstream::push_upload_data_chunk(const uint8_t *data, size_t datalen)
{ {
// Assumes that request headers have already been pushed to output // Assumes that request headers have already been pushed to output
// buffer using push_request_headers(). // buffer using push_request_headers().
if(!dconn_) {
LOG(WARNING) << "dconn_ is NULL";
return 0;
}
ssize_t res = 0; ssize_t res = 0;
int rv; int rv;
bufferevent *bev = dconn_->get_bev(); bufferevent *bev = dconn_->get_bev();

View File

@ -60,6 +60,9 @@ public:
void force_resume_read(); void force_resume_read();
void set_downstream_connection(DownstreamConnection *dconn); void set_downstream_connection(DownstreamConnection *dconn);
DownstreamConnection* get_downstream_connection(); DownstreamConnection* get_downstream_connection();
// Returns true if output buffer is full. If underlying dconn_ is
// NULL, this function always returns false.
bool get_output_buffer_full();
// downstream request API // downstream request API
const Headers& get_request_headers() const; const Headers& get_request_headers() const;
void add_request_header(const std::string& name, const std::string& value); void add_request_header(const std::string& name, const std::string& value);

View File

@ -258,12 +258,19 @@ int HttpsUpstream::on_read()
} }
} else if(htperr == htparse_error_none) { } else if(htperr == htparse_error_none) {
// downstream can be NULL here. // downstream can be NULL here.
if(downstream && downstream->get_request_state() == Downstream::INITIAL && if(downstream) {
current_header_length_ > SHRPX_HTTPS_MAX_HEADER_LENGTH) { if(downstream->get_request_state() == Downstream::INITIAL &&
LOG(WARNING) << "Request Header too long:" << current_header_length_ current_header_length_ > SHRPX_HTTPS_MAX_HEADER_LENGTH) {
<< " bytes"; LOG(WARNING) << "Request Header too long:" << current_header_length_
get_client_handler()->set_should_close_after_write(true); << " bytes";
error_reply(400); get_client_handler()->set_should_close_after_write(true);
error_reply(400);
} else if(downstream->get_output_buffer_full()) {
if(ENABLE_LOG) {
LOG(INFO) << "Downstream output buffer is full";
}
pause_read(SHRPX_NO_BUFFER);
}
} }
} else { } else {
if(ENABLE_LOG) { if(ENABLE_LOG) {
@ -369,6 +376,11 @@ void https_downstream_readcb(bufferevent *bev, void *ptr)
namespace { namespace {
void https_downstream_writecb(bufferevent *bev, void *ptr) void https_downstream_writecb(bufferevent *bev, void *ptr)
{ {
DownstreamConnection *dconn = reinterpret_cast<DownstreamConnection*>(ptr);
Downstream *downstream = dconn->get_downstream();
HttpsUpstream *upstream;
upstream = static_cast<HttpsUpstream*>(downstream->get_upstream());
upstream->resume_read(SHRPX_NO_BUFFER);
} }
} // namespace } // namespace