mirror of
https://github.com/facebookincubator/mvfst.git
synced 2025-11-07 22:46:22 +03:00
Key update support: Add support for initiating periodic key updates for both client and server [4/x]
Summary: Allow the server/client transport to initiate periodic key update. It's defaulted to being disabled. The new logic for initiating and verifying a key update was handled correctly by the peer is consolidated in QuicTransportFunctions. Reviewed By: mjoras Differential Revision: D53109624 fbshipit-source-id: 0c3a944978fc0e0a84252da953dc116aa7c26379
This commit is contained in:
committed by
Facebook GitHub Bot
parent
da3e5e3821
commit
aeacf40ae8
@@ -843,7 +843,20 @@ void updateConnection(
|
||||
conn.lossState.totalPacketsSent++;
|
||||
conn.lossState.totalStreamBytesSent += streamBytesSent;
|
||||
conn.lossState.totalNewStreamBytesSent += newStreamBytesSent;
|
||||
conn.oneRttWritePacketsSentInCurrentPhase++;
|
||||
|
||||
// Count the number of packets sent in the current phase.
|
||||
// This is used to initiate key updates if enabled.
|
||||
if (packet.header.getProtectionType() == conn.oneRttWritePhase) {
|
||||
if (conn.oneRttWritePendingVerification &&
|
||||
conn.oneRttWritePacketsSentInCurrentPhase == 0) {
|
||||
// This is the first packet in the new phase after we have initiated a key
|
||||
// update. We need to keep track of it to confirm the peer acks it in the
|
||||
// same phase.
|
||||
conn.oneRttWritePendingVerificationPacketNumber =
|
||||
packet.header.getPacketSequenceNum();
|
||||
}
|
||||
conn.oneRttWritePacketsSentInCurrentPhase++;
|
||||
}
|
||||
|
||||
if (!retransmittable && !isPing) {
|
||||
DCHECK(!packetEvent);
|
||||
@@ -1340,7 +1353,7 @@ void writeShortClose(
|
||||
const Aead& aead,
|
||||
const PacketNumberCipher& headerCipher) {
|
||||
auto header = ShortHeader(
|
||||
ProtectionType::KeyPhaseZero,
|
||||
connection.oneRttWritePhase,
|
||||
connId,
|
||||
getNextPacketNum(connection, PacketNumberSpace::AppData));
|
||||
writeCloseCommon(
|
||||
@@ -1919,4 +1932,66 @@ void updateOneRttWriteCipher(
|
||||
conn.oneRttWritePhase = oneRttPhase;
|
||||
conn.oneRttWritePacketsSentInCurrentPhase = 0;
|
||||
}
|
||||
|
||||
void maybeHandleIncomingKeyUpdate(QuicConnectionStateBase& conn) {
|
||||
if (conn.readCodec->getCurrentOneRttReadPhase() != conn.oneRttWritePhase) {
|
||||
// Peer has initiated a key update.
|
||||
updateOneRttWriteCipher(
|
||||
conn,
|
||||
conn.handshakeLayer->getNextOneRttWriteCipher(),
|
||||
conn.readCodec->getCurrentOneRttReadPhase());
|
||||
|
||||
conn.readCodec->setNextOneRttReadCipher(
|
||||
conn.handshakeLayer->getNextOneRttReadCipher());
|
||||
}
|
||||
}
|
||||
|
||||
void maybeInitiateKeyUpdate(QuicConnectionStateBase& conn) {
|
||||
if (conn.transportSettings.initiateKeyUpdate &&
|
||||
conn.oneRttWritePacketsSentInCurrentPhase >
|
||||
conn.transportSettings.keyUpdatePacketCountInterval) {
|
||||
if (conn.readCodec->canInitiateKeyUpdate()) {
|
||||
conn.readCodec->advanceOneRttReadPhase();
|
||||
|
||||
updateOneRttWriteCipher(
|
||||
conn,
|
||||
conn.handshakeLayer->getNextOneRttWriteCipher(),
|
||||
conn.readCodec->getCurrentOneRttReadPhase());
|
||||
conn.readCodec->setNextOneRttReadCipher(
|
||||
conn.handshakeLayer->getNextOneRttReadCipher());
|
||||
// Signal the transport that a key update has been initiated.
|
||||
conn.oneRttWritePendingVerification = true;
|
||||
conn.oneRttWritePendingVerificationPacketNumber.clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void maybeVerifyPendingKeyUpdate(
|
||||
QuicConnectionStateBase& conn,
|
||||
const OutstandingPacketWrapper& outstandingPacket,
|
||||
const RegularQuicPacket& ackPacket) {
|
||||
if (!(protectionTypeToEncryptionLevel(
|
||||
outstandingPacket.packet.header.getProtectionType()) ==
|
||||
EncryptionLevel::AppData)) {
|
||||
// This is not an app data packet. We can't have initiated a key update yet.
|
||||
return;
|
||||
}
|
||||
|
||||
if (conn.oneRttWritePendingVerificationPacketNumber &&
|
||||
outstandingPacket.packet.header.getPacketSequenceNum() >=
|
||||
conn.oneRttWritePendingVerificationPacketNumber.value()) {
|
||||
// There is a pending key update. This packet should be acked in
|
||||
// the current phase.
|
||||
if (ackPacket.header.getProtectionType() == conn.oneRttWritePhase) {
|
||||
// Key update is verified.
|
||||
conn.oneRttWritePendingVerificationPacketNumber.clear();
|
||||
conn.oneRttWritePendingVerification = false;
|
||||
} else {
|
||||
throw QuicTransportException(
|
||||
"Packet with key update was acked in the wrong phase",
|
||||
TransportErrorCode::CRYPTO_ERROR);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace quic
|
||||
|
||||
Reference in New Issue
Block a user