Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions proxy/http2/Http2CommonSession.cc
Original file line number Diff line number Diff line change
Expand Up @@ -369,6 +369,7 @@ Http2CommonSession::do_process_frame_read(int event, VIO *vio, bool inside_frame
// Return if there was an error
if (err > Http2ErrorCode::HTTP2_ERROR_NO_ERROR || do_start_frame_read(err) < 0) {
// send an error if specified. Otherwise, just go away
this->connection_state.restart_receiving(nullptr);
if (err > Http2ErrorCode::HTTP2_ERROR_NO_ERROR) {
if (!this->connection_state.is_state_closed()) {
this->connection_state.send_goaway_frame(this->connection_state.get_latest_stream_id_in(), err);
Expand All @@ -387,6 +388,7 @@ Http2CommonSession::do_process_frame_read(int event, VIO *vio, bool inside_frame

if (this->_should_do_something_else()) {
if (this->_reenable_event == nullptr) {
this->connection_state.restart_receiving(nullptr);
vio->disable();
this->_reenable_event = this->get_mutex()->thread_holding->schedule_in(this->get_proxy_session(), HRTIME_MSECONDS(1),
HTTP2_SESSION_EVENT_REENABLE, vio);
Expand All @@ -397,6 +399,7 @@ Http2CommonSession::do_process_frame_read(int event, VIO *vio, bool inside_frame

// If the client hasn't shut us down, reenable
if (!this->get_proxy_session()->is_peer_closed()) {
this->connection_state.restart_receiving(nullptr);
vio->reenable();
}
return 0;
Expand Down
21 changes: 16 additions & 5 deletions proxy/http2/Http2ConnectionState.cc
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,9 @@ Http2ConnectionState::rcv_data_frame(const Http2Frame &frame)

Http2StreamDebug(this->session, id, "Received DATA frame");

// Update connection window size, before any stream specific handling
this->decrement_local_rwnd(payload_length);

if (this->get_zombie_event()) {
Warning("Data frame for zombied session %" PRId64, this->session->get_connection_id());
}
Expand Down Expand Up @@ -174,7 +177,8 @@ Http2ConnectionState::rcv_data_frame(const Http2Frame &frame)
}

// Check whether Window Size is acceptable
if (!this->_local_rwnd_is_shrinking && this->get_local_rwnd() < payload_length) {
// compare to 0 because we already decreased the connection rwnd with payload_length
if (!this->_local_rwnd_is_shrinking && this->get_local_rwnd() < 0) {
return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_CONNECTION, Http2ErrorCode::HTTP2_ERROR_FLOW_CONTROL_ERROR,
"recv data this->local_rwnd < payload_length");
}
Expand All @@ -183,8 +187,7 @@ Http2ConnectionState::rcv_data_frame(const Http2Frame &frame)
"recv data stream->local_rwnd < payload_length");
}

// Update Window size
this->decrement_local_rwnd(payload_length);
// Update stream window size
stream->decrement_local_rwnd(payload_length);

if (is_debug_tag_set("http2_con")) {
Expand Down Expand Up @@ -316,9 +319,17 @@ Http2ConnectionState::rcv_headers_frame(const Http2Frame &frame)
}
}

// Ignoring HEADERS frame on a closed stream. The HdrHeap has gone away and it will core.
// HEADERS frame on a closed stream. The HdrHeap has gone away and it will core.
if (stream->get_state() == Http2StreamState::HTTP2_STREAM_STATE_CLOSED) {
return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
Http2StreamDebug(session, stream_id, "Replaced closed stream");
free_stream_after_decoding = true;
stream = THREAD_ALLOC_INIT(http2StreamAllocator, this_ethread(), session->get_proxy_session(), stream_id,
peer_settings.get(HTTP2_SETTINGS_INITIAL_WINDOW_SIZE), true, false);
if (!stream) {
// This happening is possibly catastrophic, the HPACK tables can be out of sync
// Maybe this is a connection level error?
return Http2Error(Http2ErrorClass::HTTP2_ERROR_CLASS_NONE);
}
}

Http2HeadersParameter params;
Expand Down