(n/a, not in use) add interfaces to set up peer address in QuicPacketCreator which the serialized packets are sent to through out the current call stack. No protected.
PiperOrigin-RevId: 328189072
Change-Id: I3c6d25aeb0f685891652519d62b92b1c0436d688
diff --git a/quic/core/quic_packet_creator.cc b/quic/core/quic_packet_creator.cc
index f842538..507a87a 100644
--- a/quic/core/quic_packet_creator.cc
+++ b/quic/core/quic_packet_creator.cc
@@ -2011,5 +2011,30 @@
return latched_hard_max_packet_length_ != 0;
}
+void QuicPacketCreator::SetDefaultPeerAddress(QuicSocketAddress address) {
+ if (!packet_.peer_address.IsInitialized()) {
+ packet_.peer_address = address;
+ return;
+ }
+ if (packet_.peer_address != address) {
+ FlushCurrentPacket();
+ packet_.peer_address = address;
+ }
+}
+
+QuicPacketCreator::ScopedPeerAddressContext::ScopedPeerAddressContext(
+ QuicPacketCreator* creator,
+ QuicSocketAddress address)
+ : creator_(creator), old_peer_address_(creator_->packet_.peer_address) {
+ QUIC_BUG_IF(!creator_->packet_.peer_address.IsInitialized())
+ << "Context is used before seralized packet's peer address is "
+ "initialized.";
+ creator_->SetDefaultPeerAddress(address);
+}
+
+QuicPacketCreator::ScopedPeerAddressContext::~ScopedPeerAddressContext() {
+ creator_->SetDefaultPeerAddress(old_peer_address_);
+}
+
#undef ENDPOINT // undef for jumbo builds
} // namespace quic
diff --git a/quic/core/quic_packet_creator.h b/quic/core/quic_packet_creator.h
index a225793..0fe3621 100644
--- a/quic/core/quic_packet_creator.h
+++ b/quic/core/quic_packet_creator.h
@@ -82,6 +82,20 @@
virtual void OnStreamFrameCoalesced(const QuicStreamFrame& /*frame*/) {}
};
+ // Set the peer address which the serialized packet will be sent to during the
+ // scope of this object. Upon exiting the scope, the original peer address is
+ // restored.
+ class QUIC_EXPORT_PRIVATE ScopedPeerAddressContext {
+ public:
+ ScopedPeerAddressContext(QuicPacketCreator* creator,
+ QuicSocketAddress address);
+ ~ScopedPeerAddressContext();
+
+ private:
+ QuicPacketCreator* creator_;
+ QuicSocketAddress old_peer_address_;
+ };
+
QuicPacketCreator(QuicConnectionId server_connection_id,
QuicFramer* framer,
DelegateInterface* delegate);
@@ -463,6 +477,10 @@
return coalesced_packet_of_higher_space_;
}
+ // Use this address to sent to the peer from now on. If this address is
+ // different from the current one, flush all the queue frames first.
+ void SetDefaultPeerAddress(QuicSocketAddress address);
+
private:
friend class test::QuicPacketCreatorPeer;
diff --git a/quic/core/quic_packet_creator_test.cc b/quic/core/quic_packet_creator_test.cc
index 60703fb..563f1eb 100644
--- a/quic/core/quic_packet_creator_test.cc
+++ b/quic/core/quic_packet_creator_test.cc
@@ -3833,6 +3833,134 @@
}
}
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ PeerAddressContextWithSameAddress) {
+ QuicSocketAddress peer_addr(QuicIpAddress::Any4(), 12345);
+ creator_.SetDefaultPeerAddress(peer_addr);
+ // Send some stream data.
+ MakeIOVector("foo", &iov_);
+ EXPECT_CALL(delegate_, ShouldGeneratePacket(_, _))
+ .WillRepeatedly(Return(true));
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(creator_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, NO_FIN);
+ EXPECT_EQ(3u, consumed.bytes_consumed);
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ {
+ // Set a different address via context which should trigger flush.
+ QuicPacketCreator::ScopedPeerAddressContext context(&creator_, peer_addr);
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ // Queue another STREAM_FRAME.
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(creator_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, FIN);
+ EXPECT_EQ(3u, consumed.bytes_consumed);
+ }
+ // After exiting the scope, the last queued frame should be flushed.
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(Invoke([=](SerializedPacket packet) {
+ EXPECT_EQ(peer_addr, packet.peer_address);
+ ASSERT_EQ(2u, packet.retransmittable_frames.size());
+ EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type);
+ EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.back().type);
+ }));
+ creator_.FlushCurrentPacket();
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ PeerAddressContextWithDifferentAddress) {
+ QuicSocketAddress peer_addr(QuicIpAddress::Any4(), 12345);
+ creator_.SetDefaultPeerAddress(peer_addr);
+ // Send some stream data.
+ MakeIOVector("foo", &iov_);
+ EXPECT_CALL(delegate_, ShouldGeneratePacket(_, _))
+ .WillRepeatedly(Return(true));
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(creator_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, NO_FIN);
+ EXPECT_EQ(3u, consumed.bytes_consumed);
+
+ QuicSocketAddress peer_addr1(QuicIpAddress::Any4(), 12346);
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(Invoke([=](SerializedPacket packet) {
+ EXPECT_EQ(peer_addr, packet.peer_address);
+ ASSERT_EQ(1u, packet.retransmittable_frames.size());
+ EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type);
+ }))
+ .WillOnce(Invoke([=](SerializedPacket packet) {
+ EXPECT_EQ(peer_addr1, packet.peer_address);
+ ASSERT_EQ(1u, packet.retransmittable_frames.size());
+ EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type);
+ }));
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ {
+ // Set a different address via context which should trigger flush.
+ QuicPacketCreator::ScopedPeerAddressContext context(&creator_, peer_addr1);
+ EXPECT_FALSE(creator_.HasPendingFrames());
+ // Queue another STREAM_FRAME.
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(creator_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, FIN);
+ EXPECT_EQ(3u, consumed.bytes_consumed);
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ }
+ // After exiting the scope, the last queued frame should be flushed.
+ EXPECT_FALSE(creator_.HasPendingFrames());
+}
+
+TEST_F(QuicPacketCreatorMultiplePacketsTest,
+ NestedPeerAddressContextWithDifferentAddress) {
+ QuicSocketAddress peer_addr(QuicIpAddress::Any4(), 12345);
+ creator_.SetDefaultPeerAddress(peer_addr);
+ QuicPacketCreator::ScopedPeerAddressContext context(&creator_, peer_addr);
+
+ // Send some stream data.
+ MakeIOVector("foo", &iov_);
+ EXPECT_CALL(delegate_, ShouldGeneratePacket(_, _))
+ .WillRepeatedly(Return(true));
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(creator_.transport_version(),
+ Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, NO_FIN);
+ EXPECT_EQ(3u, consumed.bytes_consumed);
+ EXPECT_TRUE(creator_.HasPendingFrames());
+
+ QuicSocketAddress peer_addr1(QuicIpAddress::Any4(), 12346);
+ EXPECT_CALL(delegate_, OnSerializedPacket(_))
+ .WillOnce(Invoke([=](SerializedPacket packet) {
+ EXPECT_EQ(peer_addr, packet.peer_address);
+ ASSERT_EQ(1u, packet.retransmittable_frames.size());
+ EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type);
+
+ // Set up another context with a different address.
+ QuicPacketCreator::ScopedPeerAddressContext context(&creator_,
+ peer_addr1);
+ MakeIOVector("foo", &iov_);
+ EXPECT_CALL(delegate_, ShouldGeneratePacket(_, _))
+ .WillRepeatedly(Return(true));
+ QuicConsumedData consumed = creator_.ConsumeData(
+ QuicUtils::GetFirstBidirectionalStreamId(
+ creator_.transport_version(), Perspective::IS_CLIENT),
+ &iov_, 1u, iov_.iov_len, 0, NO_FIN);
+ EXPECT_EQ(3u, consumed.bytes_consumed);
+ EXPECT_TRUE(creator_.HasPendingFrames());
+ // This should trigger another OnSerializedPacket() with the 2nd
+ // address.
+ creator_.FlushCurrentPacket();
+ }))
+ .WillOnce(Invoke([=](SerializedPacket packet) {
+ EXPECT_EQ(peer_addr1, packet.peer_address);
+ ASSERT_EQ(1u, packet.retransmittable_frames.size());
+ EXPECT_EQ(STREAM_FRAME, packet.retransmittable_frames.front().type);
+ }));
+ creator_.FlushCurrentPacket();
+}
+
} // namespace
} // namespace test
} // namespace quic
diff --git a/quic/core/quic_packets.cc b/quic/core/quic_packets.cc
index 6ffa39a..30bf334 100644
--- a/quic/core/quic_packets.cc
+++ b/quic/core/quic_packets.cc
@@ -475,7 +475,8 @@
transmission_type(other.transmission_type),
largest_acked(other.largest_acked),
has_ack_frame_copy(other.has_ack_frame_copy),
- fate(other.fate) {
+ fate(other.fate),
+ peer_address(other.peer_address) {
if (this != &other) {
if (release_encrypted_buffer && encrypted_buffer != nullptr) {
release_encrypted_buffer(encrypted_buffer);
@@ -519,6 +520,7 @@
copy->transmission_type = serialized.transmission_type;
copy->largest_acked = serialized.largest_acked;
copy->fate = serialized.fate;
+ copy->peer_address = serialized.peer_address;
if (copy_buffer) {
copy->encrypted_buffer = CopyBuffer(serialized);
diff --git a/quic/core/quic_packets.h b/quic/core/quic_packets.h
index 450b842..e00bcda 100644
--- a/quic/core/quic_packets.h
+++ b/quic/core/quic_packets.h
@@ -404,6 +404,7 @@
// nonretransmittable_frames.
bool has_ack_frame_copy;
SerializedPacketFate fate;
+ QuicSocketAddress peer_address;
};
// Make a copy of |serialized| (including the underlying frames). |copy_buffer|