Commit 7e217511 authored by Tatsuhiro Tsujikawa's avatar Tatsuhiro Tsujikawa

nghttpx: Code cleanup

Mainly make nested code block to rather flat style.
parent 8c67bbe3
...@@ -272,19 +272,25 @@ void eventcb(bufferevent *bev, short events, void *ptr) ...@@ -272,19 +272,25 @@ void eventcb(bufferevent *bev, short events, void *ptr)
return; return;
} }
int fd = bufferevent_getfd(bev); auto fd = bufferevent_getfd(bev);
int val = 1; int val = 1;
if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
reinterpret_cast<char *>(&val), sizeof(val)) == -1) { reinterpret_cast<char*>(&val), sizeof(val)) == -1) {
SSLOG(WARNING, http2session) SSLOG(WARNING, http2session)
<< "Setting option TCP_NODELAY failed: errno=" << errno; << "Setting option TCP_NODELAY failed: errno=" << errno;
} }
} else if(events & BEV_EVENT_EOF) { return;
}
if(events & BEV_EVENT_EOF) {
if(LOG_ENABLED(INFO)) { if(LOG_ENABLED(INFO)) {
SSLOG(INFO, http2session) << "EOF"; SSLOG(INFO, http2session) << "EOF";
} }
http2session->disconnect(); http2session->disconnect();
} else if(events & (BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT)) { return;
}
if(events & (BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT)) {
if(LOG_ENABLED(INFO)) { if(LOG_ENABLED(INFO)) {
if(events & BEV_EVENT_ERROR) { if(events & BEV_EVENT_ERROR) {
SSLOG(INFO, http2session) << "Network error"; SSLOG(INFO, http2session) << "Network error";
...@@ -293,6 +299,7 @@ void eventcb(bufferevent *bev, short events, void *ptr) ...@@ -293,6 +299,7 @@ void eventcb(bufferevent *bev, short events, void *ptr)
} }
} }
http2session->disconnect(); http2session->disconnect();
return;
} }
} }
} // namespace } // namespace
...@@ -350,12 +357,18 @@ void proxy_eventcb(bufferevent *bev, short events, void *ptr) ...@@ -350,12 +357,18 @@ void proxy_eventcb(bufferevent *bev, short events, void *ptr)
SSLOG(ERROR, http2session) << "bufferevent_write() failed"; SSLOG(ERROR, http2session) << "bufferevent_write() failed";
http2session->disconnect(); http2session->disconnect();
} }
} else if(events & BEV_EVENT_EOF) { return;
}
if(events & BEV_EVENT_EOF) {
if(LOG_ENABLED(INFO)) { if(LOG_ENABLED(INFO)) {
SSLOG(INFO, http2session) << "Proxy EOF"; SSLOG(INFO, http2session) << "Proxy EOF";
} }
http2session->disconnect(); http2session->disconnect();
} else if(events & (BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT)) { return;
}
if(events & (BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT)) {
if(LOG_ENABLED(INFO)) { if(LOG_ENABLED(INFO)) {
if(events & BEV_EVENT_ERROR) { if(events & BEV_EVENT_ERROR) {
SSLOG(INFO, http2session) << "Network error"; SSLOG(INFO, http2session) << "Network error";
...@@ -364,6 +377,7 @@ void proxy_eventcb(bufferevent *bev, short events, void *ptr) ...@@ -364,6 +377,7 @@ void proxy_eventcb(bufferevent *bev, short events, void *ptr)
} }
} }
http2session->disconnect(); http2session->disconnect();
return;
} }
} }
} // namespace } // namespace
...@@ -409,7 +423,11 @@ int Http2Session::initiate_connection() ...@@ -409,7 +423,11 @@ int Http2Session::initiate_connection()
proxy_htp_->data = this; proxy_htp_->data = this;
state_ = PROXY_CONNECTING; state_ = PROXY_CONNECTING;
} else if(state_ == DISCONNECTED || state_ == PROXY_CONNECTED) {
return 0;
}
if(state_ == DISCONNECTED || state_ == PROXY_CONNECTED) {
if(LOG_ENABLED(INFO)) { if(LOG_ENABLED(INFO)) {
SSLOG(INFO, this) << "Connecting to downstream server"; SSLOG(INFO, this) << "Connecting to downstream server";
} }
...@@ -492,11 +510,12 @@ int Http2Session::initiate_connection() ...@@ -492,11 +510,12 @@ int Http2Session::initiate_connection()
if(state_ != CONNECTED) { if(state_ != CONNECTED) {
state_ = CONNECTING; state_ = CONNECTING;
} }
} else {
return 0;
}
// Unreachable // Unreachable
DIE(); DIE();
}
return 0;
} }
void Http2Session::unwrap_free_bev() void Http2Session::unwrap_free_bev()
...@@ -517,10 +536,13 @@ int htp_hdrs_completecb(http_parser *htp) ...@@ -517,10 +536,13 @@ int htp_hdrs_completecb(http_parser *htp)
SSLOG(INFO, http2session) << "Tunneling success"; SSLOG(INFO, http2session) << "Tunneling success";
} }
http2session->set_state(Http2Session::PROXY_CONNECTED); http2session->set_state(Http2Session::PROXY_CONNECTED);
} else {
return 0;
}
SSLOG(WARNING, http2session) << "Tunneling failed"; SSLOG(WARNING, http2session) << "Tunneling failed";
http2session->set_state(Http2Session::PROXY_FAILED); http2session->set_state(Http2Session::PROXY_FAILED);
}
return 0; return 0;
} }
} // namespace } // namespace
......
...@@ -61,25 +61,40 @@ int on_stream_close_callback ...@@ -61,25 +61,40 @@ int on_stream_close_callback
<< " is being closed"; << " is being closed";
} }
auto downstream = upstream->find_downstream(stream_id); auto downstream = upstream->find_downstream(stream_id);
if(downstream) {
if(!downstream) {
return 0;
}
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; delete downstream;
} else {
return 0;
}
downstream->set_request_state(Downstream::STREAM_CLOSED); downstream->set_request_state(Downstream::STREAM_CLOSED);
if(downstream->get_response_state() == Downstream::MSG_COMPLETE) { if(downstream->get_response_state() == Downstream::MSG_COMPLETE) {
// At this point, downstream response was read // At this point, downstream response was read
if(!downstream->get_upgraded() && if(!downstream->get_upgraded() &&
!downstream->get_response_connection_close()) { !downstream->get_response_connection_close()) {
// Keep-alive // Keep-alive
auto dconn = downstream->get_downstream_connection(); auto dconn = downstream->get_downstream_connection();
if(dconn) { if(dconn) {
dconn->detach_downstream(downstream); dconn->detach_downstream(downstream);
} }
} }
upstream->remove_downstream(downstream); upstream->remove_downstream(downstream);
delete downstream; delete downstream;
} else {
return 0;
}
// At this point, downstream read may be paused. // At this point, downstream read may be paused.
// If shrpx_downstream::push_request_headers() failed, the // If shrpx_downstream::push_request_headers() failed, the
...@@ -89,9 +104,7 @@ int on_stream_close_callback ...@@ -89,9 +104,7 @@ int on_stream_close_callback
// 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.
}
}
}
return 0; return 0;
} }
} // namespace } // namespace
...@@ -423,12 +436,16 @@ int on_data_chunk_recv_callback(nghttp2_session *session, ...@@ -423,12 +436,16 @@ int on_data_chunk_recv_callback(nghttp2_session *session,
{ {
auto upstream = static_cast<Http2Upstream*>(user_data); auto upstream = static_cast<Http2Upstream*>(user_data);
auto downstream = upstream->find_downstream(stream_id); auto downstream = upstream->find_downstream(stream_id);
if(downstream) {
if(!downstream) {
return 0;
}
if(downstream->push_upload_data_chunk(data, len) != 0) { if(downstream->push_upload_data_chunk(data, len) != 0) {
upstream->rst_stream(downstream, NGHTTP2_INTERNAL_ERROR); upstream->rst_stream(downstream, NGHTTP2_INTERNAL_ERROR);
return 0; return 0;
} }
}
return 0; return 0;
} }
} // namespace } // namespace
...@@ -691,6 +708,7 @@ void downstream_readcb(bufferevent *bev, void *ptr) ...@@ -691,6 +708,7 @@ void downstream_readcb(bufferevent *bev, void *ptr)
auto dconn = static_cast<DownstreamConnection*>(ptr); auto dconn = static_cast<DownstreamConnection*>(ptr);
auto downstream = dconn->get_downstream(); auto downstream = dconn->get_downstream();
auto upstream = static_cast<Http2Upstream*>(downstream->get_upstream()); auto upstream = static_cast<Http2Upstream*>(downstream->get_upstream());
if(downstream->get_request_state() == Downstream::STREAM_CLOSED) { if(downstream->get_request_state() == Downstream::STREAM_CLOSED) {
// If upstream HTTP2 stream was closed, we just close downstream, // If upstream HTTP2 stream was closed, we just close downstream,
// because there is no consumer now. Downstream connection is also // because there is no consumer now. Downstream connection is also
...@@ -707,11 +725,11 @@ void downstream_readcb(bufferevent *bev, void *ptr) ...@@ -707,11 +725,11 @@ void downstream_readcb(bufferevent *bev, void *ptr)
// on_stream_close_callback. // on_stream_close_callback.
upstream->rst_stream(downstream, infer_upstream_rst_stream_error_code upstream->rst_stream(downstream, infer_upstream_rst_stream_error_code
(downstream->get_response_rst_stream_error_code())); (downstream->get_response_rst_stream_error_code()));
downstream->set_downstream_connection(0); downstream->set_downstream_connection(nullptr);
delete dconn; delete dconn;
dconn = 0; dconn = nullptr;
} else { } else {
int rv = downstream->on_read(); auto rv = downstream->on_read();
if(rv != 0) { if(rv != 0) {
if(LOG_ENABLED(INFO)) { if(LOG_ENABLED(INFO)) {
DCLOG(INFO, dconn) << "HTTP parser failure"; DCLOG(INFO, dconn) << "HTTP parser failure";
...@@ -728,9 +746,9 @@ void downstream_readcb(bufferevent *bev, void *ptr) ...@@ -728,9 +746,9 @@ void downstream_readcb(bufferevent *bev, void *ptr)
downstream->set_response_state(Downstream::MSG_COMPLETE); downstream->set_response_state(Downstream::MSG_COMPLETE);
// Clearly, we have to close downstream connection on http parser // Clearly, we have to close downstream connection on http parser
// failure. // failure.
downstream->set_downstream_connection(0); downstream->set_downstream_connection(nullptr);
delete dconn; delete dconn;
dconn = 0; dconn = nullptr;
} }
} }
if(upstream->send() != 0) { if(upstream->send() != 0) {
...@@ -765,14 +783,18 @@ void downstream_eventcb(bufferevent *bev, short events, void *ptr) ...@@ -765,14 +783,18 @@ void downstream_eventcb(bufferevent *bev, short events, void *ptr)
DCLOG(INFO, dconn) << "Connection established. stream_id=" DCLOG(INFO, dconn) << "Connection established. stream_id="
<< downstream->get_stream_id(); << downstream->get_stream_id();
} }
int fd = bufferevent_getfd(bev); auto fd = bufferevent_getfd(bev);
int val = 1; int val = 1;
if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, if(setsockopt(fd, IPPROTO_TCP, TCP_NODELAY,
reinterpret_cast<char *>(&val), sizeof(val)) == -1) { reinterpret_cast<char*>(&val), sizeof(val)) == -1) {
DCLOG(WARNING, dconn) << "Setting option TCP_NODELAY failed: errno=" DCLOG(WARNING, dconn) << "Setting option TCP_NODELAY failed: errno="
<< errno; << errno;
} }
} else if(events & BEV_EVENT_EOF) {
return;
}
if(events & BEV_EVENT_EOF) {
if(LOG_ENABLED(INFO)) { if(LOG_ENABLED(INFO)) {
DCLOG(INFO, dconn) << "EOF. stream_id=" << downstream->get_stream_id(); DCLOG(INFO, dconn) << "EOF. stream_id=" << downstream->get_stream_id();
} }
...@@ -781,12 +803,15 @@ void downstream_eventcb(bufferevent *bev, short events, void *ptr) ...@@ -781,12 +803,15 @@ void downstream_eventcb(bufferevent *bev, short events, void *ptr)
// the first place. We can delete downstream. // the first place. We can delete downstream.
upstream->remove_downstream(downstream); upstream->remove_downstream(downstream);
delete downstream; delete downstream;
} else {
return;
}
// Delete downstream connection. If we don't delete it here, it // Delete downstream connection. If we don't delete it here, it
// will be pooled in on_stream_close_callback. // will be pooled in on_stream_close_callback.
downstream->set_downstream_connection(0); downstream->set_downstream_connection(nullptr);
delete dconn; delete dconn;
dconn = 0; dconn = nullptr;
// downstream wil be deleted in on_stream_close_callback. // downstream wil be deleted in on_stream_close_callback.
if(downstream->get_response_state() == Downstream::HEADER_COMPLETE) { if(downstream->get_response_state() == Downstream::HEADER_COMPLETE) {
// Server may indicate the end of the request by EOF // Server may indicate the end of the request by EOF
...@@ -814,8 +839,10 @@ void downstream_eventcb(bufferevent *bev, short events, void *ptr) ...@@ -814,8 +839,10 @@ void downstream_eventcb(bufferevent *bev, short events, void *ptr)
return; return;
} }
// At this point, downstream may be deleted. // At this point, downstream may be deleted.
return;
} }
} else if(events & (BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT)) {
if(events & (BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT)) {
if(LOG_ENABLED(INFO)) { if(LOG_ENABLED(INFO)) {
if(events & BEV_EVENT_ERROR) { if(events & BEV_EVENT_ERROR) {
DCLOG(INFO, dconn) << "Downstream network error: " DCLOG(INFO, dconn) << "Downstream network error: "
...@@ -828,15 +855,20 @@ void downstream_eventcb(bufferevent *bev, short events, void *ptr) ...@@ -828,15 +855,20 @@ void downstream_eventcb(bufferevent *bev, short events, void *ptr)
DCLOG(INFO, dconn) << "Note: this is tunnel connection"; DCLOG(INFO, dconn) << "Note: this is tunnel connection";
} }
} }
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; delete downstream;
} else {
return;
}
// Delete downstream connection. If we don't delete it here, it // Delete downstream connection. If we don't delete it here, it
// will be pooled in on_stream_close_callback. // will be pooled in on_stream_close_callback.
downstream->set_downstream_connection(0); downstream->set_downstream_connection(nullptr);
delete dconn; delete dconn;
dconn = 0; dconn = nullptr;
if(downstream->get_response_state() == Downstream::MSG_COMPLETE) { if(downstream->get_response_state() == Downstream::MSG_COMPLETE) {
// For SSL tunneling, we issue RST_STREAM. For other types of // For SSL tunneling, we issue RST_STREAM. For other types of
// stream, we don't have to do anything since response was // stream, we don't have to do anything since response was
...@@ -866,7 +898,7 @@ void downstream_eventcb(bufferevent *bev, short events, void *ptr) ...@@ -866,7 +898,7 @@ void downstream_eventcb(bufferevent *bev, short events, void *ptr)
return; return;
} }
// At this point, downstream may be deleted. // At this point, downstream may be deleted.
} return;
} }
} }
} // namespace } // namespace
......
...@@ -193,19 +193,23 @@ int htp_hdrs_completecb(http_parser *htp) ...@@ -193,19 +193,23 @@ int htp_hdrs_completecb(http_parser *htp)
} }
rv = dconn->attach_downstream(downstream); rv = dconn->attach_downstream(downstream);
if(rv != 0) { if(rv != 0) {
downstream->set_request_state(Downstream::CONNECT_FAIL); downstream->set_request_state(Downstream::CONNECT_FAIL);
downstream->set_downstream_connection(0); downstream->set_downstream_connection(nullptr);
delete dconn; delete dconn;
return -1; return -1;
} else { }
rv = downstream->push_request_headers(); rv = downstream->push_request_headers();
if(rv != 0) { if(rv != 0) {
return -1; return -1;
} }
downstream->set_request_state(Downstream::HEADER_COMPLETE); downstream->set_request_state(Downstream::HEADER_COMPLETE);
return 0; return 0;
}
} }
} // namespace } // namespace
...@@ -431,9 +435,9 @@ int HttpsUpstream::resume_read(IOCtrlReason reason, Downstream *downstream) ...@@ -431,9 +435,9 @@ int HttpsUpstream::resume_read(IOCtrlReason reason, Downstream *downstream)
// are not notified by readcb until new data arrive. // are not notified by readcb until new data arrive.
http_parser_pause(&htp_, 0); http_parser_pause(&htp_, 0);
return on_read(); return on_read();
} else {
return 0;
} }
return 0;
} }
namespace { namespace {
...@@ -443,22 +447,67 @@ void https_downstream_readcb(bufferevent *bev, void *ptr) ...@@ -443,22 +447,67 @@ void https_downstream_readcb(bufferevent *bev, void *ptr)
auto downstream = dconn->get_downstream(); auto downstream = dconn->get_downstream();
auto upstream = static_cast<HttpsUpstream*>(downstream->get_upstream()); auto upstream = static_cast<HttpsUpstream*>(downstream->get_upstream());
int rv; int rv;
rv = downstream->on_read(); rv = downstream->on_read();
if(downstream->get_response_state() == Downstream::MSG_RESET) { if(downstream->get_response_state() == Downstream::MSG_RESET) {
delete upstream->get_client_handler(); delete upstream->get_client_handler();
} else if(rv == 0) {
return;
}
if(rv != 0) {
if(downstream->get_response_state() == Downstream::HEADER_COMPLETE) {
// We already sent HTTP response headers to upstream
// client. Just close the upstream connection.
delete upstream->get_client_handler();
return;
}
// We did not sent any HTTP response, so sent error
// response. Cannot reuse downstream connection in this case.
if(upstream->error_reply(502) != 0) {
delete upstream->get_client_handler();
return;
}
if(downstream->get_request_state() == Downstream::MSG_COMPLETE) {
upstream->delete_downstream();
// Process next HTTP request
if(upstream->resume_read(SHRPX_MSG_BLOCK, 0) == -1) {
return;
}
}
return;
}
auto handler = upstream->get_client_handler(); auto handler = upstream->get_client_handler();
if(downstream->get_response_state() == Downstream::MSG_COMPLETE) { if(downstream->get_response_state() != Downstream::MSG_COMPLETE) {
if(handler->get_outbuf_length() >= OUTBUF_MAX_THRES) {
downstream->pause_read(SHRPX_NO_BUFFER);
}
return;
}
if(downstream->get_response_connection_close()) { if(downstream->get_response_connection_close()) {
// Connection close // Connection close
downstream->set_downstream_connection(0); downstream->set_downstream_connection(nullptr);
delete dconn; delete dconn;
dconn = 0;
dconn = nullptr;
} else { } else {
// Keep-alive // Keep-alive
dconn->detach_downstream(downstream); dconn->detach_downstream(downstream);
} }
if(downstream->get_request_state() == Downstream::MSG_COMPLETE) { if(downstream->get_request_state() == Downstream::MSG_COMPLETE) {
if(handler->get_should_close_after_write() && if(handler->get_should_close_after_write() &&
handler->get_outbuf_length() == 0) { handler->get_outbuf_length() == 0) {
...@@ -466,15 +515,21 @@ void https_downstream_readcb(bufferevent *bev, void *ptr) ...@@ -466,15 +515,21 @@ void https_downstream_readcb(bufferevent *bev, void *ptr)
// the peer, we cannot use writecb for ClientHandler. In // the peer, we cannot use writecb for ClientHandler. In
// this case, we just delete handler here. // this case, we just delete handler here.
delete handler; delete handler;
return; return;
} else { }
upstream->delete_downstream(); upstream->delete_downstream();
// Process next HTTP request // Process next HTTP request
if(upstream->resume_read(SHRPX_MSG_BLOCK, 0) == -1) { if(upstream->resume_read(SHRPX_MSG_BLOCK, 0) == -1) {
return; return;
} }
return;
} }
} else if(downstream->get_upgraded()) {
if(downstream->get_upgraded()) {
// This path is effectively only taken for HTTP2 downstream // This path is effectively only taken for HTTP2 downstream
// because only HTTP2 downstream sets response_state to // because only HTTP2 downstream sets response_state to
// MSG_COMPLETE and this function. For HTTP downstream, EOF // MSG_COMPLETE and this function. For HTTP downstream, EOF
...@@ -486,38 +541,16 @@ void https_downstream_readcb(bufferevent *bev, void *ptr) ...@@ -486,38 +541,16 @@ void https_downstream_readcb(bufferevent *bev, void *ptr)
// For tunneled connection, if there is no pending data, // For tunneled connection, if there is no pending data,
// delete handler because on_write will not be called. // delete handler because on_write will not be called.
delete handler; delete handler;
} else {
return;
}
if(LOG_ENABLED(INFO)) { if(LOG_ENABLED(INFO)) {
DLOG(INFO, downstream) << "Tunneled connection has pending data"; DLOG(INFO, downstream) << "Tunneled connection has pending data";
} }
}
}
} else {
if(handler->get_outbuf_length() >= OUTBUF_MAX_THRES) {
downstream->pause_read(SHRPX_NO_BUFFER);
}
}
} else {
if(downstream->get_response_state() == Downstream::HEADER_COMPLETE) {
// We already sent HTTP response headers to upstream
// client. Just close the upstream connection.
delete upstream->get_client_handler();
} else {
// We did not sent any HTTP response, so sent error
// response. Cannot reuse downstream connection in this case.
if(upstream->error_reply(502) != 0) {
delete upstream->get_client_handler();
return;
}
if(downstream->get_request_state() == Downstream::MSG_COMPLETE) {
upstream->delete_downstream();
// Process next HTTP request
if(upstream->resume_read(SHRPX_MSG_BLOCK, 0) == -1) {
return; return;
} }
}
}
}
} }
} // namespace } // namespace
...@@ -545,7 +578,11 @@ void https_downstream_eventcb(bufferevent *bev, short events, void *ptr) ...@@ -545,7 +578,11 @@ void https_downstream_eventcb(bufferevent *bev, short events, void *ptr)
if(LOG_ENABLED(INFO)) { if(LOG_ENABLED(INFO)) {
DCLOG(INFO, dconn) << "Connection established"; DCLOG(INFO, dconn) << "Connection established";
} }
} else if(events & BEV_EVENT_EOF) {
return;
}
if(events & BEV_EVENT_EOF) {
if(LOG_ENABLED(INFO)) { if(LOG_ENABLED(INFO)) {
DCLOG(INFO, dconn) << "EOF"; DCLOG(INFO, dconn) << "EOF";
} }
...@@ -567,9 +604,7 @@ void https_downstream_eventcb(bufferevent *bev, short events, void *ptr) ...@@ -567,9 +604,7 @@ void https_downstream_eventcb(bufferevent *bev, short events, void *ptr)
delete handler; delete handler;
return; return;
} }
} else if(downstream->get_response_state() == Downstream::MSG_COMPLETE) { } else if(downstream->get_response_state() != Downstream::MSG_COMPLETE) {
// Nothing to do
} else {
// error // error
if(LOG_ENABLED(INFO)) { if(LOG_ENABLED(INFO)) {
DCLOG(INFO, dconn) << "Treated as error"; DCLOG(INFO, dconn) << "Treated as error";
...@@ -585,7 +620,11 @@ void https_downstream_eventcb(bufferevent *bev, short events, void *ptr) ...@@ -585,7 +620,11 @@ void https_downstream_eventcb(bufferevent *bev, short events, void *ptr)
return; return;
} }
} }
} else if(events & (BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT)) {
return;
}
if(events & (BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT)) {
if(LOG_ENABLED(INFO)) { if(LOG_ENABLED(INFO)) {
if(events & BEV_EVENT_ERROR) { if(events & BEV_EVENT_ERROR) {
DCLOG(INFO, dconn) << "Network error"; DCLOG(INFO, dconn) << "Network error";
......
...@@ -103,11 +103,16 @@ void on_stream_close_callback ...@@ -103,11 +103,16 @@ void on_stream_close_callback
<< " is being closed"; << " is being closed";
} }
auto downstream = upstream->find_downstream(stream_id); auto downstream = upstream->find_downstream(stream_id);
if(downstream) { if(!downstream) {
return;
}
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; delete downstream;
} else { return;
}
downstream->set_request_state(Downstream::STREAM_CLOSED); downstream->set_request_state(Downstream::STREAM_CLOSED);
if(downstream->get_response_state() == Downstream::MSG_COMPLETE) { if(downstream->get_response_state() == Downstream::MSG_COMPLETE) {
// At this point, downstream response was read // At this point, downstream response was read
...@@ -121,7 +126,9 @@ void on_stream_close_callback ...@@ -121,7 +126,9 @@ void on_stream_close_callback
} }
upstream->remove_downstream(downstream); upstream->remove_downstream(downstream);
delete downstream; delete downstream;
} else { return;
}
// At this point, downstream read may be paused. // At this point, downstream read may be paused.
// If shrpx_downstream::push_request_headers() failed, the // If shrpx_downstream::push_request_headers() failed, the
...@@ -131,9 +138,6 @@ void on_stream_close_callback ...@@ -131,9 +138,6 @@ void on_stream_close_callback
// 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.
}
}
}
} }
} // namespace } // namespace
...@@ -245,12 +249,20 @@ void on_data_chunk_recv_callback(spdylay_session *session, ...@@ -245,12 +249,20 @@ void on_data_chunk_recv_callback(spdylay_session *session,
{ {
auto upstream = static_cast<SpdyUpstream*>(user_data); auto upstream = static_cast<SpdyUpstream*>(user_data);
auto downstream = upstream->find_downstream(stream_id); auto downstream = upstream->find_downstream(stream_id);
if(downstream) {
if(!downstream) {
return;
}
if(downstream->push_upload_data_chunk(data, len) != 0) { if(downstream->push_upload_data_chunk(data, len) != 0) {
upstream->rst_stream(downstream, SPDYLAY_INTERNAL_ERROR); upstream->rst_stream(downstream, SPDYLAY_INTERNAL_ERROR);
return; return;
} }
if(upstream->get_flow_control()) {
if(!upstream->get_flow_control()) {
return;
}
// If connection-level window control is not enabled (e.g, // If connection-level window control is not enabled (e.g,
// spdy/3), spdylay_session_get_recv_data_length() is always // spdy/3), spdylay_session_get_recv_data_length() is always
// returns 0. // returns 0.
...@@ -281,8 +293,6 @@ void on_data_chunk_recv_callback(spdylay_session *session, ...@@ -281,8 +293,6 @@ void on_data_chunk_recv_callback(spdylay_session *session,
upstream->rst_stream(downstream, SPDYLAY_FLOW_CONTROL_ERROR); upstream->rst_stream(downstream, SPDYLAY_FLOW_CONTROL_ERROR);
return; return;
} }
}
}
} }
} // namespace } // namespace
...@@ -520,11 +530,11 @@ void spdy_downstream_readcb(bufferevent *bev, void *ptr) ...@@ -520,11 +530,11 @@ void spdy_downstream_readcb(bufferevent *bev, void *ptr)
// on_stream_close_callback. // on_stream_close_callback.
upstream->rst_stream(downstream, infer_upstream_rst_stream_status_code upstream->rst_stream(downstream, infer_upstream_rst_stream_status_code
(downstream->get_response_rst_stream_error_code())); (downstream->get_response_rst_stream_error_code()));
downstream->set_downstream_connection(0); downstream->set_downstream_connection(nullptr);
delete dconn; delete dconn;
dconn = 0; dconn = nullptr;
} else { } else {
int rv = downstream->on_read(); auto rv = downstream->on_read();
if(rv != 0) { if(rv != 0) {
if(LOG_ENABLED(INFO)) { if(LOG_ENABLED(INFO)) {
DCLOG(INFO, dconn) << "HTTP parser failure"; DCLOG(INFO, dconn) << "HTTP parser failure";
...@@ -541,9 +551,9 @@ void spdy_downstream_readcb(bufferevent *bev, void *ptr) ...@@ -541,9 +551,9 @@ void spdy_downstream_readcb(bufferevent *bev, void *ptr)
downstream->set_response_state(Downstream::MSG_COMPLETE); downstream->set_response_state(Downstream::MSG_COMPLETE);
// Clearly, we have to close downstream connection on http parser // Clearly, we have to close downstream connection on http parser
// failure. // failure.
downstream->set_downstream_connection(0); downstream->set_downstream_connection(nullptr);
delete dconn; delete dconn;
dconn = 0; dconn = nullptr;
} }
} }
if(upstream->send() != 0) { if(upstream->send() != 0) {
...@@ -573,6 +583,7 @@ void spdy_downstream_eventcb(bufferevent *bev, short events, void *ptr) ...@@ -573,6 +583,7 @@ void spdy_downstream_eventcb(bufferevent *bev, short events, void *ptr)
auto dconn = static_cast<DownstreamConnection*>(ptr); auto dconn = static_cast<DownstreamConnection*>(ptr);
auto downstream = dconn->get_downstream(); auto downstream = dconn->get_downstream();
auto upstream = static_cast<SpdyUpstream*>(downstream->get_upstream()); auto upstream = static_cast<SpdyUpstream*>(downstream->get_upstream());
if(events & BEV_EVENT_CONNECTED) { if(events & BEV_EVENT_CONNECTED) {
if(LOG_ENABLED(INFO)) { if(LOG_ENABLED(INFO)) {
DCLOG(INFO, dconn) << "Connection established. stream_id=" DCLOG(INFO, dconn) << "Connection established. stream_id="
...@@ -585,7 +596,10 @@ void spdy_downstream_eventcb(bufferevent *bev, short events, void *ptr) ...@@ -585,7 +596,10 @@ void spdy_downstream_eventcb(bufferevent *bev, short events, void *ptr)
DCLOG(WARNING, dconn) << "Setting option TCP_NODELAY failed: errno=" DCLOG(WARNING, dconn) << "Setting option TCP_NODELAY failed: errno="
<< errno; << errno;
} }
} else if(events & BEV_EVENT_EOF) { return;
}
if(events & BEV_EVENT_EOF) {
if(LOG_ENABLED(INFO)) { if(LOG_ENABLED(INFO)) {
DCLOG(INFO, dconn) << "EOF. stream_id=" << downstream->get_stream_id(); DCLOG(INFO, dconn) << "EOF. stream_id=" << downstream->get_stream_id();
} }
...@@ -594,12 +608,14 @@ void spdy_downstream_eventcb(bufferevent *bev, short events, void *ptr) ...@@ -594,12 +608,14 @@ void spdy_downstream_eventcb(bufferevent *bev, short events, void *ptr)
// the first place. We can delete downstream. // the first place. We can delete downstream.
upstream->remove_downstream(downstream); upstream->remove_downstream(downstream);
delete downstream; delete downstream;
} else { return;
}
// Delete downstream connection. If we don't delete it here, it // Delete downstream connection. If we don't delete it here, it
// will be pooled in on_stream_close_callback. // will be pooled in on_stream_close_callback.
downstream->set_downstream_connection(0); downstream->set_downstream_connection(nullptr);
delete dconn; delete dconn;
dconn = 0; dconn = nullptr;
// downstream wil be deleted in on_stream_close_callback. // downstream wil be deleted in on_stream_close_callback.
if(downstream->get_response_state() == Downstream::HEADER_COMPLETE) { if(downstream->get_response_state() == Downstream::HEADER_COMPLETE) {
// Server may indicate the end of the request by EOF // Server may indicate the end of the request by EOF
...@@ -627,8 +643,11 @@ void spdy_downstream_eventcb(bufferevent *bev, short events, void *ptr) ...@@ -627,8 +643,11 @@ void spdy_downstream_eventcb(bufferevent *bev, short events, void *ptr)
return; return;
} }
// At this point, downstream may be deleted. // At this point, downstream may be deleted.
return;
} }
} else if(events & (BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT)) {
if(events & (BEV_EVENT_ERROR | BEV_EVENT_TIMEOUT)) {
if(LOG_ENABLED(INFO)) { if(LOG_ENABLED(INFO)) {
if(events & BEV_EVENT_ERROR) { if(events & BEV_EVENT_ERROR) {
DCLOG(INFO, dconn) << "Downstream network error: " DCLOG(INFO, dconn) << "Downstream network error: "
...@@ -644,12 +663,15 @@ void spdy_downstream_eventcb(bufferevent *bev, short events, void *ptr) ...@@ -644,12 +663,15 @@ 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; delete downstream;
} else { return;
}
// Delete downstream connection. If we don't delete it here, it // Delete downstream connection. If we don't delete it here, it
// will be pooled in on_stream_close_callback. // will be pooled in on_stream_close_callback.
downstream->set_downstream_connection(0); downstream->set_downstream_connection(nullptr);
delete dconn; delete dconn;
dconn = 0; dconn = nullptr;
if(downstream->get_response_state() == Downstream::MSG_COMPLETE) { if(downstream->get_response_state() == Downstream::MSG_COMPLETE) {
// For SSL tunneling, we issue RST_STREAM. For other types of // For SSL tunneling, we issue RST_STREAM. For other types of
// stream, we don't have to do anything since response was // stream, we don't have to do anything since response was
...@@ -679,7 +701,7 @@ void spdy_downstream_eventcb(bufferevent *bev, short events, void *ptr) ...@@ -679,7 +701,7 @@ void spdy_downstream_eventcb(bufferevent *bev, short events, void *ptr)
return; return;
} }
// At this point, downstream may be deleted. // At this point, downstream may be deleted.
} return;
} }
} }
} // namespace } // namespace
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment