QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 1 | // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 | // Use of this source code is governed by a BSD-style license that can be |
| 3 | // found in the LICENSE file. |
| 4 | |
| 5 | // Responsible for generating packets on behalf of a QuicConnection. |
fayang | 914fbe1 | 2019-07-11 06:23:55 -0700 | [diff] [blame] | 6 | // Packets are serialized just-in-time. |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 7 | // Ack and Feedback frames will be requested from the Connection |
| 8 | // just-in-time. When a packet needs to be sent, the Generator |
| 9 | // will serialize a packet and pass it to QuicConnection::SendOrQueuePacket() |
| 10 | // |
| 11 | // The Generator's mode of operation is controlled by two conditions: |
| 12 | // |
| 13 | // 1) Is the Delegate writable? |
| 14 | // |
| 15 | // If the Delegate is not writable, then no operations will cause |
| 16 | // a packet to be serialized. In particular: |
| 17 | // * SetShouldSendAck will simply record that an ack is to be sent. |
| 18 | // * AddControlFrame will enqueue the control frame. |
| 19 | // * ConsumeData will do nothing. |
| 20 | // |
| 21 | // If the Delegate is writable, then the behavior depends on the second |
| 22 | // condition: |
| 23 | // |
| 24 | // 2) Is the Generator in batch mode? |
| 25 | // |
| 26 | // If the Generator is NOT in batch mode, then each call to a write |
| 27 | // operation will serialize one or more packets. The contents will |
| 28 | // include any previous queued frames. If an ack should be sent |
| 29 | // but has not been sent, then the Delegate will be asked to create |
| 30 | // an Ack frame which will then be included in the packet. When |
| 31 | // the write call completes, the current packet will be serialized |
| 32 | // and sent to the Delegate, even if it is not full. |
| 33 | // |
| 34 | // If the Generator is in batch mode, then each write operation will |
| 35 | // add data to the "current" packet. When the current packet becomes |
| 36 | // full, it will be serialized and sent to the packet. When batch |
| 37 | // mode is ended via |FinishBatchOperations|, the current packet |
| 38 | // will be serialzied, even if it is not full. |
| 39 | |
| 40 | #ifndef QUICHE_QUIC_CORE_QUIC_PACKET_GENERATOR_H_ |
| 41 | #define QUICHE_QUIC_CORE_QUIC_PACKET_GENERATOR_H_ |
| 42 | |
| 43 | #include <cstddef> |
| 44 | #include <cstdint> |
| 45 | #include <list> |
| 46 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 47 | #include "net/third_party/quiche/src/quic/core/quic_packet_creator.h" |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 48 | #include "net/third_party/quiche/src/quic/core/quic_sent_packet_manager.h" |
| 49 | #include "net/third_party/quiche/src/quic/core/quic_types.h" |
| 50 | #include "net/third_party/quiche/src/quic/platform/api/quic_export.h" |
| 51 | #include "net/third_party/quiche/src/quic/platform/api/quic_mem_slice_span.h" |
| 52 | |
| 53 | namespace quic { |
| 54 | |
| 55 | namespace test { |
| 56 | class QuicPacketGeneratorPeer; |
| 57 | } // namespace test |
| 58 | |
| 59 | class QUIC_EXPORT_PRIVATE QuicPacketGenerator { |
| 60 | public: |
dschinazi | 7b9278c | 2019-05-20 07:36:21 -0700 | [diff] [blame] | 61 | QuicPacketGenerator(QuicConnectionId server_connection_id, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 62 | QuicFramer* framer, |
| 63 | QuicRandom* random_generator, |
fayang | cad1179 | 2019-09-16 13:11:44 -0700 | [diff] [blame] | 64 | QuicPacketCreator::DelegateInterface* delegate); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 65 | QuicPacketGenerator(const QuicPacketGenerator&) = delete; |
| 66 | QuicPacketGenerator& operator=(const QuicPacketGenerator&) = delete; |
| 67 | |
| 68 | ~QuicPacketGenerator(); |
| 69 | |
fayang | 3203f25 | 2019-05-03 06:00:03 -0700 | [diff] [blame] | 70 | // Consumes retransmittable control |frame|. Returns true if the frame is |
| 71 | // successfully consumed. Returns false otherwise. |
| 72 | bool ConsumeRetransmittableControlFrame(const QuicFrame& frame); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 73 | |
| 74 | // Given some data, may consume part or all of it and pass it to the |
| 75 | // packet creator to be serialized into packets. If not in batch |
| 76 | // mode, these packets will also be sent during this call. |
| 77 | // When |state| is FIN_AND_PADDING, random padding of size [1, 256] will be |
| 78 | // added after stream frames. If current constructed packet cannot |
| 79 | // accommodate, the padding will overflow to the next packet(s). |
| 80 | QuicConsumedData ConsumeData(QuicStreamId id, |
| 81 | size_t write_length, |
| 82 | QuicStreamOffset offset, |
| 83 | StreamSendingState state); |
| 84 | |
| 85 | // Consumes data for CRYPTO frames sent at |level| starting at |offset| for a |
| 86 | // total of |write_length| bytes, and returns the number of bytes consumed. |
| 87 | // The data is passed into the packet creator and serialized into one or more |
| 88 | // packets. |
| 89 | size_t ConsumeCryptoData(EncryptionLevel level, |
| 90 | size_t write_length, |
| 91 | QuicStreamOffset offset); |
| 92 | |
| 93 | // Sends as many data only packets as allowed by the send algorithm and the |
| 94 | // available iov. |
| 95 | // This path does not support padding, or bundling pending frames. |
| 96 | // In case we access this method from ConsumeData, total_bytes_consumed |
| 97 | // keeps track of how many bytes have already been consumed. |
| 98 | QuicConsumedData ConsumeDataFastPath(QuicStreamId id, |
| 99 | size_t write_length, |
| 100 | QuicStreamOffset offset, |
| 101 | bool fin, |
| 102 | size_t total_bytes_consumed); |
| 103 | |
| 104 | // Generates an MTU discovery packet of specified size. |
| 105 | void GenerateMtuDiscoveryPacket(QuicByteCount target_mtu); |
| 106 | |
| 107 | // Indicates whether packet flusher is currently attached. |
| 108 | bool PacketFlusherAttached() const; |
| 109 | // Attaches packet flusher. |
| 110 | void AttachPacketFlusher(); |
fayang | 914fbe1 | 2019-07-11 06:23:55 -0700 | [diff] [blame] | 111 | // Flushes everything, including current open packet and pending padding. |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 112 | void Flush(); |
| 113 | |
fayang | 914fbe1 | 2019-07-11 06:23:55 -0700 | [diff] [blame] | 114 | // Flushes current open packet. |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 115 | void FlushAllQueuedFrames(); |
| 116 | |
fayang | 914fbe1 | 2019-07-11 06:23:55 -0700 | [diff] [blame] | 117 | // Returns true if there are frames pending to be serialized. |
| 118 | bool HasPendingFrames() const; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 119 | |
| 120 | // Makes the framer not serialize the protocol version in sent packets. |
| 121 | void StopSendingVersion(); |
| 122 | |
| 123 | // SetDiversificationNonce sets the nonce that will be sent in each public |
| 124 | // header of packets encrypted at the initial encryption level. Should only |
| 125 | // be called by servers. |
| 126 | void SetDiversificationNonce(const DiversificationNonce& nonce); |
| 127 | |
| 128 | // Creates a version negotiation packet which supports |supported_versions|. |
| 129 | std::unique_ptr<QuicEncryptedPacket> SerializeVersionNegotiationPacket( |
| 130 | bool ietf_quic, |
dschinazi | 48ac919 | 2019-07-31 00:07:26 -0700 | [diff] [blame] | 131 | bool use_length_prefix, |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 132 | const ParsedQuicVersionVector& supported_versions); |
| 133 | |
| 134 | // Creates a connectivity probing packet. |
| 135 | OwningSerializedPacketPointer SerializeConnectivityProbingPacket(); |
| 136 | |
| 137 | // Create connectivity probing request and response packets using PATH |
| 138 | // CHALLENGE and PATH RESPONSE frames, respectively. |
| 139 | // SerializePathChallengeConnectivityProbingPacket will pad the packet to be |
| 140 | // MTU bytes long. |
| 141 | OwningSerializedPacketPointer SerializePathChallengeConnectivityProbingPacket( |
| 142 | QuicPathFrameBuffer* payload); |
| 143 | |
| 144 | // If |is_padded| is true then SerializePathResponseConnectivityProbingPacket |
| 145 | // will pad the packet to be MTU bytes long, else it will not pad the packet. |
| 146 | // |payloads| is cleared. |
| 147 | OwningSerializedPacketPointer SerializePathResponseConnectivityProbingPacket( |
| 148 | const QuicDeque<QuicPathFrameBuffer>& payloads, |
| 149 | const bool is_padded); |
| 150 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 151 | // Update the packet number length to use in future packets as soon as it |
| 152 | // can be safely changed. |
| 153 | void UpdatePacketNumberLength(QuicPacketNumber least_packet_awaited_by_peer, |
| 154 | QuicPacketCount max_packets_in_flight); |
| 155 | |
fayang | 4c1c236 | 2019-09-13 07:20:01 -0700 | [diff] [blame] | 156 | // Skip |count| packet numbers. |
| 157 | void SkipNPacketNumbers(QuicPacketCount count, |
| 158 | QuicPacketNumber least_packet_awaited_by_peer, |
| 159 | QuicPacketCount max_packets_in_flight); |
| 160 | |
dschinazi | 7b9278c | 2019-05-20 07:36:21 -0700 | [diff] [blame] | 161 | // Set the minimum number of bytes for the server connection id length; |
| 162 | void SetServerConnectionIdLength(uint32_t length); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 163 | |
| 164 | // Sets the encrypter to use for the encryption level. |
| 165 | void SetEncrypter(EncryptionLevel level, |
| 166 | std::unique_ptr<QuicEncrypter> encrypter); |
| 167 | |
| 168 | // Returns true if there are control frames or current constructed packet has |
| 169 | // pending retransmittable frames. |
| 170 | bool HasRetransmittableFrames() const; |
| 171 | |
| 172 | // Returns true if current constructed packet has pending stream frames for |
| 173 | // stream |id|. |
| 174 | bool HasPendingStreamFramesOfStream(QuicStreamId id) const; |
| 175 | |
| 176 | // Sets the encryption level that will be applied to new packets. |
| 177 | void set_encryption_level(EncryptionLevel level); |
| 178 | |
| 179 | // packet number of the last created packet, or 0 if no packets have been |
| 180 | // created. |
| 181 | QuicPacketNumber packet_number() const; |
| 182 | |
| 183 | // Returns the maximum length a current packet can actually have. |
| 184 | QuicByteCount GetCurrentMaxPacketLength() const; |
| 185 | |
| 186 | // Set maximum packet length in the creator immediately. May not be called |
| 187 | // when there are frames queued in the creator. |
| 188 | void SetMaxPacketLength(QuicByteCount length); |
| 189 | |
| 190 | // Set transmission type of next constructed packets. |
| 191 | void SetTransmissionType(TransmissionType type); |
| 192 | |
dschinazi | 244f6dc | 2019-05-06 15:45:16 -0700 | [diff] [blame] | 193 | // Sets the retry token to be sent over the wire in IETF Initial packets. |
| 194 | void SetRetryToken(QuicStringPiece retry_token); |
| 195 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 196 | // Tries to add a message frame containing |message| and returns the status. |
| 197 | MessageStatus AddMessageFrame(QuicMessageId message_id, |
| 198 | QuicMemSliceSpan message); |
| 199 | |
| 200 | // Called to flush ACK and STOP_WAITING frames, returns false if the flush |
| 201 | // fails. |
| 202 | bool FlushAckFrame(const QuicFrames& frames); |
| 203 | |
| 204 | // Returns the largest payload that will fit into a single MESSAGE frame. |
ianswett | b239f86 | 2019-04-05 09:15:06 -0700 | [diff] [blame] | 205 | QuicPacketLength GetCurrentLargestMessagePayload() const; |
| 206 | QuicPacketLength GetGuaranteedLargestMessagePayload() const; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 207 | |
dschinazi | 7b9278c | 2019-05-20 07:36:21 -0700 | [diff] [blame] | 208 | // Update the server connection ID used in outgoing packets. |
| 209 | void SetServerConnectionId(QuicConnectionId server_connection_id); |
QUICHE team | c65d1d1 | 2019-03-19 20:58:04 -0700 | [diff] [blame] | 210 | |
dschinazi | 346b7ce | 2019-06-05 01:38:18 -0700 | [diff] [blame] | 211 | // Update the client connection ID used in outgoing packets. |
| 212 | void SetClientConnectionId(QuicConnectionId client_connection_id); |
| 213 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 214 | void set_debug_delegate(QuicPacketCreator::DebugDelegate* debug_delegate) { |
| 215 | packet_creator_.set_debug_delegate(debug_delegate); |
| 216 | } |
| 217 | |
nharper | 3907ac2 | 2019-09-25 15:32:28 -0700 | [diff] [blame] | 218 | void set_fully_pad_crypto_handshake_packets(bool new_value); |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 219 | |
fayang | 18be79a | 2019-09-16 15:17:12 -0700 | [diff] [blame] | 220 | bool fully_pad_crypto_handshake_packets() const; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 221 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 222 | private: |
| 223 | friend class test::QuicPacketGeneratorPeer; |
| 224 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 225 | // Adds a random amount of padding (between 1 to 256 bytes). |
| 226 | void AddRandomPadding(); |
| 227 | |
| 228 | // Sends remaining pending padding. |
| 229 | // Pending paddings should only be sent when there is nothing else to send. |
| 230 | void SendRemainingPendingPadding(); |
| 231 | |
| 232 | // Called when there is data to be sent, Retrieves updated ACK frame from |
| 233 | // delegate_ and flushes it. |
| 234 | void MaybeBundleAckOpportunistically(); |
| 235 | |
fayang | cad1179 | 2019-09-16 13:11:44 -0700 | [diff] [blame] | 236 | QuicPacketCreator::DelegateInterface* delegate_; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 237 | |
| 238 | QuicPacketCreator packet_creator_; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 239 | |
| 240 | // Transmission type of the next serialized packet. |
| 241 | TransmissionType next_transmission_type_; |
| 242 | |
| 243 | // True if packet flusher is currently attached. |
| 244 | bool flusher_attached_; |
| 245 | |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 246 | QuicRandom* random_generator_; |
| 247 | |
| 248 | // Whether crypto handshake packets should be fully padded. |
| 249 | bool fully_pad_crypto_handshake_packets_; |
| 250 | |
fayang | 354c942 | 2019-05-21 08:10:35 -0700 | [diff] [blame] | 251 | // Packet number of the first packet of a write operation. This gets set |
| 252 | // when the out-most flusher attaches and gets cleared when the out-most |
| 253 | // flusher detaches. |
| 254 | QuicPacketNumber write_start_packet_number_; |
QUICHE team | a6ef0a6 | 2019-03-07 20:34:33 -0500 | [diff] [blame] | 255 | }; |
| 256 | |
| 257 | } // namespace quic |
| 258 | |
| 259 | #endif // QUICHE_QUIC_CORE_QUIC_PACKET_GENERATOR_H_ |