-
Notifications
You must be signed in to change notification settings - Fork 5.3k
quiche: add support of delayed close to QUIC session #9163
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
67d6cb5
f783bc3
40ab281
6c5a4f4
a6f2e4e
5642cf8
9a79cb9
8b3e75c
770e242
d704d78
322190a
c68a66c
16fd27a
f0bf8aa
a1b57d6
2d877c6
40b7c21
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 |
|---|---|---|
|
|
@@ -50,20 +50,46 @@ bool QuicFilterManagerConnectionImpl::aboveHighWatermark() const { | |
| } | ||
|
|
||
| void QuicFilterManagerConnectionImpl::close(Network::ConnectionCloseType type) { | ||
| if (type != Network::ConnectionCloseType::NoFlush) { | ||
| // TODO(danzh): Implement FlushWrite and FlushWriteAndDelay mode. | ||
| } | ||
| if (quic_connection_ == nullptr) { | ||
| // Already detached from quic connection. | ||
| return; | ||
| } | ||
| closeConnectionImmediately(); | ||
| } | ||
|
|
||
| void QuicFilterManagerConnectionImpl::setDelayedCloseTimeout(std::chrono::milliseconds timeout) { | ||
| if (timeout != std::chrono::milliseconds::zero()) { | ||
| // TODO(danzh) support delayed close of connection. | ||
| NOT_IMPLEMENTED_GCOVR_EXCL_LINE; | ||
| const bool delayed_close_timeout_configured = delayed_close_timeout_.count() > 0; | ||
| if (hasDataToWrite() && type != Network::ConnectionCloseType::NoFlush) { | ||
| if (delayed_close_timeout_configured) { | ||
| // QUIC connection has unsent data and caller wants to flush them. Wait for flushing or | ||
| // timeout. | ||
| if (!inDelayedClose()) { | ||
| // Only set alarm if not in delay close mode yet. | ||
| initializeDelayedCloseTimer(); | ||
| } | ||
| // Update delay close state according to current call. | ||
| if (type == Network::ConnectionCloseType::FlushWriteAndDelay) { | ||
| delayed_close_state_ = DelayedCloseState::CloseAfterFlushAndWait; | ||
| } else { | ||
| ASSERT(type == Network::ConnectionCloseType::FlushWrite); | ||
| delayed_close_state_ = DelayedCloseState::CloseAfterFlush; | ||
| } | ||
| } else { | ||
| delayed_close_state_ = DelayedCloseState::CloseAfterFlush; | ||
| } | ||
| } else if (hasDataToWrite()) { | ||
| // Quic connection has unsent data but caller wants to close right away. | ||
| ASSERT(type == Network::ConnectionCloseType::NoFlush); | ||
| quic_connection_->OnCanWrite(); | ||
| closeConnectionImmediately(); | ||
| } else { | ||
| // Quic connection doesn't have unsent data. It's up to the caller and | ||
| // the configuration whether to wait or not before closing. | ||
| if (delayed_close_timeout_configured && | ||
|
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 have one if for delayed_close_timeout_configured and have the above code and this code in it?
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. But due to the intertwine of ConnectionCloseType and the presence of delayed_close_time in config, I feel it doesn't simplify the logic much... |
||
| type == Network::ConnectionCloseType::FlushWriteAndDelay) { | ||
| if (!inDelayedClose()) { | ||
| initializeDelayedCloseTimer(); | ||
| } | ||
| delayed_close_state_ = DelayedCloseState::CloseAfterFlushAndWait; | ||
| } else { | ||
| closeConnectionImmediately(); | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -102,6 +128,21 @@ void QuicFilterManagerConnectionImpl::adjustBytesToSend(int64_t delta) { | |
| write_buffer_watermark_simulation_.checkLowWatermark(bytes_to_send_); | ||
| } | ||
|
|
||
| void QuicFilterManagerConnectionImpl::maybeApplyDelayClosePolicy() { | ||
| if (!inDelayedClose()) { | ||
| return; | ||
| } | ||
| if (hasDataToWrite() || delayed_close_state_ == DelayedCloseState::CloseAfterFlushAndWait) { | ||
| if (delayed_close_timer_ != nullptr) { | ||
| // Re-arm delay close timer on every write event if there are still data | ||
| // buffered or the connection close is supposed to be delayed. | ||
| delayed_close_timer_->enableTimer(delayed_close_timeout_); | ||
| } | ||
| } else { | ||
| closeConnectionImmediately(); | ||
| } | ||
| } | ||
|
|
||
| void QuicFilterManagerConnectionImpl::onConnectionCloseEvent( | ||
| const quic::QuicConnectionCloseFrame& frame, quic::ConnectionCloseSource source) { | ||
| transport_failure_reason_ = absl::StrCat(quic::QuicErrorCodeToString(frame.quic_error_code), | ||
|
|
@@ -115,6 +156,9 @@ void QuicFilterManagerConnectionImpl::onConnectionCloseEvent( | |
| } | ||
|
|
||
| void QuicFilterManagerConnectionImpl::closeConnectionImmediately() { | ||
| if (quic_connection_ == nullptr) { | ||
| return; | ||
| } | ||
| quic_connection_->CloseConnection(quic::QUIC_NO_ERROR, "Closed by application", | ||
| quic::ConnectionCloseBehavior::SEND_CONNECTION_CLOSE_PACKET); | ||
| quic_connection_ = nullptr; | ||
|
|
||
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.
revert?
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.
These are format fixes for previous change