Allow peers to pick low flow control limits in T099
Google QUIC requires flow control limits to be above 16K but IETF QUIC allows any values. In order to interoperate we need to allow low values in T099.
gfe-relnote: protected by disabled flag quic_supports_tls_handshake
PiperOrigin-RevId: 246002368
Change-Id: I5660e591256a355985877c2fb3c41fee06eb5a06
diff --git a/quic/core/quic_config.cc b/quic/core/quic_config.cc
index ef4fdad..cad98db 100644
--- a/quic/core/quic_config.cc
+++ b/quic/core/quic_config.cc
@@ -562,7 +562,7 @@
uint32_t window_bytes) {
if (window_bytes < kMinimumFlowControlSendWindow) {
QUIC_BUG << "Initial stream flow control receive window (" << window_bytes
- << ") cannot be set lower than default ("
+ << ") cannot be set lower than minimum ("
<< kMinimumFlowControlSendWindow << ").";
window_bytes = kMinimumFlowControlSendWindow;
}
diff --git a/quic/core/quic_constants.h b/quic/core/quic_constants.h
index a18c07b..81bed70 100644
--- a/quic/core/quic_constants.h
+++ b/quic/core/quic_constants.h
@@ -61,7 +61,10 @@
const QuicPacketCount kMaxInitialCongestionWindow = 200;
// Minimum size of initial flow control window, for both stream and session.
+// This is only enforced when version.AllowsLowFlowControlLimits() is false.
const uint32_t kMinimumFlowControlSendWindow = 16 * 1024; // 16 KB
+// Default size of initial flow control window, for both stream and session.
+const uint32_t kDefaultFlowControlSendWindow = 16 * 1024; // 16 KB
// Maximum flow control receive window limits for connection and stream.
const QuicByteCount kStreamReceiveWindowLimit = 16 * 1024 * 1024; // 16 MB
diff --git a/quic/core/quic_session.cc b/quic/core/quic_session.cc
index 2b9ffa5..5d02a12 100644
--- a/quic/core/quic_session.cc
+++ b/quic/core/quic_session.cc
@@ -69,7 +69,9 @@
this,
QuicUtils::GetInvalidStreamId(connection->transport_version()),
/*is_connection_flow_controller*/ true,
- kMinimumFlowControlSendWindow,
+ connection->version().AllowsLowFlowControlLimits()
+ ? 0
+ : kMinimumFlowControlSendWindow,
config_.GetInitialSessionFlowControlWindowToSend(),
kSessionReceiveWindowLimit,
perspective() == Perspective::IS_SERVER,
@@ -1054,10 +1056,11 @@
}
void QuicSession::OnNewStreamFlowControlWindow(QuicStreamOffset new_window) {
- if (new_window < kMinimumFlowControlSendWindow) {
+ if (new_window < kMinimumFlowControlSendWindow &&
+ !connection_->version().AllowsLowFlowControlLimits()) {
QUIC_LOG_FIRST_N(ERROR, 1)
<< "Peer sent us an invalid stream flow control send window: "
- << new_window << ", below default: " << kMinimumFlowControlSendWindow;
+ << new_window << ", below minimum: " << kMinimumFlowControlSendWindow;
if (connection_->connected()) {
connection_->CloseConnection(
QUIC_FLOW_CONTROL_INVALID_WINDOW, "New stream window too low",
@@ -1080,7 +1083,8 @@
}
void QuicSession::OnNewSessionFlowControlWindow(QuicStreamOffset new_window) {
- if (new_window < kMinimumFlowControlSendWindow) {
+ if (new_window < kMinimumFlowControlSendWindow &&
+ !connection_->version().AllowsLowFlowControlLimits()) {
QUIC_LOG_FIRST_N(ERROR, 1)
<< "Peer sent us an invalid session flow control send window: "
<< new_window << ", below default: " << kMinimumFlowControlSendWindow;
diff --git a/quic/core/quic_session_test.cc b/quic/core/quic_session_test.cc
index dddde7d..ad6d324 100644
--- a/quic/core/quic_session_test.cc
+++ b/quic/core/quic_session_test.cc
@@ -1448,8 +1448,12 @@
QuicConfigPeer::SetReceivedInitialStreamFlowControlWindow(session_.config(),
kInvalidWindow);
- EXPECT_CALL(*connection_,
- CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
+ if (!connection_->version().AllowsLowFlowControlLimits()) {
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
+ } else {
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
+ }
session_.OnConfigNegotiated();
}
@@ -1459,9 +1463,12 @@
const uint32_t kInvalidWindow = kMinimumFlowControlSendWindow - 1;
QuicConfigPeer::SetReceivedInitialSessionFlowControlWindow(session_.config(),
kInvalidWindow);
-
- EXPECT_CALL(*connection_,
- CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
+ if (!connection_->version().AllowsLowFlowControlLimits()) {
+ EXPECT_CALL(*connection_,
+ CloseConnection(QUIC_FLOW_CONTROL_INVALID_WINDOW, _, _));
+ } else {
+ EXPECT_CALL(*connection_, CloseConnection(_, _, _)).Times(0);
+ }
session_.OnConfigNegotiated();
}
diff --git a/quic/core/quic_stream.cc b/quic/core/quic_stream.cc
index 4fba898..f9b19b1 100644
--- a/quic/core/quic_stream.cc
+++ b/quic/core/quic_stream.cc
@@ -33,7 +33,7 @@
return session->config()->ReceivedInitialStreamFlowControlWindowBytes();
}
- return kMinimumFlowControlSendWindow;
+ return kDefaultFlowControlSendWindow;
}
} // namespace
diff --git a/quic/core/quic_versions.cc b/quic/core/quic_versions.cc
index a37f3a7..92232ba 100644
--- a/quic/core/quic_versions.cc
+++ b/quic/core/quic_versions.cc
@@ -42,6 +42,11 @@
handshake_protocol == PROTOCOL_TLS1_3;
}
+bool ParsedQuicVersion::AllowsLowFlowControlLimits() const {
+ return transport_version == QUIC_VERSION_99 &&
+ handshake_protocol == PROTOCOL_TLS1_3;
+}
+
std::ostream& operator<<(std::ostream& os, const ParsedQuicVersion& version) {
os << ParsedQuicVersionToString(version);
return os;
diff --git a/quic/core/quic_versions.h b/quic/core/quic_versions.h
index 160adeb..8da7361 100644
--- a/quic/core/quic_versions.h
+++ b/quic/core/quic_versions.h
@@ -147,6 +147,10 @@
}
bool KnowsWhichDecrypterToUse() const;
+
+ // Indicates that this QUIC version does not have an enforced minimum value
+ // for flow control values negotiated during the handshake.
+ bool AllowsLowFlowControlLimits() const;
};
QUIC_EXPORT_PRIVATE ParsedQuicVersion UnsupportedQuicVersion();