Project import generated by Copybara.
PiperOrigin-RevId: 237361882
Change-Id: I109a68f44db867b20f8c6a7732b0ce657133e52a
diff --git a/quic/core/quic_packet_creator.h b/quic/core/quic_packet_creator.h
new file mode 100644
index 0000000..f4512c3
--- /dev/null
+++ b/quic/core/quic_packet_creator.h
@@ -0,0 +1,416 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+// Accumulates frames for the next packet until more frames no longer fit or
+// it's time to create a packet from them.
+
+#ifndef QUICHE_QUIC_CORE_QUIC_PACKET_CREATOR_H_
+#define QUICHE_QUIC_CORE_QUIC_PACKET_CREATOR_H_
+
+#include <cstddef>
+#include <memory>
+#include <utility>
+#include <vector>
+
+#include "base/macros.h"
+#include "net/third_party/quiche/src/quic/core/quic_connection_close_delegate_interface.h"
+#include "net/third_party/quiche/src/quic/core/quic_framer.h"
+#include "net/third_party/quiche/src/quic/core/quic_packets.h"
+#include "net/third_party/quiche/src/quic/core/quic_pending_retransmission.h"
+#include "net/third_party/quiche/src/quic/core/quic_types.h"
+#include "net/third_party/quiche/src/quic/platform/api/quic_export.h"
+
+namespace quic {
+namespace test {
+class QuicPacketCreatorPeer;
+}
+
+class QUIC_EXPORT_PRIVATE QuicPacketCreator {
+ public:
+ // A delegate interface for further processing serialized packet.
+ class QUIC_EXPORT_PRIVATE DelegateInterface
+ : public QuicConnectionCloseDelegateInterface {
+ public:
+ ~DelegateInterface() override {}
+ // Get a buffer of kMaxPacketSize bytes to serialize the next packet.
+ // If return nullptr, QuicPacketCreator will serialize on a stack buffer.
+ virtual char* GetPacketBuffer() = 0;
+ // Called when a packet is serialized. Delegate does not take the ownership
+ // of |serialized_packet|, but takes ownership of any frames it removes
+ // from |packet.retransmittable_frames|.
+ virtual void OnSerializedPacket(SerializedPacket* serialized_packet) = 0;
+ };
+
+ // Interface which gets callbacks from the QuicPacketCreator at interesting
+ // points. Implementations must not mutate the state of the creator
+ // as a result of these callbacks.
+ class QUIC_EXPORT_PRIVATE DebugDelegate {
+ public:
+ virtual ~DebugDelegate() {}
+
+ // Called when a frame has been added to the current packet.
+ virtual void OnFrameAddedToPacket(const QuicFrame& frame) {}
+ };
+
+ QuicPacketCreator(QuicConnectionId connection_id,
+ QuicFramer* framer,
+ DelegateInterface* delegate);
+ QuicPacketCreator(QuicConnectionId connection_id,
+ QuicFramer* framer,
+ QuicRandom* random,
+ DelegateInterface* delegate);
+ QuicPacketCreator(const QuicPacketCreator&) = delete;
+ QuicPacketCreator& operator=(const QuicPacketCreator&) = delete;
+
+ ~QuicPacketCreator();
+
+ // Makes the framer not serialize the protocol version in sent packets.
+ void StopSendingVersion();
+
+ // SetDiversificationNonce sets the nonce that will be sent in each public
+ // header of packets encrypted at the initial encryption level. Should only
+ // be called by servers.
+ void SetDiversificationNonce(const DiversificationNonce& nonce);
+
+ // Update the packet number length to use in future packets as soon as it
+ // can be safely changed.
+ // TODO(fayang): Directly set packet number length instead of compute it in
+ // creator.
+ void UpdatePacketNumberLength(QuicPacketNumber least_packet_awaited_by_peer,
+ QuicPacketCount max_packets_in_flight);
+
+ // The overhead the framing will add for a packet with one frame.
+ static size_t StreamFramePacketOverhead(
+ QuicTransportVersion version,
+ QuicConnectionIdLength destination_connection_id_length,
+ QuicConnectionIdLength source_connection_id_length,
+ bool include_version,
+ bool include_diversification_nonce,
+ QuicPacketNumberLength packet_number_length,
+ QuicVariableLengthIntegerLength retry_token_length_length,
+ QuicVariableLengthIntegerLength length_length,
+ QuicStreamOffset offset);
+
+ // Returns false and flushes all pending frames if current open packet is
+ // full.
+ // If current packet is not full, creates a stream frame that fits into the
+ // open packet and adds it to the packet.
+ bool ConsumeData(QuicStreamId id,
+ size_t write_length,
+ size_t iov_offset,
+ QuicStreamOffset offset,
+ bool fin,
+ bool needs_full_padding,
+ TransmissionType transmission_type,
+ QuicFrame* frame);
+
+ // Creates a CRYPTO frame that fits into the current packet (which must be
+ // empty) and adds it to the packet.
+ bool ConsumeCryptoData(EncryptionLevel level,
+ size_t write_length,
+ QuicStreamOffset offset,
+ TransmissionType transmission_type,
+ QuicFrame* frame);
+
+ // Returns true if current open packet can accommodate more stream frames of
+ // stream |id| at |offset| and data length |data_size|, false otherwise.
+ bool HasRoomForStreamFrame(QuicStreamId id,
+ QuicStreamOffset offset,
+ size_t data_size);
+
+ // Returns true if current open packet can accommodate a message frame of
+ // |length|.
+ bool HasRoomForMessageFrame(QuicByteCount length);
+
+ // Re-serializes frames with the original packet's packet number length.
+ // Used for retransmitting packets to ensure they aren't too long.
+ void ReserializeAllFrames(const QuicPendingRetransmission& retransmission,
+ char* buffer,
+ size_t buffer_len);
+
+ // Serializes all added frames into a single packet and invokes the delegate_
+ // to further process the SerializedPacket.
+ void Flush();
+
+ // Optimized method to create a QuicStreamFrame and serialize it. Adds the
+ // QuicStreamFrame to the returned SerializedPacket. Sets
+ // |num_bytes_consumed| to the number of bytes consumed to create the
+ // QuicStreamFrame.
+ void CreateAndSerializeStreamFrame(QuicStreamId id,
+ size_t write_length,
+ QuicStreamOffset iov_offset,
+ QuicStreamOffset stream_offset,
+ bool fin,
+ TransmissionType transmission_type,
+ size_t* num_bytes_consumed);
+
+ // Returns true if there are frames pending to be serialized.
+ bool HasPendingFrames() const;
+
+ // Returns true if there are retransmittable frames pending to be serialized.
+ bool HasPendingRetransmittableFrames() const;
+
+ // Returns true if there are stream frames for |id| pending to be serialized.
+ bool HasPendingStreamFramesOfStream(QuicStreamId id) const;
+
+ // Returns the number of bytes which are available to be used by additional
+ // frames in the packet. Since stream frames are slightly smaller when they
+ // are the last frame in a packet, this method will return a different
+ // value than max_packet_size - PacketSize(), in this case.
+ size_t BytesFree();
+
+ // Returns the number of bytes that the packet will expand by if a new frame
+ // is added to the packet. If the last frame was a stream frame, it will
+ // expand slightly when a new frame is added, and this method returns the
+ // amount of expected expansion.
+ size_t ExpansionOnNewFrame() const;
+
+ // Returns the number of bytes in the current packet, including the header,
+ // if serialized with the current frames. Adding a frame to the packet
+ // may change the serialized length of existing frames, as per the comment
+ // in BytesFree.
+ size_t PacketSize();
+
+ // Tries to add |frame| to the packet creator's list of frames to be
+ // serialized. If the frame does not fit into the current packet, flushes the
+ // packet and returns false.
+ bool AddSavedFrame(const QuicFrame& frame,
+ TransmissionType transmission_type);
+
+ // Identical to AddSavedFrame, but allows the frame to be padded.
+ bool AddPaddedSavedFrame(const QuicFrame& frame,
+ TransmissionType transmission_type);
+
+ // Creates a version negotiation packet which supports |supported_versions|.
+ std::unique_ptr<QuicEncryptedPacket> SerializeVersionNegotiationPacket(
+ bool ietf_quic,
+ const ParsedQuicVersionVector& supported_versions);
+
+ // Creates a connectivity probing packet for versions prior to version 99.
+ OwningSerializedPacketPointer SerializeConnectivityProbingPacket();
+
+ // Create connectivity probing request and response packets using PATH
+ // CHALLENGE and PATH RESPONSE frames, respectively, for version 99/IETF QUIC.
+ // SerializePathChallengeConnectivityProbingPacket will pad the packet to be
+ // MTU bytes long.
+ OwningSerializedPacketPointer SerializePathChallengeConnectivityProbingPacket(
+ QuicPathFrameBuffer* payload);
+
+ // If |is_padded| is true then SerializePathResponseConnectivityProbingPacket
+ // will pad the packet to be MTU bytes long, else it will not pad the packet.
+ // |payloads| is cleared.
+ OwningSerializedPacketPointer SerializePathResponseConnectivityProbingPacket(
+ const QuicDeque<QuicPathFrameBuffer>& payloads,
+ const bool is_padded);
+
+ // Returns a dummy packet that is valid but contains no useful information.
+ static SerializedPacket NoPacket();
+
+ // Returns length of destination connection ID to send over the wire.
+ QuicConnectionIdLength GetDestinationConnectionIdLength() const;
+
+ // Returns length of source connection ID to send over the wire.
+ QuicConnectionIdLength GetSourceConnectionIdLength() const;
+
+ // Sets whether the connection ID should be sent over the wire.
+ void SetConnectionIdIncluded(QuicConnectionIdIncluded connection_id_included);
+
+ // Sets the encryption level that will be applied to new packets.
+ void set_encryption_level(EncryptionLevel level) {
+ packet_.encryption_level = level;
+ }
+
+ // packet number of the last created packet, or 0 if no packets have been
+ // created.
+ QuicPacketNumber packet_number() const { return packet_.packet_number; }
+
+ QuicByteCount max_packet_length() const { return max_packet_length_; }
+
+ bool has_ack() const { return packet_.has_ack; }
+
+ bool has_stop_waiting() const { return packet_.has_stop_waiting; }
+
+ // Sets the encrypter to use for the encryption level and updates the max
+ // plaintext size.
+ void SetEncrypter(EncryptionLevel level,
+ std::unique_ptr<QuicEncrypter> encrypter);
+
+ // Indicates whether the packet creator is in a state where it can change
+ // current maximum packet length.
+ bool CanSetMaxPacketLength() const;
+
+ // Sets the maximum packet length.
+ void SetMaxPacketLength(QuicByteCount length);
+
+ // Increases pending_padding_bytes by |size|. Pending padding will be sent by
+ // MaybeAddPadding().
+ void AddPendingPadding(QuicByteCount size);
+
+ // Sets transmission type of next constructed packets.
+ void SetTransmissionType(TransmissionType type);
+
+ // Sets the retry token to be sent over the wire in v99 IETF Initial packets.
+ void SetRetryToken(QuicStringPiece retry_token);
+
+ // Returns the largest payload that will fit into a single MESSAGE frame.
+ QuicPacketLength GetLargestMessagePayload() const;
+
+ void set_debug_delegate(DebugDelegate* debug_delegate) {
+ debug_delegate_ = debug_delegate;
+ }
+
+ void set_can_set_transmission_type(bool can_set_transmission_type) {
+ can_set_transmission_type_ = can_set_transmission_type;
+ }
+
+ bool ShouldSetTransmissionTypeForNextFrame() const {
+ return can_set_transmission_type_ && set_transmission_type_for_next_frame_;
+ }
+
+ QuicByteCount pending_padding_bytes() const { return pending_padding_bytes_; }
+
+ QuicTransportVersion transport_version() const {
+ return framer_->transport_version();
+ }
+
+ private:
+ friend class test::QuicPacketCreatorPeer;
+
+ // Creates a stream frame which fits into the current open packet. If
+ // |write_length| is 0 and fin is true, the expected behavior is to consume
+ // the fin but return 0.
+ void CreateStreamFrame(QuicStreamId id,
+ size_t write_length,
+ size_t iov_offset,
+ QuicStreamOffset offset,
+ bool fin,
+ QuicFrame* frame);
+
+ // Creates a CRYPTO frame which fits into the current open packet. Returns
+ // false if there isn't enough room in the current open packet for a CRYPTO
+ // frame, and true if there is.
+ bool CreateCryptoFrame(EncryptionLevel level,
+ size_t write_length,
+ QuicStreamOffset offset,
+ QuicFrame* frame);
+
+ void FillPacketHeader(QuicPacketHeader* header);
+
+ // Adds a |frame| if there is space and returns false and flushes all pending
+ // frames if there isn't room. If |save_retransmittable_frames| is true,
+ // saves the |frame| in the next SerializedPacket.
+ bool AddFrame(const QuicFrame& frame,
+ bool save_retransmittable_frames,
+ TransmissionType transmission_type);
+
+ // Adds a padding frame to the current packet (if there is space) when (1)
+ // current packet needs full padding or (2) there are pending paddings.
+ void MaybeAddPadding();
+
+ // Serializes all frames which have been added and adds any which should be
+ // retransmitted to packet_.retransmittable_frames. All frames must fit into
+ // a single packet.
+ // Fails if |buffer_len| isn't long enough for the encrypted packet.
+ void SerializePacket(char* encrypted_buffer, size_t buffer_len);
+
+ // Called after a new SerialiedPacket is created to call the delegate's
+ // OnSerializedPacket and reset state.
+ void OnSerializedPacket();
+
+ // Clears all fields of packet_ that should be cleared between serializations.
+ void ClearPacket();
+
+ // Returns true if a diversification nonce should be included in the current
+ // packet's header.
+ bool IncludeNonceInPublicHeader() const;
+
+ // Returns true if version should be included in current packet's header.
+ bool IncludeVersionInHeader() const;
+
+ // Returns length of packet number to send over the wire.
+ // packet_.packet_number_length should never be read directly, use this
+ // function instead.
+ QuicPacketNumberLength GetPacketNumberLength() const;
+
+ // Returns whether the destination connection ID is sent over the wire.
+ QuicConnectionIdIncluded GetDestinationConnectionIdIncluded() const;
+
+ // Returns whether the source connection ID is sent over the wire.
+ QuicConnectionIdIncluded GetSourceConnectionIdIncluded() const;
+
+ // Returns length of the retry token variable length integer to send over the
+ // wire. Is non-zero for v99 IETF Initial packets.
+ QuicVariableLengthIntegerLength GetRetryTokenLengthLength() const;
+
+ // Returns the retry token to send over the wire, only sent in
+ // v99 IETF Initial packets.
+ QuicStringPiece GetRetryToken() const;
+
+ // Returns length of the length variable length integer to send over the
+ // wire. Is non-zero for v99 IETF Initial, 0-RTT or Handshake packets.
+ QuicVariableLengthIntegerLength GetLengthLength() const;
+
+ // Returns true if |frame| starts with CHLO.
+ bool StreamFrameStartsWithChlo(const QuicStreamFrame& frame) const;
+
+ // Returns true if packet under construction has IETF long header.
+ bool HasIetfLongHeader() const;
+
+ // Does not own these delegates or the framer.
+ DelegateInterface* delegate_;
+ DebugDelegate* debug_delegate_;
+ QuicFramer* framer_;
+ QuicRandom* random_;
+
+ // Controls whether version should be included while serializing the packet.
+ // send_version_in_packet_ should never be read directly, use
+ // IncludeVersionInHeader() instead.
+ bool send_version_in_packet_;
+ // If true, then |diversification_nonce_| will be included in the header of
+ // all packets created at the initial encryption level.
+ bool have_diversification_nonce_;
+ DiversificationNonce diversification_nonce_;
+ // Maximum length including headers and encryption (UDP payload length.)
+ QuicByteCount max_packet_length_;
+ size_t max_plaintext_size_;
+ // Whether the connection_id is sent over the wire.
+ QuicConnectionIdIncluded connection_id_included_;
+
+ // Frames to be added to the next SerializedPacket
+ QuicFrames queued_frames_;
+
+ // packet_size should never be read directly, use PacketSize() instead.
+ // TODO(ianswett): Move packet_size_ into SerializedPacket once
+ // QuicEncryptedPacket has been flattened into SerializedPacket.
+ size_t packet_size_;
+ QuicConnectionId connection_id_;
+
+ // Packet used to invoke OnSerializedPacket.
+ SerializedPacket packet_;
+
+ // Retry token to send over the wire in v99 IETF Initial packets.
+ QuicString retry_token_;
+
+ // Pending padding bytes to send. Pending padding bytes will be sent in next
+ // packet(s) (after all other frames) if current constructed packet does not
+ // have room to send all of them.
+ QuicByteCount pending_padding_bytes_;
+
+ // Indicates whether current constructed packet needs full padding to max
+ // packet size. Please note, full padding does not consume pending padding
+ // bytes.
+ bool needs_full_padding_;
+
+ // If true, packet_'s transmission type is only set by
+ // SetPacketTransmissionType and does not get cleared in ClearPacket.
+ bool can_set_transmission_type_;
+
+ // Latched value of --quic_set_transmission_type_for_next_frame. Don't use
+ // this variable directly, use ShouldSetTransmissionTypeForNextFrame instead.
+ bool set_transmission_type_for_next_frame_;
+};
+
+} // namespace quic
+
+#endif // QUICHE_QUIC_CORE_QUIC_PACKET_CREATOR_H_