-
Notifications
You must be signed in to change notification settings - Fork 5.3k
quiche: implement stream idle timeout in codec #17674
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
c275f94
531cfbc
38774bb
dcf9fef
4392432
635ee68
c160b86
ccf179d
e378df5
dc817ee
231b14e
c7d1627
c72a1f4
77791de
b65c64a
b7b9049
050631f
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 |
|---|---|---|
|
|
@@ -181,25 +181,16 @@ class ConnectionImpl : public virtual Connection, | |
| * Base class for client and server side streams. | ||
| */ | ||
| struct StreamImpl : public virtual StreamEncoder, | ||
| public Stream, | ||
| public LinkedObject<StreamImpl>, | ||
| public Event::DeferredDeletable, | ||
| public StreamCallbackHelper, | ||
| public Http::MultiplexedStreamImplBase, | ||
| public ScopeTrackedObject { | ||
|
|
||
| StreamImpl(ConnectionImpl& parent, uint32_t buffer_limit); | ||
| ~StreamImpl() override; | ||
| // TODO(mattklein123): Optimally this would be done in the destructor but there are currently | ||
| // deferred delete lifetime issues that need sorting out if the destructor of the stream is | ||
| // going to be able to refer to the parent connection. | ||
| virtual void destroy(); | ||
| void disarmStreamIdleTimer() { | ||
| if (stream_idle_timer_ != nullptr) { | ||
| // To ease testing and the destructor assertion. | ||
| stream_idle_timer_->disableTimer(); | ||
| stream_idle_timer_.reset(); | ||
| } | ||
| } | ||
|
|
||
| // Http::MultiplexedStreamImplBase | ||
| void destroy() override; | ||
| void onPendingFlushTimer() override; | ||
|
|
||
| StreamImpl* base() { return this; } | ||
| ssize_t onDataSourceRead(uint64_t length, uint32_t* data_flags); | ||
|
|
@@ -217,8 +208,6 @@ class ConnectionImpl : public virtual Connection, | |
| virtual HeaderMap& headers() PURE; | ||
| virtual void allocTrailers() PURE; | ||
| virtual HeaderMapPtr cloneTrailers(const HeaderMap& trailers) PURE; | ||
| virtual void createPendingFlushTimer() PURE; | ||
| void onPendingFlushTimer(); | ||
|
|
||
| // Http::StreamEncoder | ||
| void encodeData(Buffer::Instance& data, bool end_stream) override; | ||
|
|
@@ -236,9 +225,6 @@ class ConnectionImpl : public virtual Connection, | |
| return parent_.connection_.addressProvider().localAddress(); | ||
| } | ||
| absl::string_view responseDetails() override { return details_; } | ||
| void setFlushTimeout(std::chrono::milliseconds timeout) override { | ||
| stream_idle_timeout_ = timeout; | ||
| } | ||
| void setAccount(Buffer::BufferMemoryAccountSharedPtr account) override; | ||
|
|
||
| // ScopeTrackedObject | ||
|
|
@@ -317,9 +303,12 @@ class ConnectionImpl : public virtual Connection, | |
| bool pending_send_buffer_high_watermark_called_ : 1; | ||
| bool reset_due_to_messaging_error_ : 1; | ||
| absl::string_view details_; | ||
| // See HttpConnectionManager.stream_idle_timeout. | ||
| std::chrono::milliseconds stream_idle_timeout_{}; | ||
| Event::TimerPtr stream_idle_timer_; | ||
|
|
||
| protected: | ||
|
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. ditto on commenting the override.
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. Done. It is only used by base class. So I prefer keep it as protected. |
||
| // Http::MultiplexedStreamImplBase | ||
| bool hasPendingData() override { | ||
| return pending_send_data_->length() > 0 || pending_trailers_to_encode_ != nullptr; | ||
| } | ||
| }; | ||
|
|
||
| using StreamImplPtr = std::unique_ptr<StreamImpl>; | ||
|
|
@@ -333,6 +322,11 @@ class ConnectionImpl : public virtual Connection, | |
| : StreamImpl(parent, buffer_limit), response_decoder_(response_decoder), | ||
| headers_or_trailers_(ResponseHeaderMapImpl::create()) {} | ||
|
|
||
| // Http::MultiplexedStreamImplBase | ||
| void setFlushTimeout(std::chrono::milliseconds /*timeout*/) override { | ||
| // Client streams do not need a flush timer because we currently assume that any failure | ||
| // to flush would be covered by a request/stream/etc. timeout. | ||
| } | ||
| // StreamImpl | ||
| void submitHeaders(const std::vector<nghttp2_nv>& final_headers, | ||
| nghttp2_data_provider* provider) override; | ||
|
|
@@ -358,10 +352,6 @@ class ConnectionImpl : public virtual Connection, | |
| HeaderMapPtr cloneTrailers(const HeaderMap& trailers) override { | ||
| return createHeaderMap<RequestTrailerMapImpl>(trailers); | ||
| } | ||
| void createPendingFlushTimer() override { | ||
| // Client streams do not create a flush timer because we currently assume that any failure | ||
| // to flush would be covered by a request/stream/etc. timeout. | ||
| } | ||
|
|
||
| // RequestEncoder | ||
| Status encodeHeaders(const RequestHeaderMap& headers, bool end_stream) override; | ||
|
|
@@ -407,7 +397,6 @@ class ConnectionImpl : public virtual Connection, | |
| HeaderMapPtr cloneTrailers(const HeaderMap& trailers) override { | ||
| return createHeaderMap<ResponseTrailerMapImpl>(trailers); | ||
| } | ||
| void createPendingFlushTimer() override; | ||
| void resetStream(StreamResetReason reason) override; | ||
|
|
||
| // ResponseEncoder | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -66,6 +66,9 @@ Http::Status EnvoyQuicClientStream::encodeHeaders(const Http::RequestHeaderMap& | |
| } | ||
| } | ||
| WriteHeaders(std::move(spdy_headers), end_stream, nullptr); | ||
| if (local_end_stream_) { | ||
| onLocalEndStream(); | ||
| } | ||
| return Http::okStatus(); | ||
| } | ||
|
|
||
|
|
@@ -85,6 +88,9 @@ void EnvoyQuicClientStream::encodeData(Buffer::Instance& data, bool end_stream) | |
| Reset(quic::QUIC_BAD_APPLICATION_PAYLOAD); | ||
| return; | ||
| } | ||
| if (local_end_stream_) { | ||
| onLocalEndStream(); | ||
| } | ||
| } | ||
|
|
||
| void EnvoyQuicClientStream::encodeTrailers(const Http::RequestTrailerMap& trailers) { | ||
|
|
@@ -93,6 +99,7 @@ void EnvoyQuicClientStream::encodeTrailers(const Http::RequestTrailerMap& traile | |
| ENVOY_STREAM_LOG(debug, "encodeTrailers: {}.", *this, trailers); | ||
| ScopedWatermarkBufferUpdater updater(this, this); | ||
| WriteTrailers(envoyHeadersToSpdyHeaderBlock(trailers), nullptr); | ||
| onLocalEndStream(); | ||
| } | ||
|
|
||
| void EnvoyQuicClientStream::encodeMetadata(const Http::MetadataMapVector& /*metadata_map_vector*/) { | ||
|
|
@@ -271,6 +278,7 @@ void EnvoyQuicClientStream::OnConnectionClosed(quic::QuicErrorCode error, | |
| } | ||
|
|
||
| void EnvoyQuicClientStream::OnClose() { | ||
| destroy(); | ||
| quic::QuicSpdyClientStream::OnClose(); | ||
| if (isDoingWatermarkAccounting()) { | ||
| // This is called in the scope of a watermark buffer updater. Clear the | ||
|
|
@@ -321,5 +329,7 @@ void EnvoyQuicClientStream::onStreamError(absl::optional<bool> should_close_conn | |
| } | ||
| } | ||
|
|
||
| bool EnvoyQuicClientStream::hasPendingData() { return BufferedDataBytes() > 0; } | ||
|
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. Maybe comment how this plays with trailers?
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. done. I added comment in server stream to which this interface actually matters. |
||
|
|
||
| } // namespace Quic | ||
| } // namespace Envoy | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -70,6 +70,9 @@ class EnvoyQuicClientStream : public quic::QuicSpdyClientStream, | |
| void OnTrailingHeadersComplete(bool fin, size_t frame_len, | ||
| const quic::QuicHeaderList& header_list) override; | ||
|
|
||
| // Http::MultiplexedStreamImplBase | ||
| bool hasPendingData() override; | ||
|
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. should we disable flush timer for client streams as we do for HTTP/2? or maybe since we have separate classes only inherit for the server stream?
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. It is disabled via overriding setFlushTimeout() to no-op a few lines above.
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. ah, I missed it as it wasn't part of the diff, my bad! |
||
|
|
||
| private: | ||
| QuicFilterManagerConnectionImpl* filterManagerConnection(); | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
generally for overrides we comment the class it's from
// Http::MultiplexedStreamImplBase
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
done