15821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Copyright (c) 2012 The Chromium Authors. All rights reserved. 25821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be 35821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)// found in the LICENSE file. 45821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 55821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/quic/quic_packet_creator.h" 65821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 75d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)#include "base/basictypes.h" 85821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "base/logging.h" 92a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/crypto/quic_random.h" 1058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)#include "net/quic/quic_ack_notifier.h" 112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "net/quic/quic_fec_group.h" 125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)#include "net/quic/quic_utils.h" 135821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 145821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using base::StringPiece; 155821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::make_pair; 16d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)using std::max; 175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::min; 185821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::pair; 195821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)using std::vector; 205821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)namespace net { 225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 235f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)namespace { 245f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Default max packets in an FEC group. 265f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static const size_t kDefaultMaxPacketsPerFecGroup = 10; 275f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)// Lowest max packets in an FEC group. 285f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)static const size_t kLowestMaxPacketsPerFecGroup = 2; 295f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 305f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} // namespace 315f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 325d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// A QuicRandom wrapper that gets a bucket of entropy and distributes it 335d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// bit-by-bit. Replenishes the bucket as needed. Not thread-safe. Expose this 345d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)// class if single bit randomness is needed elsewhere. 355d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)class QuicRandomBoolSource { 365d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) public: 375d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // random: Source of entropy. Not owned. 385d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) explicit QuicRandomBoolSource(QuicRandom* random) 395d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) : random_(random), 405d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bit_bucket_(0), 415d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bit_mask_(0) {} 425d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 435d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) ~QuicRandomBoolSource() {} 445d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 455d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Returns the next random bit from the bucket. 465d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool RandBool() { 475d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) if (bit_mask_ == 0) { 485d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bit_bucket_ = random_->RandUint64(); 495d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bit_mask_ = 1; 505d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 515d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bool result = ((bit_bucket_ & bit_mask_) != 0); 525d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) bit_mask_ <<= 1; 535d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) return result; 545d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) } 555d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 565d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) private: 575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Source of entropy. 585d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) QuicRandom* random_; 595d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // Stored random bits. 605d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64 bit_bucket_; 615d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) // The next available bit has "1" in the mask. Zero means empty bucket. 625d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) uint64 bit_mask_; 635d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 645d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DISALLOW_COPY_AND_ASSIGN(QuicRandomBoolSource); 655d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles)}; 665d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) 67a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)QuicPacketCreator::QuicPacketCreator(QuicConnectionId connection_id, 682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) QuicFramer* framer, 69f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) QuicRandom* random_generator) 70a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) : connection_id_(connection_id), 71010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) encryption_level_(ENCRYPTION_NONE), 725821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) framer_(framer), 735d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) random_bool_source_(new QuicRandomBoolSource(random_generator)), 745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) sequence_number_(0), 75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) should_fec_protect_(false), 762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fec_group_number_(0), 77f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) send_version_in_packet_(!framer->is_server()), 7846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) max_packet_length_(kDefaultMaxPacketSize), 795f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) max_packets_per_fec_group_(kDefaultMaxPacketsPerFecGroup), 8046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) connection_id_length_(PACKET_8BYTE_CONNECTION_ID), 8146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) next_sequence_number_length_(PACKET_1BYTE_SEQUENCE_NUMBER), 8246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) sequence_number_length_(next_sequence_number_length_), 833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) packet_size_(0) { 84d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) framer_->set_fec_builder(this); 855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 865821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 875821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)QuicPacketCreator::~QuicPacketCreator() { 885821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 895821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 905821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QuicPacketCreator::OnBuiltFecProtectedPayload( 912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const QuicPacketHeader& header, StringPiece payload) { 925821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) if (fec_group_.get()) { 9368043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) DCHECK_NE(0u, header.fec_group); 94010d83a9304c5a91596085d917d248abff47903aTorne (Richard Coles) fec_group_->Update(encryption_level_, header, payload); 955821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 965821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 975821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 985f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)void QuicPacketCreator::set_max_packets_per_fec_group( 995f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) size_t max_packets_per_fec_group) { 1005f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) max_packets_per_fec_group_ = max(kLowestMaxPacketsPerFecGroup, 1015f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) max_packets_per_fec_group); 1025f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) DCHECK_LT(0u, max_packets_per_fec_group_); 1035f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles)} 1045f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) 1052a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool QuicPacketCreator::ShouldSendFec(bool force_close) const { 106f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK(!HasPendingFrames()); 107868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) return fec_group_.get() != NULL && fec_group_->NumReceivedPackets() > 0 && 108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) (force_close || fec_group_->NumReceivedPackets() >= 10946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) max_packets_per_fec_group_); 1102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1115821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 112f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool QuicPacketCreator::IsFecGroupOpen() const { 1135f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) return fec_group_.get() != NULL; 114f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)} 115f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) 116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void QuicPacketCreator::StartFecProtectingPackets() { 117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!IsFecEnabled()) { 118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LOG(DFATAL) << "Cannot start FEC protection when FEC is not enabled."; 119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 1202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // TODO(jri): This currently requires that the generator flush out any 122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // pending frames when FEC protection is turned on. If current packet can be 123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // converted to an FEC protected packet, do it. This will require the 124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // generator to check if the resulting expansion still allows the incoming 125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // frame to be added to the packet. 126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (HasPendingFrames()) { 127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LOG(DFATAL) << "Cannot start FEC protection with pending frames."; 128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(!should_fec_protect_); 131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) should_fec_protect_ = true; 132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void QuicPacketCreator::StopFecProtectingPackets() { 135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (fec_group_.get() != NULL) { 136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) LOG(DFATAL) << "Cannot stop FEC protection with open FEC group."; 137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return; 138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(should_fec_protect_); 140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) should_fec_protect_ = false; 141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) fec_group_number_ = 0; 142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool QuicPacketCreator::IsFecProtected() const { 145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return should_fec_protect_; 146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool QuicPacketCreator::IsFecEnabled() const { 14946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return max_packets_per_fec_group_ > 0; 150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)} 151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)InFecGroup QuicPacketCreator::MaybeUpdateLengthsAndStartFec() { 153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (fec_group_.get() != NULL) { 154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Don't update any lengths when an FEC group is open, to ensure same 155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // packet header size in all packets within a group. 156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return IN_FEC_GROUP; 157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!queued_frames_.empty()) { 159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Don't change creator state if there are frames queued. 160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return fec_group_.get() == NULL ? NOT_IN_FEC_GROUP : IN_FEC_GROUP; 161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 16246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) 16346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Update sequence number length only on packet and FEC group boundaries. 16446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) sequence_number_length_ = next_sequence_number_length_; 165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (!should_fec_protect_) { 167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return NOT_IN_FEC_GROUP; 168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Start a new FEC group since protection is on. Set the fec group number to 170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // the sequence number of the next packet. 171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) fec_group_number_ = sequence_number() + 1; 172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) fec_group_.reset(new QuicFecGroup()); 173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) return IN_FEC_GROUP; 1742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1755821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 1762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// Stops serializing version of the protocol in packets sent after this call. 1772a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// A packet that is already open might send kQuicVersionSize bytes less than the 1782a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// maximum packet size if we stop sending version before it is serialized. 1792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)void QuicPacketCreator::StopSendingVersion() { 1802a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(send_version_in_packet_); 1812a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) send_version_in_packet_ = false; 1822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (packet_size_ > 0) { 1832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_LT(kQuicVersionSize, packet_size_); 1842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) packet_size_ -= kQuicVersionSize; 1855821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 1862a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 1872a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 188d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)void QuicPacketCreator::UpdateSequenceNumberLength( 189d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) QuicPacketSequenceNumber least_packet_awaited_by_peer, 1900529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch QuicByteCount congestion_window) { 191d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) DCHECK_LE(least_packet_awaited_by_peer, sequence_number_ + 1); 192d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // Since the packet creator will not change sequence number length mid FEC 193d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) // group, include the size of an FEC group to be safe. 194d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) const QuicPacketSequenceNumber current_delta = 19546d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) max_packets_per_fec_group_ + sequence_number_ + 1 196d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) - least_packet_awaited_by_peer; 1970529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const uint64 congestion_window_packets = 19846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) congestion_window / max_packet_length_; 1990529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch const uint64 delta = max(current_delta, congestion_window_packets); 20046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) next_sequence_number_length_ = 2010f1bc08d4cfcc34181b0b5cbf065c40f687bf740Torne (Richard Coles) QuicFramer::GetMinSequenceNumberLength(delta * 4); 202d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles)} 203d0247b1b59f9c528cb6df88b4f2b9afaf80d181eTorne (Richard Coles) 2042385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdochbool QuicPacketCreator::HasRoomForStreamFrame(QuicStreamId id, 2052385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch QuicStreamOffset offset) const { 206c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // TODO(jri): This is a simple safe decision for now, but make 207c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // is_in_fec_group a parameter. Same as with all public methods in 208c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // QuicPacketCreator. 2092385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch return BytesFree() > 2105f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) QuicFramer::GetMinStreamFrameSize(id, offset, true, 211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) should_fec_protect_ ? IN_FEC_GROUP : 212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) NOT_IN_FEC_GROUP); 2132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)// static 216868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles)size_t QuicPacketCreator::StreamFramePacketOverhead( 217a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) QuicConnectionIdLength connection_id_length, 218868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) bool include_version, 219868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) QuicSequenceNumberLength sequence_number_length, 220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) QuicStreamOffset offset, 221868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) InFecGroup is_in_fec_group) { 222a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return GetPacketHeaderSize(connection_id_length, include_version, 223868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) sequence_number_length, is_in_fec_group) + 2247dbb3d5cf0c15f500944d211057644d6a2f37371Ben Murdoch // Assumes this is a stream with a single lone packet. 2255f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) QuicFramer::GetMinStreamFrameSize(1u, offset, true, is_in_fec_group); 2262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 2282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t QuicPacketCreator::CreateStreamFrame(QuicStreamId id, 229f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const IOVector& data, 2302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) QuicStreamOffset offset, 2312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool fin, 2322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) QuicFrame* frame) { 23346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK_GT(max_packet_length_, StreamFramePacketOverhead( 2345f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) PACKET_8BYTE_CONNECTION_ID, kIncludeVersion, 235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) PACKET_6BYTE_SEQUENCE_NUMBER, offset, IN_FEC_GROUP)); 236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) InFecGroup is_in_fec_group = MaybeUpdateLengthsAndStartFec(); 238c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 239a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LOG_IF(DFATAL, !HasRoomForStreamFrame(id, offset)) 240a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << "No room for Stream frame, BytesFree: " << BytesFree() 241a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << " MinStreamFrameSize: " 2425f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) << QuicFramer::GetMinStreamFrameSize(id, offset, true, is_in_fec_group); 2432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 244f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) if (data.Empty()) { 245a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LOG_IF(DFATAL, !fin) 246a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << "Creating a stream frame with no data or fin."; 2471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Create a new packet for the fin, if necessary. 248f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) *frame = QuicFrame(new QuicStreamFrame(id, true, offset, data)); 2491e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return 0; 2501e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 2511e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 252f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const size_t data_size = data.TotalBufferSize(); 253c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch size_t min_frame_size = QuicFramer::GetMinStreamFrameSize( 2545f1c94371a64b3196d4be9466099bb892df9b88eTorne (Richard Coles) id, offset, /* last_frame_in_packet= */ true, is_in_fec_group); 255c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch size_t bytes_consumed = min<size_t>(BytesFree() - min_frame_size, data_size); 2565821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 257f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bool set_fin = fin && bytes_consumed == data_size; // Last frame. 258f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) IOVector frame_data; 259f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) frame_data.AppendIovecAtMostBytes(data.iovec(), data.Size(), 260f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) bytes_consumed); 261f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) DCHECK_EQ(frame_data.TotalBufferSize(), bytes_consumed); 262f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) *frame = QuicFrame(new QuicStreamFrame(id, set_fin, offset, frame_data)); 2632a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return bytes_consumed; 2642a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 2655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 26658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)size_t QuicPacketCreator::CreateStreamFrameWithNotifier( 26758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) QuicStreamId id, 268f2477e01787aa58f445919b809d89e252beef54fTorne (Richard Coles) const IOVector& data, 26958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) QuicStreamOffset offset, 27058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) bool fin, 27158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) QuicAckNotifier* notifier, 27258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) QuicFrame* frame) { 27358537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) size_t bytes_consumed = CreateStreamFrame(id, data, offset, fin, frame); 27458537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 27558537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // The frame keeps track of the QuicAckNotifier until it is serialized into 27658537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // a packet. At that point the notifier is informed of the sequence number 27758537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) // of the packet that this frame was eventually sent in. 27858537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) frame->stream_frame->notifier = notifier; 27958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 28058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) return bytes_consumed; 28158537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles)} 28258537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) 2833551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)SerializedPacket QuicPacketCreator::ReserializeAllFrames( 2843551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) const QuicFrames& frames, 2853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) QuicSequenceNumberLength original_length) { 286cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK(fec_group_.get() == NULL); 287cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const QuicSequenceNumberLength saved_length = sequence_number_length_; 28846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) const QuicSequenceNumberLength saved_next_length = 28946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) next_sequence_number_length_; 290cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) const bool saved_should_fec_protect = should_fec_protect_; 29168043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 292cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Temporarily set the sequence number length and stop FEC protection. 2933551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) sequence_number_length_ = original_length; 29446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) next_sequence_number_length_ = original_length; 295cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) should_fec_protect_ = false; 29668043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 297cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) // Serialize the packet and restore the FEC and sequence number length state. 2983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) SerializedPacket serialized_packet = SerializeAllFrames(frames); 299cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) sequence_number_length_ = saved_length; 30046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) next_sequence_number_length_ = saved_next_length; 301cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) should_fec_protect_ = saved_should_fec_protect; 30268043e1e95eeb07d5cae7aca370b26518b0867d6Torne (Richard Coles) 3033551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return serialized_packet; 3043551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 3053551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3062a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SerializedPacket QuicPacketCreator::SerializeAllFrames( 3072a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const QuicFrames& frames) { 3082a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // TODO(satyamshekhar): Verify that this DCHECK won't fail. What about queued 3092a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // frames from SendStreamData()[send_stream_should_flush_ == false && 3102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) // data.empty() == true] and retransmit due to RTO. 3112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(0u, queued_frames_.size()); 312a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LOG_IF(DFATAL, frames.empty()) 313a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << "Attempt to serialize empty packet"; 3142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) for (size_t i = 0; i < frames.size(); ++i) { 3152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool success = AddFrame(frames[i], false); 3162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(success); 3175821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) } 3182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) SerializedPacket packet = SerializePacket(); 3192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(packet.retransmittable_frames == NULL); 3202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return packet; 3215821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3225821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 323f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles)bool QuicPacketCreator::HasPendingFrames() const { 3242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return !queued_frames_.empty(); 3252a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3265821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3276d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)bool QuicPacketCreator::HasPendingRetransmittableFrames() const { 3286d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) return queued_retransmittable_frames_.get() != NULL && 3296d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) !queued_retransmittable_frames_->frames().empty(); 3306d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles)} 3316d86b77056ed63eb6871182f42a9fd5f07550f90Torne (Richard Coles) 332c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdochsize_t QuicPacketCreator::ExpansionOnNewFrame() const { 333c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // If packet is FEC protected, there's no expansion. 334cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) if (should_fec_protect_) { 335c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return 0; 336c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch } 337c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // If the last frame in the packet is a stream frame, then it will expand to 338c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch // include the stream_length field when a new frame is added. 339c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch bool has_trailing_stream_frame = 340c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch !queued_frames_.empty() && queued_frames_.back().type == STREAM_FRAME; 341c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return has_trailing_stream_frame ? kQuicStreamPayloadLengthSize : 0; 342c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch} 343c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 3442a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)size_t QuicPacketCreator::BytesFree() const { 3452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) const size_t max_plaintext_size = 34646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) framer_->GetMaxPlaintextSize(max_packet_length_); 3471e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DCHECK_GE(max_plaintext_size, PacketSize()); 348c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch return max_plaintext_size - min(max_plaintext_size, PacketSize() 349c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch + ExpansionOnNewFrame()); 3503551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)} 3513551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) 3523551c9c881056c480085172ff9840cab31610854Torne (Richard Coles)size_t QuicPacketCreator::PacketSize() const { 35346d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (!queued_frames_.empty()) { 35446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) return packet_size_; 3553551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) } 35646d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) if (fec_group_.get() == NULL) { 35746d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) // Update sequence number length on packet and FEC boundary. 35846d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) sequence_number_length_ = next_sequence_number_length_; 35946d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) } 36046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) packet_size_ = GetPacketHeaderSize( 36146d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) connection_id_length_, send_version_in_packet_, sequence_number_length_, 36246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) should_fec_protect_ ? IN_FEC_GROUP : NOT_IN_FEC_GROUP); 3633551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) return packet_size_; 3645821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 3655821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3662a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool QuicPacketCreator::AddSavedFrame(const QuicFrame& frame) { 3672a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return AddFrame(frame, true); 3682a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 3695821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 3702a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SerializedPacket QuicPacketCreator::SerializePacket() { 371a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LOG_IF(DFATAL, queued_frames_.empty()) 372a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << "Attempt to serialize empty packet"; 373cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) DCHECK_GE(sequence_number_ + 1, fec_group_number_); 3745821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QuicPacketHeader header; 375cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) FillPacketHeader(should_fec_protect_ ? fec_group_number_ : 0, false, &header); 3762a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 3775d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) MaybeAddPadding(); 3781e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 3791e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) size_t max_plaintext_size = 38046d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) framer_->GetMaxPlaintextSize(max_packet_length_); 3811e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DCHECK_GE(max_plaintext_size, packet_size_); 3821320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // ACK Frames will be truncated due to length only if they're the only frame 3831320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // in the packet, and if packet_size_ was set to max_plaintext_size. If 3841320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // truncation due to length occurred, then GetSerializedFrameLength will have 3851320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci // returned all bytes free. 3861320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci bool possibly_truncated_by_length = packet_size_ == max_plaintext_size && 3871320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci queued_frames_.size() == 1 && 3881320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci queued_frames_.back().type == ACK_FRAME; 38958537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) SerializedPacket serialized = 39058537e28ecd584eab876aee8be7156509866d23aTorne (Richard Coles) framer_->BuildDataPacket(header, queued_frames_, packet_size_); 391a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LOG_IF(DFATAL, !serialized.packet) 392a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << "Failed to serialize " << queued_frames_.size() << " frames."; 3931e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // Because of possible truncation, we can't be confident that our 3941e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) // packet size calculation worked correctly. 3951320f92c476a1ad9d19dba2a48c72b75566198e9Primiano Tucci if (!possibly_truncated_by_length) { 3961e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DCHECK_EQ(packet_size_, serialized.packet->length()); 397cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) } 3983551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) packet_size_ = 0; 3992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) queued_frames_.clear(); 4002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) serialized.retransmittable_frames = queued_retransmittable_frames_.release(); 4012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return serialized; 4025821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4035821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SerializedPacket QuicPacketCreator::SerializeFec() { 4050529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch if (fec_group_.get() == NULL || fec_group_->NumReceivedPackets() <= 0) { 4060529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch LOG(DFATAL) << "SerializeFEC called but no group or zero packets in group."; 4070529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch // TODO(jri): Make this a public method of framer? 4080529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch SerializedPacket kNoPacket(0, PACKET_1BYTE_SEQUENCE_NUMBER, NULL, 0, NULL); 4090529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch return kNoPacket; 4100529e5d033099cbfc42635f6f6183833b09dff6eBen Murdoch } 4112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK_EQ(0u, queued_frames_.size()); 4125821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QuicPacketHeader header; 4135d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) FillPacketHeader(fec_group_number_, true, &header); 4142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) QuicFecData fec_data; 4152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fec_data.fec_group = fec_group_->min_protected_packet(); 4162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fec_data.redundancy = fec_group_->payload_parity(); 4172385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch SerializedPacket serialized = framer_->BuildFecPacket(header, fec_data); 4182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) fec_group_.reset(NULL); 4193551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) packet_size_ = 0; 420a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) LOG_IF(DFATAL, !serialized.packet) 421a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) << "Failed to serialize fec packet for group:" << fec_data.fec_group; 42246d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK_GE(max_packet_length_, serialized.packet->length()); 4232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return serialized; 4242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4255821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4262a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)SerializedPacket QuicPacketCreator::SerializeConnectionClose( 4272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) QuicConnectionCloseFrame* close_frame) { 4285821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QuicFrames frames; 4292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) frames.push_back(QuicFrame(close_frame)); 4302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return SerializeAllFrames(frames); 4315821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4325821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)QuicEncryptedPacket* QuicPacketCreator::SerializeVersionNegotiationPacket( 434558790d6acca3451cf3a6b497803a5f07d0bec58Ben Murdoch const QuicVersionVector& supported_versions) { 435f8ee788a64d60abd8f2d742a5fdedde054ecd910Torne (Richard Coles) DCHECK(framer_->is_server()); 4362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) QuicPacketPublicHeader header; 437a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) header.connection_id = connection_id_; 4382a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) header.reset_flag = false; 4392a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) header.version_flag = true; 4402a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) header.versions = supported_versions; 4412a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) QuicEncryptedPacket* encrypted = 4422385ea399aae016c0806a4f9ef3c9cfe3d2a39dfBen Murdoch framer_->BuildVersionNegotiationPacket(header, supported_versions); 4432a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) DCHECK(encrypted); 44446d4c2bc3267f3f028f39e7e311b0f89aba2e4fdTorne (Richard Coles) DCHECK_GE(max_packet_length_, encrypted->length()); 4452a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return encrypted; 4465821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4475821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4485821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)void QuicPacketCreator::FillPacketHeader(QuicFecGroupNumber fec_group, 4492a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool fec_flag, 4505821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) QuicPacketHeader* header) { 451a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) header->public_header.connection_id = connection_id_; 4522a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) header->public_header.reset_flag = false; 4532a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) header->public_header.version_flag = send_version_in_packet_; 4542a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) header->fec_flag = fec_flag; 4555821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header->packet_sequence_number = ++sequence_number_; 4563551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) header->public_header.sequence_number_length = sequence_number_length_; 4575d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) header->entropy_flag = random_bool_source_->RandBool(); 458868fa2fe829687343ffae624259930155e16dbd8Torne (Richard Coles) header->is_in_fec_group = fec_group == 0 ? NOT_IN_FEC_GROUP : IN_FEC_GROUP; 4595821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) header->fec_group = fec_group; 4605821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} 4615821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles) 4622a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool QuicPacketCreator::ShouldRetransmit(const QuicFrame& frame) { 463a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) switch (frame.type) { 464a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case ACK_FRAME: 465a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case CONGESTION_FEEDBACK_FRAME: 466a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case PADDING_FRAME: 467a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) case STOP_WAITING_FRAME: 468a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return false; 469a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) default: 470a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) return true; 471a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) } 4722a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 4732a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 4742a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)bool QuicPacketCreator::AddFrame(const QuicFrame& frame, 4752a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) bool save_retransmittable_frames) { 4765d1f7b1de12d16ceb2c938c56701a3e8bfa558f7Torne (Richard Coles) DVLOG(1) << "Adding frame: " << frame; 477cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) InFecGroup is_in_fec_group = MaybeUpdateLengthsAndStartFec(); 478cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) 4792a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) size_t frame_len = framer_->GetSerializedFrameLength( 480c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch frame, BytesFree(), queued_frames_.empty(), true, is_in_fec_group, 481cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles) sequence_number_length_); 4822a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (frame_len == 0) { 4832a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return false; 4842a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4853551c9c881056c480085172ff9840cab31610854Torne (Richard Coles) DCHECK_LT(0u, packet_size_); 486c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch packet_size_ += ExpansionOnNewFrame() + frame_len; 487c5cede9ae108bb15f6b7a8aea21c7e1fefa2834cBen Murdoch 4882a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (save_retransmittable_frames && ShouldRetransmit(frame)) { 4892a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (queued_retransmittable_frames_.get() == NULL) { 4902a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) queued_retransmittable_frames_.reset(new RetransmittableFrames()); 4912a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4922a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) if (frame.type == STREAM_FRAME) { 4932a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) queued_frames_.push_back( 4942a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) queued_retransmittable_frames_->AddStreamFrame(frame.stream_frame)); 4952a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 4962a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) queued_frames_.push_back( 4972a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) queued_retransmittable_frames_->AddNonStreamFrame(frame)); 4982a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 4992a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } else { 5002a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) queued_frames_.push_back(frame); 5012a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) } 5022a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) return true; 5032a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)} 5042a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) 5051e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)void QuicPacketCreator::MaybeAddPadding() { 50629b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch if (BytesFree() == 0) { 50729b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch // Don't pad full packets. 5081e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return; 5091e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 51029b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch 51129b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch // Since ReserializeAllFrames does not populate queued_retransmittable_frames_ 51229b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch // it's not sufficient to simply call 51329b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch // queued_retransmittable_frames_->HasCryptoHandshake(). 51429b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch // TODO(rch): we should really make ReserializeAllFrames not be a special 51529b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch // case! 51629b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch 51729b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch // If any of the frames in the current packet are on the crypto stream 51829b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch // then they contain handshake messagses, and we should pad them. 51929b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch bool is_handshake = false; 52029b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch for (const QuicFrame& frame : queued_frames_) { 52129b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch if (frame.type == STREAM_FRAME && 52229b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch frame.stream_frame->stream_id == kCryptoStreamId) { 52329b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch is_handshake = true; 52429b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch break; 52529b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch } 5261e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 52729b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch if (!is_handshake) { 5281e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) return; 5291e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) } 53029b820f8d84e3bc97d62552e54923c42407f2f29Ben Murdoch 5311e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) QuicPaddingFrame padding; 5321e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) bool success = AddFrame(QuicFrame(&padding), false); 5331e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) DCHECK(success); 5341e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles)} 5351e9bf3e0803691d0a228da41fc608347b6db4340Torne (Richard Coles) 5365821806d5e7f356e8fa4b058a389a808ea183019Torne (Richard Coles)} // namespace net 537