-
Notifications
You must be signed in to change notification settings - Fork 5.3k
quiche: add 100 continue support #14246
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -19,8 +19,11 @@ | |
| #include "extensions/quic_listeners/quiche/envoy_quic_client_session.h" | ||
|
|
||
| #include "common/buffer/buffer_impl.h" | ||
| #include "common/http/codes.h" | ||
| #include "common/http/header_map_impl.h" | ||
| #include "common/http/header_utility.h" | ||
| #include "common/http/utility.h" | ||
| #include "common/common/enum_to_int.h" | ||
| #include "common/common/assert.h" | ||
|
|
||
| namespace Envoy { | ||
|
|
@@ -132,25 +135,49 @@ void EnvoyQuicClientStream::switchStreamBlockState(bool should_block) { | |
|
|
||
| void EnvoyQuicClientStream::OnInitialHeadersComplete(bool fin, size_t frame_len, | ||
| const quic::QuicHeaderList& header_list) { | ||
| if (rst_sent()) { | ||
| if (read_side_closed()) { | ||
| return; | ||
| } | ||
| quic::QuicSpdyStream::OnInitialHeadersComplete(fin, frame_len, header_list); | ||
| ASSERT(headers_decompressed() && !header_list.empty()); | ||
|
|
||
| response_decoder_->decodeHeaders( | ||
| quicHeadersToEnvoyHeaders<Http::ResponseHeaderMapImpl>(header_list), | ||
| /*end_stream=*/fin); | ||
| ENVOY_STREAM_LOG(debug, "Received headers: {}.", *this, header_list.DebugString()); | ||
| if (fin) { | ||
| end_stream_decoded_ = true; | ||
| } | ||
| std::unique_ptr<Http::ResponseHeaderMapImpl> headers = | ||
| quicHeadersToEnvoyHeaders<Http::ResponseHeaderMapImpl>(header_list); | ||
| const uint64_t status = Http::Utility::getResponseStatus(*headers); | ||
| if (Http::CodeUtility::is1xx(status)) { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. So what happens with 1xx headers which are not 100-continue? For non-QUIC we send them up via decodeHeaders.
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Oh, I didn't know that. Currently we drop these headers on the floor. Will fix it.
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh fair point. maybe treat it as invalid and fast-fail the response then?
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Re-wrote 1xx header handling logic here. PTAL! |
||
| if (status == enumToInt(Http::Code::SwitchingProtocols)) { | ||
| // HTTP3 doesn't support the HTTP Upgrade mechanism or 101 (Switching Protocols) status code. | ||
| Reset(quic::QUIC_BAD_APPLICATION_PAYLOAD); | ||
| return; | ||
| } | ||
|
|
||
| // These are Informational 1xx headers, not the actual response headers. | ||
| set_headers_decompressed(false); | ||
| } | ||
|
|
||
| if (status == enumToInt(Http::Code::Continue) && !decoded_100_continue_) { | ||
| // This is 100 Continue, only decode it once to support Expect:100-Continue header. | ||
| decoded_100_continue_ = true; | ||
| response_decoder_->decode100ContinueHeaders(std::move(headers)); | ||
| } else if (status != enumToInt(Http::Code::Continue)) { | ||
| response_decoder_->decodeHeaders(std::move(headers), | ||
| /*end_stream=*/fin); | ||
| } | ||
|
|
||
| ConsumeHeaderList(); | ||
| } | ||
|
|
||
| void EnvoyQuicClientStream::OnBodyAvailable() { | ||
| ASSERT(FinishedReadingHeaders()); | ||
| ASSERT(read_disable_counter_ == 0); | ||
| ASSERT(!in_decode_data_callstack_); | ||
| if (read_side_closed()) { | ||
| return; | ||
| } | ||
| in_decode_data_callstack_ = true; | ||
|
|
||
| Buffer::InstancePtr buffer = std::make_unique<Buffer::OwnedImpl>(); | ||
|
|
@@ -178,13 +205,13 @@ void EnvoyQuicClientStream::OnBodyAvailable() { | |
| // already delivered it or decodeTrailers will be called. | ||
| bool skip_decoding = (buffer->length() == 0 && !fin_read_and_no_trailers) || end_stream_decoded_; | ||
| if (!skip_decoding) { | ||
| response_decoder_->decodeData(*buffer, fin_read_and_no_trailers); | ||
| if (fin_read_and_no_trailers) { | ||
| end_stream_decoded_ = true; | ||
| } | ||
| response_decoder_->decodeData(*buffer, fin_read_and_no_trailers); | ||
| } | ||
|
|
||
| if (!sequencer()->IsClosed()) { | ||
| if (!sequencer()->IsClosed() || read_side_closed()) { | ||
| in_decode_data_callstack_ = false; | ||
| if (read_disable_counter_ > 0) { | ||
| // If readDisable() was ever called during decodeData() and it meant to disable | ||
|
|
@@ -204,6 +231,10 @@ void EnvoyQuicClientStream::OnBodyAvailable() { | |
|
|
||
| void EnvoyQuicClientStream::OnTrailingHeadersComplete(bool fin, size_t frame_len, | ||
| const quic::QuicHeaderList& header_list) { | ||
| if (read_side_closed()) { | ||
| return; | ||
| } | ||
| ENVOY_STREAM_LOG(debug, "Received trailers: {}.", *this, header_list.DebugString()); | ||
| quic::QuicSpdyStream::OnTrailingHeadersComplete(fin, frame_len, header_list); | ||
| ASSERT(trailers_decompressed()); | ||
| if (session()->connection()->connected() && !rst_sent()) { | ||
|
|
@@ -215,9 +246,9 @@ void EnvoyQuicClientStream::maybeDecodeTrailers() { | |
| if (sequencer()->IsClosed() && !FinishedReadingTrailers()) { | ||
| ASSERT(!received_trailers().empty()); | ||
| // Only decode trailers after finishing decoding body. | ||
| end_stream_decoded_ = true; | ||
| response_decoder_->decodeTrailers( | ||
| spdyHeaderBlockToEnvoyHeaders<Http::ResponseTrailerMapImpl>(received_trailers())); | ||
| end_stream_decoded_ = true; | ||
| MarkTrailersConsumed(); | ||
| } | ||
| } | ||
|
|
@@ -236,7 +267,9 @@ void EnvoyQuicClientStream::Reset(quic::QuicRstStreamErrorCode error) { | |
| void EnvoyQuicClientStream::OnConnectionClosed(quic::QuicErrorCode error, | ||
| quic::ConnectionCloseSource source) { | ||
| quic::QuicSpdyClientStream::OnConnectionClosed(error, source); | ||
| runResetCallbacks(quicErrorCodeToEnvoyResetReason(error)); | ||
| if (!end_stream_decoded_) { | ||
| runResetCallbacks(quicErrorCodeToEnvoyResetReason(error)); | ||
| } | ||
| } | ||
|
|
||
| void EnvoyQuicClientStream::OnClose() { | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.