Add two copy utility function CopyQuicFrame and CopyQuicFrames. gfe-relnote: n/a (add unused utility functions) PiperOrigin-RevId: 275463436 Change-Id: Ib084cac65d1cf9c060abe492cc47aa10032972f6
diff --git a/quic/core/frames/quic_frame.cc b/quic/core/frames/quic_frame.cc index 5e85fc0..e640179 100644 --- a/quic/core/frames/quic_frame.cc +++ b/quic/core/frames/quic_frame.cc
@@ -254,6 +254,101 @@ return copy; } +QuicFrame CopyQuicFrame(QuicBufferAllocator* allocator, + const QuicFrame& frame) { + QuicFrame copy; + switch (frame.type) { + case PADDING_FRAME: + copy = QuicFrame(QuicPaddingFrame(frame.padding_frame)); + break; + case RST_STREAM_FRAME: + copy = QuicFrame(new QuicRstStreamFrame(*frame.rst_stream_frame)); + break; + case CONNECTION_CLOSE_FRAME: + copy = QuicFrame( + new QuicConnectionCloseFrame(*frame.connection_close_frame)); + break; + case GOAWAY_FRAME: + copy = QuicFrame(new QuicGoAwayFrame(*frame.goaway_frame)); + break; + case WINDOW_UPDATE_FRAME: + copy = QuicFrame(new QuicWindowUpdateFrame(*frame.window_update_frame)); + break; + case BLOCKED_FRAME: + copy = QuicFrame(new QuicBlockedFrame(*frame.blocked_frame)); + break; + case STOP_WAITING_FRAME: + copy = QuicFrame(QuicStopWaitingFrame(frame.stop_waiting_frame)); + break; + case PING_FRAME: + copy = QuicFrame(QuicPingFrame(frame.ping_frame.control_frame_id)); + break; + case CRYPTO_FRAME: + copy = QuicFrame(new QuicCryptoFrame(*frame.crypto_frame)); + break; + case STREAM_FRAME: + copy = QuicFrame(QuicStreamFrame(frame.stream_frame)); + break; + case ACK_FRAME: + copy = QuicFrame(new QuicAckFrame(*frame.ack_frame)); + break; + case MTU_DISCOVERY_FRAME: + copy = QuicFrame(QuicMtuDiscoveryFrame(frame.mtu_discovery_frame)); + break; + case NEW_CONNECTION_ID_FRAME: + copy = QuicFrame( + new QuicNewConnectionIdFrame(*frame.new_connection_id_frame)); + break; + case MAX_STREAMS_FRAME: + copy = QuicFrame(QuicMaxStreamsFrame(frame.max_streams_frame)); + break; + case STREAMS_BLOCKED_FRAME: + copy = QuicFrame(QuicStreamsBlockedFrame(frame.streams_blocked_frame)); + break; + case PATH_RESPONSE_FRAME: + copy = QuicFrame(new QuicPathResponseFrame(*frame.path_response_frame)); + break; + case PATH_CHALLENGE_FRAME: + copy = QuicFrame(new QuicPathChallengeFrame(*frame.path_challenge_frame)); + break; + case STOP_SENDING_FRAME: + copy = QuicFrame(new QuicStopSendingFrame(*frame.stop_sending_frame)); + break; + case MESSAGE_FRAME: + copy = QuicFrame(new QuicMessageFrame(frame.message_frame->message_id)); + copy.message_frame->data = frame.message_frame->data; + copy.message_frame->message_length = frame.message_frame->message_length; + for (const auto& slice : frame.message_frame->message_data) { + QuicMemSlice copy_slice(allocator, slice.length()); + memcpy(const_cast<char*>(copy_slice.data()), slice.data(), + slice.length()); + copy.message_frame->message_data.push_back(std::move(copy_slice)); + } + break; + case NEW_TOKEN_FRAME: + copy = QuicFrame(new QuicNewTokenFrame(*frame.new_token_frame)); + break; + case RETIRE_CONNECTION_ID_FRAME: + copy = QuicFrame( + new QuicRetireConnectionIdFrame(*frame.retire_connection_id_frame)); + break; + default: + QUIC_BUG << "Cannot copy frame: " << frame; + copy = QuicFrame(QuicPingFrame(kInvalidControlFrameId)); + break; + } + return copy; +} + +QuicFrames CopyQuicFrames(QuicBufferAllocator* allocator, + const QuicFrames& frames) { + QuicFrames copy; + for (const auto& frame : frames) { + copy.push_back(CopyQuicFrame(allocator, frame)); + } + return copy; +} + std::ostream& operator<<(std::ostream& os, const QuicFrame& frame) { switch (frame.type) { case PADDING_FRAME: {
diff --git a/quic/core/frames/quic_frame.h b/quic/core/frames/quic_frame.h index 1fa9e01..226cbfb 100644 --- a/quic/core/frames/quic_frame.h +++ b/quic/core/frames/quic_frame.h
@@ -140,6 +140,14 @@ QUIC_EXPORT_PRIVATE QuicFrame CopyRetransmittableControlFrame(const QuicFrame& frame); +// Returns a copy of |frame|. +QUIC_EXPORT_PRIVATE QuicFrame CopyQuicFrame(QuicBufferAllocator* allocator, + const QuicFrame& frame); + +// Returns a copy of |frames|. +QUIC_EXPORT_PRIVATE QuicFrames CopyQuicFrames(QuicBufferAllocator* allocator, + const QuicFrames& frames); + // Human-readable description suitable for logging. QUIC_EXPORT_PRIVATE std::string QuicFramesToString(const QuicFrames& frames);
diff --git a/quic/core/frames/quic_frames_test.cc b/quic/core/frames/quic_frames_test.cc index 8492a0c..63fe653 100644 --- a/quic/core/frames/quic_frames_test.cc +++ b/quic/core/frames/quic_frames_test.cc
@@ -481,6 +481,104 @@ EXPECT_EQ(QuicPacketNumber(99u), ack_frame1.packets.Max()); } +TEST_F(QuicFramesTest, CopyQuicFrames) { + QuicFrames frames; + SimpleBufferAllocator allocator; + QuicMemSliceStorage storage(nullptr, 0, nullptr, 0); + QuicMessageFrame* message_frame = + new QuicMessageFrame(1, MakeSpan(&allocator, "message", &storage)); + // Construct a frame list. + for (uint8_t i = 0; i < NUM_FRAME_TYPES; ++i) { + switch (i) { + case PADDING_FRAME: + frames.push_back(QuicFrame(QuicPaddingFrame(-1))); + break; + case RST_STREAM_FRAME: + frames.push_back(QuicFrame(new QuicRstStreamFrame())); + break; + case CONNECTION_CLOSE_FRAME: + frames.push_back(QuicFrame(new QuicConnectionCloseFrame())); + break; + case GOAWAY_FRAME: + frames.push_back(QuicFrame(new QuicGoAwayFrame())); + break; + case WINDOW_UPDATE_FRAME: + frames.push_back(QuicFrame(new QuicWindowUpdateFrame())); + break; + case BLOCKED_FRAME: + frames.push_back(QuicFrame(new QuicBlockedFrame())); + break; + case STOP_WAITING_FRAME: + frames.push_back(QuicFrame(QuicStopWaitingFrame())); + break; + case PING_FRAME: + frames.push_back(QuicFrame(QuicPingFrame())); + break; + case CRYPTO_FRAME: + frames.push_back(QuicFrame(new QuicCryptoFrame())); + break; + case STREAM_FRAME: + frames.push_back(QuicFrame(QuicStreamFrame())); + break; + case ACK_FRAME: + frames.push_back(QuicFrame(new QuicAckFrame())); + break; + case MTU_DISCOVERY_FRAME: + frames.push_back(QuicFrame(QuicMtuDiscoveryFrame())); + break; + case NEW_CONNECTION_ID_FRAME: + frames.push_back(QuicFrame(new QuicNewConnectionIdFrame())); + break; + case MAX_STREAMS_FRAME: + frames.push_back(QuicFrame(QuicMaxStreamsFrame())); + break; + case STREAMS_BLOCKED_FRAME: + frames.push_back(QuicFrame(QuicStreamsBlockedFrame())); + break; + case PATH_RESPONSE_FRAME: + frames.push_back(QuicFrame(new QuicPathResponseFrame())); + break; + case PATH_CHALLENGE_FRAME: + frames.push_back(QuicFrame(new QuicPathChallengeFrame())); + break; + case STOP_SENDING_FRAME: + frames.push_back(QuicFrame(new QuicStopSendingFrame())); + break; + case MESSAGE_FRAME: + frames.push_back(QuicFrame(message_frame)); + break; + case NEW_TOKEN_FRAME: + frames.push_back(QuicFrame(new QuicNewTokenFrame())); + break; + case RETIRE_CONNECTION_ID_FRAME: + frames.push_back(QuicFrame(new QuicRetireConnectionIdFrame())); + break; + default: + ASSERT_TRUE(false) + << "Please fix CopyQuicFrames if a new frame type is added."; + break; + } + } + + QuicFrames copy = CopyQuicFrames(&allocator, frames); + ASSERT_EQ(NUM_FRAME_TYPES, copy.size()); + for (uint8_t i = 0; i < NUM_FRAME_TYPES; ++i) { + EXPECT_EQ(i, copy[i].type); + if (i != MESSAGE_FRAME) { + continue; + } + // Verify message frame is correctly copied. + EXPECT_EQ(1u, copy[i].message_frame->message_id); + EXPECT_EQ(nullptr, copy[i].message_frame->data); + EXPECT_EQ(7u, copy[i].message_frame->message_length); + ASSERT_EQ(1u, copy[i].message_frame->message_data.size()); + EXPECT_EQ(0, memcmp(copy[i].message_frame->message_data[0].data(), + frames[i].message_frame->message_data[0].data(), 7)); + } + DeleteFrames(&frames); + DeleteFrames(©); +} + class PacketNumberQueueTest : public QuicTest {}; // Tests that a queue contains the expected data after calls to Add().