mirror of
https://github.com/facebookincubator/mvfst.git
synced 2026-01-06 03:41:10 +03:00
Encode packet header after Quic cloner is sure the packet can be cloned
Summary: otherwise we keep encoding packet headers and potentially write into the write buffer without actually generating a packet. It leaves a trail of bad headers inside the buffer Reviewed By: mjoras Differential Revision: D21626733 fbshipit-source-id: 3bdcf6277beccb09b390a590ba2bb0eb8e68e6c1
This commit is contained in:
committed by
Facebook GitHub Bot
parent
8715ddfc44
commit
da3eb41a78
@@ -541,6 +541,12 @@ SchedulingResult CloningScheduler::scheduleFramesForPacket(
|
||||
if (opPnSpace != PacketNumberSpace::AppData) {
|
||||
continue;
|
||||
}
|
||||
size_t prevSize = 0;
|
||||
if (conn_.transportSettings.dataPathType ==
|
||||
DataPathType::ContinuousMemory) {
|
||||
ScopedBufAccessor scopedBufAccessor(conn_.bufAccessor);
|
||||
prevSize = scopedBufAccessor.buf()->length();
|
||||
}
|
||||
// Reusing the same builder throughout loop bodies will lead to frames
|
||||
// belong to different original packets being written into the same clone
|
||||
// packet. So re-create a builder every time.
|
||||
@@ -560,9 +566,6 @@ SchedulingResult CloningScheduler::scheduleFramesForPacket(
|
||||
header,
|
||||
getAckState(conn_, builderPnSpace).largestAckedByPeer);
|
||||
}
|
||||
internalBuilder->setCipherOverhead(cipherOverhead_);
|
||||
internalBuilder->encodePacketHeader();
|
||||
PacketRebuilder rebuilder(*internalBuilder, conn_);
|
||||
// We shouldn't clone Handshake packet.
|
||||
if (iter->isHandshake) {
|
||||
continue;
|
||||
@@ -573,13 +576,16 @@ SchedulingResult CloningScheduler::scheduleFramesForPacket(
|
||||
conn_.outstandingPacketEvents.count(*iter->associatedEvent) == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// The writableBytes here is an optimization. If the writableBytes is too
|
||||
// small for this packet. rebuildFromPacket should fail anyway.
|
||||
// I think this only fail if udpSendPacketLen somehow shrinks in the middle
|
||||
// of a connection.
|
||||
if (iter->encodedSize > writableBytes + cipherOverhead_) {
|
||||
continue;
|
||||
}
|
||||
|
||||
internalBuilder->setCipherOverhead(cipherOverhead_);
|
||||
internalBuilder->encodePacketHeader();
|
||||
PacketRebuilder rebuilder(*internalBuilder, conn_);
|
||||
|
||||
// TODO: It's possible we write out a packet that's larger than the packet
|
||||
// size limit. For example, when the packet sequence number has advanced to
|
||||
// a point where we need more bytes to encoded it than that of the original
|
||||
@@ -593,6 +599,22 @@ SchedulingResult CloningScheduler::scheduleFramesForPacket(
|
||||
if (rebuildResult) {
|
||||
return SchedulingResult(
|
||||
std::move(rebuildResult), std::move(*internalBuilder).buildPacket());
|
||||
} else if (
|
||||
conn_.transportSettings.dataPathType ==
|
||||
DataPathType::ContinuousMemory) {
|
||||
// When we use Inplace packet building and reuse the write buffer, even if
|
||||
// the packet rebuild has failed, there might be some bytes already
|
||||
// written into the buffer and the buffer tail pointer has already moved.
|
||||
// We need to roll back the tail pointer to the position before the packet
|
||||
// building to exclude those bytes. Otherwise these bytes will be sitting
|
||||
// in between legit packets inside the buffer and will either cause errors
|
||||
// further down the write path, or be sent out and then dropped at peer
|
||||
// when peer fail to parse them.
|
||||
internalBuilder.reset();
|
||||
CHECK(conn_.bufAccessor && conn_.bufAccessor->ownsBuffer());
|
||||
ScopedBufAccessor scopedBufAccessor(conn_.bufAccessor);
|
||||
auto& buf = scopedBufAccessor.buf();
|
||||
buf->trimEnd(buf->length() - prevSize);
|
||||
}
|
||||
}
|
||||
return SchedulingResult(folly::none, folly::none);
|
||||
|
||||
Reference in New Issue
Block a user