(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|