// 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. If multipath enabled, only creates // packets on one path at the same time. Currently, next packet number is // tracked per-path. #ifndef NET_QUIC_QUIC_PACKET_CREATOR_H_ #define NET_QUIC_QUIC_PACKET_CREATOR_H_ #include #include #include #include #include #include "base/macros.h" #include "base/memory/scoped_ptr.h" #include "base/strings/string_piece.h" #include "net/quic/quic_framer.h" #include "net/quic/quic_protocol.h" using base::hash_map; namespace net { namespace test { class QuicPacketCreatorPeer; } class QuicRandom; class QuicRandomBoolSource; class NET_EXPORT_PRIVATE QuicPacketCreator { public: // A delegate interface for further processing serialized packet. class NET_EXPORT_PRIVATE DelegateInterface { public: virtual ~DelegateInterface() {} // Called when a packet is serialized. Delegate does not take the ownership // of |serialized_packet|, but may take ownership of |packet.packet| // and |packet.retransmittable_frames|. If it does so, they must be set // to nullptr. virtual void OnSerializedPacket(SerializedPacket* serialized_packet) = 0; // Called when an unrecoverable error is encountered. virtual void OnUnrecoverableError(QuicErrorCode error, ConnectionCloseSource source) = 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 NET_EXPORT_PRIVATE DebugDelegate { public: virtual ~DebugDelegate() {} // Called when a frame has been added to the current packet. virtual void OnFrameAddedToPacket(const QuicFrame& frame) {} }; // QuicRandom* required for packet entropy. QuicPacketCreator(QuicConnectionId connection_id, QuicFramer* framer, QuicRandom* random_generator, QuicBufferAllocator* buffer_allocator, DelegateInterface* delegate); ~QuicPacketCreator(); // Makes the framer not serialize the protocol version in sent packets. void StopSendingVersion(); // 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( QuicConnectionIdLength connection_id_length, bool include_version, bool include_path_id, QuicPacketNumberLength packet_number_length, QuicStreamOffset offset); // Returns false and flushes all pending frames if current open packet is // full. // If current packet is not full, converts a raw payload into a stream frame // that fits into the open packet and adds it to the packet. // The payload begins at |iov_offset| into the |iov|. bool ConsumeData(QuicStreamId id, QuicIOVector iov, size_t iov_offset, QuicStreamOffset offset, bool fin, bool needs_padding, QuicFrame* frame); // Returns true if current open packet can accommodate more stream frames of // stream |id| at |offset|, false otherwise. bool HasRoomForStreamFrame(QuicStreamId id, QuicStreamOffset offset); // 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 PendingRetransmission& 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(); // 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 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); // Identical to AddSavedFrame, but allows the frame to be padded. bool AddPaddedSavedFrame(const QuicFrame& frame); // Adds |listener| to the next serialized packet and notifies the // std::listener with |length| as the number of acked bytes. void AddAckListener(QuicAckListenerInterface* listener, QuicPacketLength length); // Creates a version negotiation packet which supports |supported_versions|. // Caller owns the created packet. Also, sets the entropy hash of the // serialized packet to a random bool and returns that value as a member of // SerializedPacket. QuicEncryptedPacket* SerializeVersionNegotiationPacket( const QuicVersionVector& supported_versions); // Returns a dummy packet that is valid but contains no useful information. static SerializedPacket NoPacket(); // 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; } QuicConnectionIdLength connection_id_length() const { return connection_id_length_; } void set_connection_id_length(QuicConnectionIdLength length) { connection_id_length_ = length; } 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, 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); // Sets the path on which subsequent packets will be created. It is the // caller's responsibility to guarantee no packet is under construction before // calling this function. If |path_id| is different from current_path_, // next_packet_number_length_ is recalculated. void SetCurrentPath(QuicPathId path_id, QuicPacketNumber least_packet_awaited_by_peer, QuicPacketCount max_packets_in_flight); void set_debug_delegate(DebugDelegate* debug_delegate) { debug_delegate_ = debug_delegate; } private: friend class test::QuicPacketCreatorPeer; static bool ShouldRetransmit(const QuicFrame& frame); // Converts a raw payload to a frame which fits into the current open // packet. The payload begins at |iov_offset| into the |iov|. // Returns the number of bytes consumed from data. // If data is empty and fin is true, the expected behavior is to consume the // fin but return 0. If any data is consumed, it will be copied into a // new buffer that |frame| will point to and own. size_t CreateStreamFrame(QuicStreamId id, QuicIOVector iov, size_t iov_offset, QuicStreamOffset offset, bool fin, QuicFrame* frame); // Copies |length| bytes from iov starting at offset |iov_offset| into buffer. // |iov| must be at least iov_offset+length total length and buffer must be // at least |length| long. static void CopyToBuffer(QuicIOVector iov, size_t iov_offset, size_t length, char* buffer); // Updates packet number length on packet boundary. void MaybeUpdatePacketNumberLength(); 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); // Adds a padding frame to the current packet only if the current packet // contains a handshake message, and there is sufficient room to fit a // padding frame. 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. Sets the entropy hash of the serialized packet to a // random bool. // 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(); // Does not own these delegates or the framer. DelegateInterface* delegate_; DebugDelegate* debug_delegate_; QuicFramer* framer_; scoped_ptr random_bool_source_; QuicBufferAllocator* const buffer_allocator_; // Controls whether version should be included while serializing the packet. bool send_version_in_packet_; // Controls whether path id should be included while serializing the packet. bool send_path_id_in_packet_; // Staging variable to hold next packet number length. When sequence // number length is to be changed, this variable holds the new length until // a packet boundary, when the creator's packet_number_length_ can be changed // to this new value. QuicPacketNumberLength next_packet_number_length_; // Maximum length including headers and encryption (UDP payload length.) QuicByteCount max_packet_length_; size_t max_plaintext_size_; // Length of connection_id to send over the wire. QuicConnectionIdLength connection_id_length_; // 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_; // Map mapping path_id to last sent packet number on the path. std::unordered_map multipath_packet_number_; DISALLOW_COPY_AND_ASSIGN(QuicPacketCreator); }; } // namespace net #endif // NET_QUIC_QUIC_PACKET_CREATOR_H_