Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [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 | #include "net/quic/quic_packet_creator.h" |
| 6 | |
| 7 | #include "base/logging.h" |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 8 | #include "net/quic/crypto/quic_random.h" |
| 9 | #include "net/quic/quic_fec_group.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 10 | #include "net/quic/quic_utils.h" |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 11 | |
| 12 | using base::StringPiece; |
| 13 | using std::make_pair; |
| 14 | using std::min; |
| 15 | using std::pair; |
| 16 | using std::vector; |
| 17 | |
| 18 | namespace net { |
| 19 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 20 | QuicPacketCreator::QuicPacketCreator(QuicGuid guid, |
| 21 | QuicFramer* framer, |
| 22 | QuicRandom* random_generator, |
| 23 | bool is_server) |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 24 | : guid_(guid), |
| 25 | framer_(framer), |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 26 | random_generator_(random_generator), |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 27 | sequence_number_(0), |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 28 | fec_group_number_(0), |
| 29 | is_server_(is_server), |
| 30 | send_version_in_packet_(!is_server), |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 31 | packet_size_(GetPacketHeaderSize(options_.send_guid_length, |
| 32 | send_version_in_packet_, |
| 33 | options_.send_sequence_number_length, |
| 34 | NOT_IN_FEC_GROUP)) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 35 | framer_->set_fec_builder(this); |
| 36 | } |
| 37 | |
| 38 | QuicPacketCreator::~QuicPacketCreator() { |
| 39 | } |
| 40 | |
| 41 | void QuicPacketCreator::OnBuiltFecProtectedPayload( |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 42 | const QuicPacketHeader& header, StringPiece payload) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 43 | if (fec_group_.get()) { |
| 44 | fec_group_->Update(header, payload); |
| 45 | } |
| 46 | } |
| 47 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 48 | bool QuicPacketCreator::ShouldSendFec(bool force_close) const { |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 49 | return fec_group_.get() != NULL && fec_group_->NumReceivedPackets() > 0 && |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 50 | (force_close || |
| 51 | fec_group_->NumReceivedPackets() >= options_.max_packets_per_fec_group); |
| 52 | } |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 53 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 54 | void QuicPacketCreator::MaybeStartFEC() { |
| 55 | if (options_.max_packets_per_fec_group > 0 && fec_group_.get() == NULL) { |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 56 | DCHECK(queued_frames_.empty()); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 57 | // Set the fec group number to the sequence number of the next packet. |
| 58 | fec_group_number_ = sequence_number() + 1; |
| 59 | fec_group_.reset(new QuicFecGroup()); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 60 | packet_size_ = GetPacketHeaderSize(options_.send_guid_length, |
| 61 | send_version_in_packet_, |
| 62 | options_.send_sequence_number_length, |
| 63 | IN_FEC_GROUP); |
| 64 | DCHECK_LE(packet_size_, options_.max_packet_length); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 65 | } |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 66 | } |
| 67 | |
| 68 | // Stops serializing version of the protocol in packets sent after this call. |
| 69 | // A packet that is already open might send kQuicVersionSize bytes less than the |
| 70 | // maximum packet size if we stop sending version before it is serialized. |
| 71 | void QuicPacketCreator::StopSendingVersion() { |
| 72 | DCHECK(send_version_in_packet_); |
| 73 | send_version_in_packet_ = false; |
| 74 | if (packet_size_ > 0) { |
| 75 | DCHECK_LT(kQuicVersionSize, packet_size_); |
| 76 | packet_size_ -= kQuicVersionSize; |
| 77 | } |
| 78 | } |
| 79 | |
Ben Murdoch | 2385ea3 | 2013-08-06 11:01:04 +0100 | [diff] [blame] | 80 | bool QuicPacketCreator::HasRoomForStreamFrame(QuicStreamId id, |
| 81 | QuicStreamOffset offset) const { |
| 82 | return BytesFree() > |
| 83 | QuicFramer::GetMinStreamFrameSize(framer_->version(), id, offset, true); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 84 | } |
| 85 | |
| 86 | // static |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 87 | size_t QuicPacketCreator::StreamFramePacketOverhead( |
Ben Murdoch | 2385ea3 | 2013-08-06 11:01:04 +0100 | [diff] [blame] | 88 | QuicVersion version, |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 89 | QuicGuidLength guid_length, |
| 90 | bool include_version, |
| 91 | QuicSequenceNumberLength sequence_number_length, |
| 92 | InFecGroup is_in_fec_group) { |
| 93 | return GetPacketHeaderSize(guid_length, include_version, |
| 94 | sequence_number_length, is_in_fec_group) + |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 95 | // Assumes this is a stream with a single lone packet. |
Ben Murdoch | 2385ea3 | 2013-08-06 11:01:04 +0100 | [diff] [blame] | 96 | QuicFramer::GetMinStreamFrameSize(version, 1u, 0u, true); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 97 | } |
| 98 | |
| 99 | size_t QuicPacketCreator::CreateStreamFrame(QuicStreamId id, |
| 100 | StringPiece data, |
| 101 | QuicStreamOffset offset, |
| 102 | bool fin, |
| 103 | QuicFrame* frame) { |
| 104 | DCHECK_GT(options_.max_packet_length, |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 105 | StreamFramePacketOverhead( |
Ben Murdoch | 2385ea3 | 2013-08-06 11:01:04 +0100 | [diff] [blame] | 106 | framer_->version(), PACKET_8BYTE_GUID, kIncludeVersion, |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 107 | PACKET_6BYTE_SEQUENCE_NUMBER, IN_FEC_GROUP)); |
Ben Murdoch | 2385ea3 | 2013-08-06 11:01:04 +0100 | [diff] [blame] | 108 | DCHECK(HasRoomForStreamFrame(id, offset)); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 109 | |
| 110 | const size_t free_bytes = BytesFree(); |
| 111 | size_t bytes_consumed = 0; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 112 | |
| 113 | if (data.size() != 0) { |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 114 | // When a STREAM frame is the last frame in a packet, it consumes two fewer |
| 115 | // bytes of framing overhead. |
| 116 | // Anytime more data is available than fits in with the extra two bytes, |
| 117 | // the frame will be the last, and up to two extra bytes are consumed. |
| 118 | // TODO(ianswett): If QUIC pads, the 1 byte PADDING frame does not fit when |
| 119 | // 1 byte is available, because then the STREAM frame isn't the last. |
| 120 | |
| 121 | // The minimum frame size(0 bytes of data) if it's not the last frame. |
| 122 | size_t min_frame_size = QuicFramer::GetMinStreamFrameSize( |
| 123 | framer_->version(), id, offset, false); |
| 124 | // Check if it's the last frame in the packet. |
| 125 | if (data.size() + min_frame_size > free_bytes) { |
| 126 | // The minimum frame size(0 bytes of data) if it is the last frame. |
| 127 | size_t min_last_frame_size = QuicFramer::GetMinStreamFrameSize( |
| 128 | framer_->version(), id, offset, true); |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 129 | bytes_consumed = |
Ben Murdoch | bb1529c | 2013-08-08 10:24:53 +0100 | [diff] [blame^] | 130 | min<size_t>(free_bytes - min_last_frame_size, data.size()); |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 131 | } else { |
Ben Murdoch | 2385ea3 | 2013-08-06 11:01:04 +0100 | [diff] [blame] | 132 | DCHECK_LT(data.size(), BytesFree()); |
Ben Murdoch | 7dbb3d5 | 2013-07-17 14:55:54 +0100 | [diff] [blame] | 133 | bytes_consumed = data.size(); |
| 134 | } |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 135 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 136 | bool set_fin = fin && bytes_consumed == data.size(); // Last frame. |
| 137 | StringPiece data_frame(data.data(), bytes_consumed); |
| 138 | *frame = QuicFrame(new QuicStreamFrame(id, set_fin, offset, data_frame)); |
| 139 | } else { |
| 140 | DCHECK(fin); |
| 141 | // Create a new packet for the fin, if necessary. |
| 142 | *frame = QuicFrame(new QuicStreamFrame(id, true, offset, "")); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 143 | } |
| 144 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 145 | return bytes_consumed; |
| 146 | } |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 147 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 148 | SerializedPacket QuicPacketCreator::SerializeAllFrames( |
| 149 | const QuicFrames& frames) { |
| 150 | // TODO(satyamshekhar): Verify that this DCHECK won't fail. What about queued |
| 151 | // frames from SendStreamData()[send_stream_should_flush_ == false && |
| 152 | // data.empty() == true] and retransmit due to RTO. |
| 153 | DCHECK_EQ(0u, queued_frames_.size()); |
| 154 | for (size_t i = 0; i < frames.size(); ++i) { |
| 155 | bool success = AddFrame(frames[i], false); |
| 156 | DCHECK(success); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 157 | } |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 158 | SerializedPacket packet = SerializePacket(); |
| 159 | DCHECK(packet.retransmittable_frames == NULL); |
| 160 | return packet; |
| 161 | } |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 162 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 163 | bool QuicPacketCreator::HasPendingFrames() { |
| 164 | return !queued_frames_.empty(); |
| 165 | } |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 166 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 167 | size_t QuicPacketCreator::BytesFree() const { |
| 168 | const size_t max_plaintext_size = |
| 169 | framer_->GetMaxPlaintextSize(options_.max_packet_length); |
| 170 | if (packet_size_ > max_plaintext_size) { |
| 171 | return 0; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 172 | } |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 173 | return max_plaintext_size - packet_size_; |
| 174 | } |
| 175 | |
| 176 | bool QuicPacketCreator::AddSavedFrame(const QuicFrame& frame) { |
| 177 | return AddFrame(frame, true); |
| 178 | } |
| 179 | |
| 180 | SerializedPacket QuicPacketCreator::SerializePacket() { |
| 181 | DCHECK_EQ(false, queued_frames_.empty()); |
| 182 | QuicPacketHeader header; |
| 183 | FillPacketHeader(fec_group_number_, false, false, &header); |
| 184 | |
Ben Murdoch | 2385ea3 | 2013-08-06 11:01:04 +0100 | [diff] [blame] | 185 | SerializedPacket serialized = framer_->BuildDataPacket( |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 186 | header, queued_frames_, packet_size_); |
| 187 | queued_frames_.clear(); |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 188 | packet_size_ = GetPacketHeaderSize(options_.send_guid_length, |
| 189 | send_version_in_packet_, |
| 190 | options_.send_sequence_number_length, |
| 191 | fec_group_.get() != NULL ? |
| 192 | IN_FEC_GROUP : NOT_IN_FEC_GROUP); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 193 | serialized.retransmittable_frames = queued_retransmittable_frames_.release(); |
| 194 | return serialized; |
| 195 | } |
| 196 | |
| 197 | SerializedPacket QuicPacketCreator::SerializeFec() { |
| 198 | DCHECK_LT(0u, fec_group_->NumReceivedPackets()); |
| 199 | DCHECK_EQ(0u, queued_frames_.size()); |
| 200 | QuicPacketHeader header; |
| 201 | FillPacketHeader(fec_group_number_, true, |
| 202 | fec_group_->entropy_parity(), &header); |
| 203 | QuicFecData fec_data; |
| 204 | fec_data.fec_group = fec_group_->min_protected_packet(); |
| 205 | fec_data.redundancy = fec_group_->payload_parity(); |
Ben Murdoch | 2385ea3 | 2013-08-06 11:01:04 +0100 | [diff] [blame] | 206 | SerializedPacket serialized = framer_->BuildFecPacket(header, fec_data); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 207 | fec_group_.reset(NULL); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 208 | fec_group_number_ = 0; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 209 | // Reset packet_size_, since the next packet may not have an FEC group. |
| 210 | packet_size_ = GetPacketHeaderSize(options_.send_guid_length, |
| 211 | send_version_in_packet_, |
| 212 | options_.send_sequence_number_length, |
| 213 | NOT_IN_FEC_GROUP); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 214 | DCHECK(serialized.packet); |
| 215 | DCHECK_GE(options_.max_packet_length, serialized.packet->length()); |
| 216 | return serialized; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 217 | } |
| 218 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 219 | SerializedPacket QuicPacketCreator::SerializeConnectionClose( |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 220 | QuicConnectionCloseFrame* close_frame) { |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 221 | QuicFrames frames; |
| 222 | frames.push_back(QuicFrame(close_frame)); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 223 | return SerializeAllFrames(frames); |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 224 | } |
| 225 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 226 | QuicEncryptedPacket* QuicPacketCreator::SerializeVersionNegotiationPacket( |
Ben Murdoch | 558790d | 2013-07-30 15:19:42 +0100 | [diff] [blame] | 227 | const QuicVersionVector& supported_versions) { |
Torne (Richard Coles) | c2e0dbd | 2013-05-09 18:35:53 +0100 | [diff] [blame] | 228 | DCHECK(is_server_); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 229 | QuicPacketPublicHeader header; |
| 230 | header.guid = guid_; |
| 231 | header.reset_flag = false; |
| 232 | header.version_flag = true; |
| 233 | header.versions = supported_versions; |
| 234 | QuicEncryptedPacket* encrypted = |
Ben Murdoch | 2385ea3 | 2013-08-06 11:01:04 +0100 | [diff] [blame] | 235 | framer_->BuildVersionNegotiationPacket(header, supported_versions); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 236 | DCHECK(encrypted); |
| 237 | DCHECK_GE(options_.max_packet_length, encrypted->length()); |
| 238 | return encrypted; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 239 | } |
| 240 | |
| 241 | void QuicPacketCreator::FillPacketHeader(QuicFecGroupNumber fec_group, |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 242 | bool fec_flag, |
| 243 | bool fec_entropy_flag, |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 244 | QuicPacketHeader* header) { |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 245 | header->public_header.guid = guid_; |
| 246 | header->public_header.reset_flag = false; |
| 247 | header->public_header.version_flag = send_version_in_packet_; |
| 248 | header->fec_flag = fec_flag; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 249 | header->packet_sequence_number = ++sequence_number_; |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 250 | |
| 251 | bool entropy_flag; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 252 | if (header->packet_sequence_number == 1) { |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 253 | DCHECK(!fec_flag); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 254 | // TODO(satyamshekhar): No entropy in the first message. |
| 255 | // For crypto tests to pass. Fix this by using deterministic QuicRandom. |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 256 | entropy_flag = 0; |
| 257 | } else if (fec_flag) { |
| 258 | // FEC packets don't have an entropy of their own. Entropy flag for FEC |
| 259 | // packets is the XOR of entropy of previous packets. |
| 260 | entropy_flag = fec_entropy_flag; |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 261 | } else { |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 262 | entropy_flag = random_generator_->RandBool(); |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 263 | } |
Torne (Richard Coles) | 868fa2f | 2013-06-11 10:57:03 +0100 | [diff] [blame] | 264 | header->entropy_flag = entropy_flag; |
| 265 | header->is_in_fec_group = fec_group == 0 ? NOT_IN_FEC_GROUP : IN_FEC_GROUP; |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 266 | header->fec_group = fec_group; |
| 267 | } |
| 268 | |
Torne (Richard Coles) | 2a99a7e | 2013-03-28 15:31:22 +0000 | [diff] [blame] | 269 | bool QuicPacketCreator::ShouldRetransmit(const QuicFrame& frame) { |
| 270 | return frame.type != ACK_FRAME && frame.type != CONGESTION_FEEDBACK_FRAME && |
| 271 | frame.type != PADDING_FRAME; |
| 272 | } |
| 273 | |
| 274 | bool QuicPacketCreator::AddFrame(const QuicFrame& frame, |
| 275 | bool save_retransmittable_frames) { |
| 276 | size_t frame_len = framer_->GetSerializedFrameLength( |
| 277 | frame, BytesFree(), queued_frames_.empty()); |
| 278 | if (frame_len == 0) { |
| 279 | return false; |
| 280 | } |
| 281 | packet_size_ += frame_len; |
| 282 | |
| 283 | if (save_retransmittable_frames && ShouldRetransmit(frame)) { |
| 284 | if (queued_retransmittable_frames_.get() == NULL) { |
| 285 | queued_retransmittable_frames_.reset(new RetransmittableFrames()); |
| 286 | } |
| 287 | if (frame.type == STREAM_FRAME) { |
| 288 | queued_frames_.push_back( |
| 289 | queued_retransmittable_frames_->AddStreamFrame(frame.stream_frame)); |
| 290 | } else { |
| 291 | queued_frames_.push_back( |
| 292 | queued_retransmittable_frames_->AddNonStreamFrame(frame)); |
| 293 | } |
| 294 | } else { |
| 295 | queued_frames_.push_back(frame); |
| 296 | } |
| 297 | return true; |
| 298 | } |
| 299 | |
Torne (Richard Coles) | 5821806 | 2012-11-14 11:43:16 +0000 | [diff] [blame] | 300 | } // namespace net |