diff --git a/src/shrpx_http_downstream_connection.cc b/src/shrpx_http_downstream_connection.cc index b01dee4..bff7aac 100644 --- a/src/shrpx_http_downstream_connection.cc +++ b/src/shrpx_http_downstream_connection.cc @@ -356,6 +356,9 @@ int htp_hdrs_completecb(http_parser *htp) downstream->set_response_minor(htp->http_minor); downstream->set_response_connection_close(!http_should_keep_alive(htp)); downstream->set_response_state(Downstream::HEADER_COMPLETE); + if(downstream->tunnel_established()) { + downstream->set_response_connection_close(true); + } if(downstream->get_upstream()->on_downstream_header_complete(downstream) != 0) { return -1; diff --git a/src/shrpx_https_upstream.cc b/src/shrpx_https_upstream.cc index 415dd9f..a40a633 100644 --- a/src/shrpx_https_upstream.cc +++ b/src/shrpx_https_upstream.cc @@ -378,20 +378,6 @@ void https_downstream_readcb(bufferevent *bev, void *ptr) delete upstream->get_client_handler(); } else if(rv == 0) { if(downstream->get_response_state() == Downstream::MSG_COMPLETE) { - if(get_config()->client_mode && downstream->tunnel_established()) { - // For tunneled connection, if there is no pending data, - // delete handler because on_write will not be called. - ClientHandler *handler = upstream->get_client_handler(); - if(handler->get_pending_write_length() == 0) { - delete handler; - } else { - if(LOG_ENABLED(INFO)) { - DLOG(INFO, downstream) << "Tunneled connection has pending data"; - } - handler->set_should_close_after_write(true); - } - return; - } if(downstream->get_response_connection_close()) { // Connection close downstream->set_downstream_connection(0); @@ -401,8 +387,8 @@ void https_downstream_readcb(bufferevent *bev, void *ptr) // Keep-alive dconn->detach_downstream(downstream); } + ClientHandler *handler = upstream->get_client_handler(); if(downstream->get_request_state() == Downstream::MSG_COMPLETE) { - ClientHandler *handler = upstream->get_client_handler(); if(handler->get_should_close_after_write() && handler->get_pending_write_length() == 0) { // If all upstream response body has already written out to @@ -417,6 +403,23 @@ void https_downstream_readcb(bufferevent *bev, void *ptr) return; } } + } else if(downstream->tunnel_established()) { + // This path is effectively only taken for SPDY downstream + // because only SPDY downstream sets response_state to + // MSG_COMPLETE and this function. For HTTP downstream, EOF + // from tunnel connection is handled on + // https_downstream_eventcb. + // + // Tunneled connection always indicates connection close. + if(handler->get_pending_write_length() == 0) { + // For tunneled connection, if there is no pending data, + // delete handler because on_write will not be called. + delete handler; + } else { + if(LOG_ENABLED(INFO)) { + DLOG(INFO, downstream) << "Tunneled connection has pending data"; + } + } } } else { ClientHandler *handler = upstream->get_client_handler(); diff --git a/src/shrpx_spdy_session.cc b/src/shrpx_spdy_session.cc index 4cc8d3c..ae21563 100644 --- a/src/shrpx_spdy_session.cc +++ b/src/shrpx_spdy_session.cc @@ -707,6 +707,7 @@ void on_ctrl_recv_callback << "stream_id=" << frame->rst_stream.stream_id; } + downstream->get_upstream()->on_downstream_body_complete(downstream); downstream->set_response_state(Downstream::MSG_COMPLETE); } else { // If we got RST_STREAM, just flag MSG_RESET to indicate @@ -801,6 +802,9 @@ void on_ctrl_recv_callback Upstream *upstream = downstream->get_upstream(); downstream->set_response_state(Downstream::HEADER_COMPLETE); + if(downstream->tunnel_established()) { + downstream->set_response_connection_close(true); + } rv = upstream->on_downstream_header_complete(downstream); if(rv != 0) { spdylay_submit_rst_stream(session, frame->syn_reply.stream_id,