shrpx: Handle the case when evbuffer_add() returned -1

This commit is contained in:
Tatsuhiro Tsujikawa 2012-07-17 00:12:31 +09:00
parent a95981f3da
commit f10848febd
3 changed files with 39 additions and 8 deletions

View File

@ -367,7 +367,11 @@ int Downstream::push_request_headers()
} }
bufferevent *bev = dconn_->get_bev(); bufferevent *bev = dconn_->get_bev();
evbuffer *output = bufferevent_get_output(bev); evbuffer *output = bufferevent_get_output(bev);
evbuffer_add(output, hdrs.c_str(), hdrs.size()); int rv;
rv = evbuffer_add(output, hdrs.c_str(), hdrs.size());
if(rv != 0) {
return -1;
}
dconn_->start_waiting_response(); dconn_->start_waiting_response();
return 0; return 0;
@ -392,17 +396,20 @@ int Downstream::push_upload_data_chunk(const uint8_t *data, size_t datalen)
res += rv; res += rv;
rv = evbuffer_add(output, chunk_size_hex, rv); rv = evbuffer_add(output, chunk_size_hex, rv);
if(rv == -1) { if(rv == -1) {
LOG(FATAL) << "evbuffer_add() failed";
return -1; return -1;
} }
} }
rv = evbuffer_add(output, data, datalen); rv = evbuffer_add(output, data, datalen);
if(rv == -1) { if(rv == -1) {
LOG(FATAL) << "evbuffer_add() failed";
return -1; return -1;
} }
res += rv; res += rv;
if(chunked_request_) { if(chunked_request_) {
rv = evbuffer_add(output, "\r\n", 2); rv = evbuffer_add(output, "\r\n", 2);
if(rv == -1) { if(rv == -1) {
LOG(FATAL) << "evbuffer_add() failed";
return -1; return -1;
} }
res += 2; res += 2;
@ -415,7 +422,10 @@ int Downstream::end_upload_data()
if(chunked_request_) { if(chunked_request_) {
bufferevent *bev = dconn_->get_bev(); bufferevent *bev = dconn_->get_bev();
evbuffer *output = bufferevent_get_output(bev); evbuffer *output = bufferevent_get_output(bev);
evbuffer_add(output, "0\r\n\r\n", 5); if(evbuffer_add(output, "0\r\n\r\n", 5) != 0) {
LOG(FATAL) << "evbuffer_add() failed";
return -1;
}
} }
return 0; return 0;
} }

View File

@ -159,7 +159,10 @@ int htp_hdrs_completecb(http_parser *htp)
delete dconn; delete dconn;
return -1; return -1;
} else { } else {
downstream->push_request_headers(); rv = downstream->push_request_headers();
if(rv != 0) {
return -1;
}
downstream->set_request_state(Downstream::HEADER_COMPLETE); downstream->set_request_state(Downstream::HEADER_COMPLETE);
return 0; return 0;
} }
@ -169,11 +172,15 @@ int htp_hdrs_completecb(http_parser *htp)
namespace { namespace {
int htp_bodycb(http_parser *htp, const char *data, size_t len) int htp_bodycb(http_parser *htp, const char *data, size_t len)
{ {
int rv;
HttpsUpstream *upstream; HttpsUpstream *upstream;
upstream = reinterpret_cast<HttpsUpstream*>(htp->data); upstream = reinterpret_cast<HttpsUpstream*>(htp->data);
Downstream *downstream = upstream->get_last_downstream(); Downstream *downstream = upstream->get_last_downstream();
downstream->push_upload_data_chunk(reinterpret_cast<const uint8_t*>(data), rv = downstream->push_upload_data_chunk
len); (reinterpret_cast<const uint8_t*>(data), len);
if(rv != 0) {
return -1;
}
return 0; return 0;
} }
} // namespace } // namespace
@ -181,13 +188,17 @@ int htp_bodycb(http_parser *htp, const char *data, size_t len)
namespace { namespace {
int htp_msg_completecb(http_parser *htp) int htp_msg_completecb(http_parser *htp)
{ {
int rv;
if(ENABLE_LOG) { if(ENABLE_LOG) {
LOG(INFO) << "Upstream https request complete"; LOG(INFO) << "Upstream https request complete";
} }
HttpsUpstream *upstream; HttpsUpstream *upstream;
upstream = reinterpret_cast<HttpsUpstream*>(htp->data); upstream = reinterpret_cast<HttpsUpstream*>(htp->data);
Downstream *downstream = upstream->get_last_downstream(); Downstream *downstream = upstream->get_last_downstream();
downstream->end_upload_data(); rv = downstream->end_upload_data();
if(rv != 0) {
return -1;
}
downstream->set_request_state(Downstream::MSG_COMPLETE); downstream->set_request_state(Downstream::MSG_COMPLETE);
// Stop further processing to complete this request // Stop further processing to complete this request
http_parser_pause(htp, 1); http_parser_pause(htp, 1);

View File

@ -118,6 +118,9 @@ void on_stream_close_callback
delete downstream; delete downstream;
} else { } else {
// At this point, downstream read may be paused. // At this point, downstream read may be paused.
// If shrpx_downstream::push_request_headers() failed, the
// error is handled here.
upstream->remove_downstream(downstream); upstream->remove_downstream(downstream);
delete downstream; delete downstream;
// How to test this case? Request sufficient large download // How to test this case? Request sufficient large download
@ -201,7 +204,11 @@ void on_ctrl_recv_callback
downstream->set_request_state(Downstream::CONNECT_FAIL); downstream->set_request_state(Downstream::CONNECT_FAIL);
return; return;
} }
downstream->push_request_headers(); rv = downstream->push_request_headers();
if(rv != 0) {
upstream->rst_stream(downstream, SPDYLAY_INTERNAL_ERROR);
return;
}
downstream->set_request_state(Downstream::HEADER_COMPLETE); downstream->set_request_state(Downstream::HEADER_COMPLETE);
if(frame->syn_stream.hd.flags & SPDYLAY_CTRL_FLAG_FIN) { if(frame->syn_stream.hd.flags & SPDYLAY_CTRL_FLAG_FIN) {
if(ENABLE_LOG) { if(ENABLE_LOG) {
@ -228,7 +235,10 @@ void on_data_chunk_recv_callback(spdylay_session *session,
SpdyUpstream *upstream = reinterpret_cast<SpdyUpstream*>(user_data); SpdyUpstream *upstream = reinterpret_cast<SpdyUpstream*>(user_data);
Downstream *downstream = upstream->find_downstream(stream_id); Downstream *downstream = upstream->find_downstream(stream_id);
if(downstream) { if(downstream) {
downstream->push_upload_data_chunk(data, len); if(downstream->push_upload_data_chunk(data, len) != 0) {
upstream->rst_stream(downstream, SPDYLAY_INTERNAL_ERROR);
return;
}
if(upstream->get_flow_control()) { if(upstream->get_flow_control()) {
downstream->inc_recv_window_size(len); downstream->inc_recv_window_size(len);
if(downstream->get_recv_window_size() > if(downstream->get_recv_window_size() >