-
Notifications
You must be signed in to change notification settings - Fork 5.5k
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 10 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 |
|---|---|---|
|
|
@@ -92,12 +92,26 @@ void EnvoyQuicServerSession::SendGoAway(quic::QuicErrorCode error_code, const st | |
| } | ||
| } | ||
|
|
||
| void EnvoyQuicServerSession::OnCanWrite() { | ||
| quic::QuicServerSessionBase::OnCanWrite(); | ||
| if (inDelayedClose() && !HasDataToWrite()) { | ||
| if (delayed_close_state_ == DelayedCloseState::CloseAfterFlushAndWait) { | ||
| ASSERT(delayed_close_timer_ != nullptr); | ||
| delayed_close_timer_->enableTimer(delayed_close_timeout_); | ||
| } else { | ||
| closeConnectionImmediately(); | ||
| } | ||
|
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. If there is data to write, don't we update the delay close timer to now + delay close?
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. The timer is set when close() is called. I don't think we postpone it whenever we get a chance to write, do we?
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. The docs say it's timeout interval after the last write, e.g. // The socket will be closed immediately after the buffer is flushed or if a period of and I believe the TCP stack re-arms the timer after each write
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. Woops, I totally missed this. I changed OnCanWrite() to re-arm timer for that case now. |
||
| } | ||
| } | ||
|
|
||
| void EnvoyQuicServerSession::OnCryptoHandshakeEvent(CryptoHandshakeEvent event) { | ||
| quic::QuicServerSessionBase::OnCryptoHandshakeEvent(event); | ||
| if (event == HANDSHAKE_CONFIRMED) { | ||
| raiseConnectionEvent(Network::ConnectionEvent::Connected); | ||
| } | ||
| } | ||
|
|
||
| bool EnvoyQuicServerSession::hasDataToWrite() { return HasDataToWrite(); } | ||
|
|
||
| } // namespace Quic | ||
| } // namespace Envoy | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -50,20 +50,43 @@ 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) { | ||
| // QUIC connection has unsent data and caller wants to flush them. Wait for flushing or timeout. | ||
| if (!inDelayedClose() && delayed_close_timeout_configured) { | ||
| // Only set alarm if not in delay close mode yet. | ||
| initializeDelayedCloseTimer(); | ||
| } | ||
| // Update delay close state according to current call. | ||
| 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) { | ||
| delayed_close_state_ = DelayedCloseState::CloseAfterFlushAndWait; | ||
| } else { | ||
| delayed_close_state_ = DelayedCloseState::CloseAfterFlush; | ||
| } | ||
| } else { | ||
|
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. I think we could remove this else, and just have else if (hasDataToWrite()) {} else { // type == NoFlush
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. good point! Done |
||
| 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 upto caller and | ||
|
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. upto -> up to the
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 |
||
| // configuration whether to wait or not before closing. | ||
| if (delayed_close_timeout_configured && | ||
| type == Network::ConnectionCloseType::FlushWriteAndDelay) { | ||
| if (!inDelayedClose()) { | ||
| initializeDelayedCloseTimer(); | ||
| } | ||
| delayed_close_state_ = DelayedCloseState::CloseAfterFlushAndWait; | ||
| } else { | ||
| closeConnectionImmediately(); | ||
| } | ||
| } | ||
| } | ||
| } | ||
|
|
||
|
|
@@ -115,6 +138,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