Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(449)

Unified Diff: net/quic/quic_packet_creator.cc

Issue 992733002: Remove //net (except for Android test stuff) and sdch (Closed) Base URL: git@github.com:domokit/mojo.git@master
Patch Set: Created 5 years, 9 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « net/quic/quic_packet_creator.h ('k') | net/quic/quic_packet_creator_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/quic/quic_packet_creator.cc
diff --git a/net/quic/quic_packet_creator.cc b/net/quic/quic_packet_creator.cc
deleted file mode 100644
index e91efa21b2b037fecf8eca3cd3a1dd8a304ca71f..0000000000000000000000000000000000000000
--- a/net/quic/quic_packet_creator.cc
+++ /dev/null
@@ -1,563 +0,0 @@
-// 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.
-
-#include "net/quic/quic_packet_creator.h"
-
-#include "base/basictypes.h"
-#include "base/logging.h"
-#include "net/quic/crypto/quic_random.h"
-#include "net/quic/quic_ack_notifier.h"
-#include "net/quic/quic_data_writer.h"
-#include "net/quic/quic_fec_group.h"
-#include "net/quic/quic_utils.h"
-
-using base::StringPiece;
-using std::make_pair;
-using std::max;
-using std::min;
-using std::pair;
-using std::vector;
-
-namespace net {
-
-namespace {
-
-// Default max packets in an FEC group.
-static const size_t kDefaultMaxPacketsPerFecGroup = 10;
-// Lowest max packets in an FEC group.
-static const size_t kLowestMaxPacketsPerFecGroup = 2;
-
-} // namespace
-
-// A QuicRandom wrapper that gets a bucket of entropy and distributes it
-// bit-by-bit. Replenishes the bucket as needed. Not thread-safe. Expose this
-// class if single bit randomness is needed elsewhere.
-class QuicRandomBoolSource {
- public:
- // random: Source of entropy. Not owned.
- explicit QuicRandomBoolSource(QuicRandom* random)
- : random_(random),
- bit_bucket_(0),
- bit_mask_(0) {}
-
- ~QuicRandomBoolSource() {}
-
- // Returns the next random bit from the bucket.
- bool RandBool() {
- if (bit_mask_ == 0) {
- bit_bucket_ = random_->RandUint64();
- bit_mask_ = 1;
- }
- bool result = ((bit_bucket_ & bit_mask_) != 0);
- bit_mask_ <<= 1;
- return result;
- }
-
- private:
- // Source of entropy.
- QuicRandom* random_;
- // Stored random bits.
- uint64 bit_bucket_;
- // The next available bit has "1" in the mask. Zero means empty bucket.
- uint64 bit_mask_;
-
- DISALLOW_COPY_AND_ASSIGN(QuicRandomBoolSource);
-};
-
-QuicPacketCreator::QuicPacketCreator(QuicConnectionId connection_id,
- QuicFramer* framer,
- QuicRandom* random_generator)
- : connection_id_(connection_id),
- encryption_level_(ENCRYPTION_NONE),
- framer_(framer),
- random_bool_source_(new QuicRandomBoolSource(random_generator)),
- sequence_number_(0),
- should_fec_protect_(false),
- fec_group_number_(0),
- send_version_in_packet_(!framer->is_server()),
- max_packet_length_(kDefaultMaxPacketSize),
- max_packets_per_fec_group_(kDefaultMaxPacketsPerFecGroup),
- connection_id_length_(PACKET_8BYTE_CONNECTION_ID),
- next_sequence_number_length_(PACKET_1BYTE_SEQUENCE_NUMBER),
- sequence_number_length_(next_sequence_number_length_),
- packet_size_(0) {
- framer_->set_fec_builder(this);
-}
-
-QuicPacketCreator::~QuicPacketCreator() {
-}
-
-void QuicPacketCreator::OnBuiltFecProtectedPayload(
- const QuicPacketHeader& header, StringPiece payload) {
- if (fec_group_.get()) {
- DCHECK_NE(0u, header.fec_group);
- fec_group_->Update(encryption_level_, header, payload);
- }
-}
-
-void QuicPacketCreator::set_max_packets_per_fec_group(
- size_t max_packets_per_fec_group) {
- max_packets_per_fec_group_ = max(kLowestMaxPacketsPerFecGroup,
- max_packets_per_fec_group);
- DCHECK_LT(0u, max_packets_per_fec_group_);
-}
-
-bool QuicPacketCreator::ShouldSendFec(bool force_close) const {
- DCHECK(!HasPendingFrames());
- return fec_group_.get() != nullptr && fec_group_->NumReceivedPackets() > 0 &&
- (force_close ||
- fec_group_->NumReceivedPackets() >= max_packets_per_fec_group_);
-}
-
-bool QuicPacketCreator::IsFecGroupOpen() const {
- return fec_group_.get() != nullptr;
-}
-
-void QuicPacketCreator::StartFecProtectingPackets() {
- if (!IsFecEnabled()) {
- LOG(DFATAL) << "Cannot start FEC protection when FEC is not enabled.";
- return;
- }
- // TODO(jri): This currently requires that the generator flush out any
- // pending frames when FEC protection is turned on. If current packet can be
- // converted to an FEC protected packet, do it. This will require the
- // generator to check if the resulting expansion still allows the incoming
- // frame to be added to the packet.
- if (HasPendingFrames()) {
- LOG(DFATAL) << "Cannot start FEC protection with pending frames.";
- return;
- }
- DCHECK(!should_fec_protect_);
- should_fec_protect_ = true;
-}
-
-void QuicPacketCreator::StopFecProtectingPackets() {
- if (fec_group_.get() != nullptr) {
- LOG(DFATAL) << "Cannot stop FEC protection with open FEC group.";
- return;
- }
- DCHECK(should_fec_protect_);
- should_fec_protect_ = false;
- fec_group_number_ = 0;
-}
-
-bool QuicPacketCreator::IsFecProtected() const {
- return should_fec_protect_;
-}
-
-bool QuicPacketCreator::IsFecEnabled() const {
- return max_packets_per_fec_group_ > 0;
-}
-
-InFecGroup QuicPacketCreator::MaybeUpdateLengthsAndStartFec() {
- if (fec_group_.get() != nullptr) {
- // Don't update any lengths when an FEC group is open, to ensure same
- // packet header size in all packets within a group.
- return IN_FEC_GROUP;
- }
- if (!queued_frames_.empty()) {
- // Don't change creator state if there are frames queued.
- return fec_group_.get() == nullptr ? NOT_IN_FEC_GROUP : IN_FEC_GROUP;
- }
-
- // Update sequence number length only on packet and FEC group boundaries.
- sequence_number_length_ = next_sequence_number_length_;
-
- if (!should_fec_protect_) {
- return NOT_IN_FEC_GROUP;
- }
- // Start a new FEC group since protection is on. Set the fec group number to
- // the sequence number of the next packet.
- fec_group_number_ = sequence_number() + 1;
- fec_group_.reset(new QuicFecGroup());
- return IN_FEC_GROUP;
-}
-
-// Stops serializing version of the protocol in packets sent after this call.
-// A packet that is already open might send kQuicVersionSize bytes less than the
-// maximum packet size if we stop sending version before it is serialized.
-void QuicPacketCreator::StopSendingVersion() {
- DCHECK(send_version_in_packet_);
- send_version_in_packet_ = false;
- if (packet_size_ > 0) {
- DCHECK_LT(kQuicVersionSize, packet_size_);
- packet_size_ -= kQuicVersionSize;
- }
-}
-
-void QuicPacketCreator::UpdateSequenceNumberLength(
- QuicPacketSequenceNumber least_packet_awaited_by_peer,
- QuicPacketCount max_packets_in_flight) {
- DCHECK_LE(least_packet_awaited_by_peer, sequence_number_ + 1);
- // Since the packet creator will not change sequence number length mid FEC
- // group, include the size of an FEC group to be safe.
- const QuicPacketSequenceNumber current_delta =
- max_packets_per_fec_group_ + sequence_number_ + 1
- - least_packet_awaited_by_peer;
- const uint64 delta = max(current_delta, max_packets_in_flight);
- next_sequence_number_length_ =
- QuicFramer::GetMinSequenceNumberLength(delta * 4);
-}
-
-bool QuicPacketCreator::HasRoomForStreamFrame(QuicStreamId id,
- QuicStreamOffset offset) const {
- // TODO(jri): This is a simple safe decision for now, but make
- // is_in_fec_group a parameter. Same as with all public methods in
- // QuicPacketCreator.
- return BytesFree() >
- QuicFramer::GetMinStreamFrameSize(id, offset, true,
- should_fec_protect_ ? IN_FEC_GROUP :
- NOT_IN_FEC_GROUP);
-}
-
-// static
-size_t QuicPacketCreator::StreamFramePacketOverhead(
- QuicConnectionIdLength connection_id_length,
- bool include_version,
- QuicSequenceNumberLength sequence_number_length,
- QuicStreamOffset offset,
- InFecGroup is_in_fec_group) {
- return GetPacketHeaderSize(connection_id_length, include_version,
- sequence_number_length, is_in_fec_group) +
- // Assumes this is a stream with a single lone packet.
- QuicFramer::GetMinStreamFrameSize(1u, offset, true, is_in_fec_group);
-}
-
-size_t QuicPacketCreator::CreateStreamFrame(QuicStreamId id,
- const IOVector& data,
- QuicStreamOffset offset,
- bool fin,
- QuicFrame* frame) {
- DCHECK_GT(max_packet_length_, StreamFramePacketOverhead(
- connection_id_length_, kIncludeVersion,
- PACKET_6BYTE_SEQUENCE_NUMBER, offset, IN_FEC_GROUP));
-
- InFecGroup is_in_fec_group = MaybeUpdateLengthsAndStartFec();
-
- LOG_IF(DFATAL, !HasRoomForStreamFrame(id, offset))
- << "No room for Stream frame, BytesFree: " << BytesFree()
- << " MinStreamFrameSize: "
- << QuicFramer::GetMinStreamFrameSize(id, offset, true, is_in_fec_group);
-
- if (data.Empty()) {
- LOG_IF(DFATAL, !fin)
- << "Creating a stream frame with no data or fin.";
- // Create a new packet for the fin, if necessary.
- *frame = QuicFrame(new QuicStreamFrame(id, true, offset, data));
- return 0;
- }
-
- const size_t data_size = data.TotalBufferSize();
- size_t min_frame_size = QuicFramer::GetMinStreamFrameSize(
- id, offset, /* last_frame_in_packet= */ true, is_in_fec_group);
- size_t bytes_consumed = min<size_t>(BytesFree() - min_frame_size, data_size);
-
- bool set_fin = fin && bytes_consumed == data_size; // Last frame.
- IOVector frame_data;
- frame_data.AppendIovecAtMostBytes(data.iovec(), data.Size(),
- bytes_consumed);
- DCHECK_EQ(frame_data.TotalBufferSize(), bytes_consumed);
- *frame = QuicFrame(new QuicStreamFrame(id, set_fin, offset, frame_data));
- return bytes_consumed;
-}
-
-SerializedPacket QuicPacketCreator::ReserializeAllFrames(
- const RetransmittableFrames& frames,
- QuicSequenceNumberLength original_length) {
- DCHECK(fec_group_.get() == nullptr);
- const QuicSequenceNumberLength saved_length = sequence_number_length_;
- const QuicSequenceNumberLength saved_next_length =
- next_sequence_number_length_;
- const bool saved_should_fec_protect = should_fec_protect_;
- const EncryptionLevel default_encryption_level = encryption_level_;
-
- // Temporarily set the sequence number length, stop FEC protection,
- // and change the encryption level.
- sequence_number_length_ = original_length;
- next_sequence_number_length_ = original_length;
- should_fec_protect_ = false;
- encryption_level_ = frames.encryption_level();
-
- // Serialize the packet and restore the FEC and sequence number length state.
- SerializedPacket serialized_packet = SerializeAllFrames(frames.frames());
- sequence_number_length_ = saved_length;
- next_sequence_number_length_ = saved_next_length;
- should_fec_protect_ = saved_should_fec_protect;
- encryption_level_ = default_encryption_level;
-
- return serialized_packet;
-}
-
-// TODO(ianswett): Remove this method, because it's test only.
-SerializedPacket QuicPacketCreator::SerializeAllFrames(
- const QuicFrames& frames) {
- // TODO(satyamshekhar): Verify that this DCHECK won't fail. What about queued
- // frames from SendStreamData()[send_stream_should_flush_ == false &&
- // data.empty() == true] and retransmit due to RTO.
- DCHECK_EQ(0u, queued_frames_.size());
- LOG_IF(DFATAL, frames.empty())
- << "Attempt to serialize empty packet";
- for (const QuicFrame& frame : frames) {
- bool success = AddFrame(frame, false);
- DCHECK(success);
- }
- SerializedPacket packet = SerializePacket();
- DCHECK(packet.retransmittable_frames == nullptr);
- return packet;
-}
-
-bool QuicPacketCreator::HasPendingFrames() const {
- return !queued_frames_.empty();
-}
-
-bool QuicPacketCreator::HasPendingRetransmittableFrames() const {
- return queued_retransmittable_frames_.get() != nullptr &&
- !queued_retransmittable_frames_->frames().empty();
-}
-
-size_t QuicPacketCreator::ExpansionOnNewFrame() const {
- // If packet is FEC protected, there's no expansion.
- if (should_fec_protect_) {
- return 0;
- }
- // If the last frame in the packet is a stream frame, then it will expand to
- // include the stream_length field when a new frame is added.
- bool has_trailing_stream_frame =
- !queued_frames_.empty() && queued_frames_.back().type == STREAM_FRAME;
- return has_trailing_stream_frame ? kQuicStreamPayloadLengthSize : 0;
-}
-
-size_t QuicPacketCreator::BytesFree() const {
- const size_t max_plaintext_size =
- framer_->GetMaxPlaintextSize(max_packet_length_);
- DCHECK_GE(max_plaintext_size, PacketSize());
- return max_plaintext_size - min(max_plaintext_size, PacketSize()
- + ExpansionOnNewFrame());
-}
-
-size_t QuicPacketCreator::PacketSize() const {
- if (!queued_frames_.empty()) {
- return packet_size_;
- }
- if (fec_group_.get() == nullptr) {
- // Update sequence number length on packet and FEC boundary.
- sequence_number_length_ = next_sequence_number_length_;
- }
- packet_size_ = GetPacketHeaderSize(
- connection_id_length_, send_version_in_packet_, sequence_number_length_,
- should_fec_protect_ ? IN_FEC_GROUP : NOT_IN_FEC_GROUP);
- return packet_size_;
-}
-
-bool QuicPacketCreator::AddSavedFrame(const QuicFrame& frame) {
- return AddFrame(frame, true);
-}
-
-SerializedPacket QuicPacketCreator::SerializePacket() {
- LOG_IF(DFATAL, queued_frames_.empty())
- << "Attempt to serialize empty packet";
- DCHECK_GE(sequence_number_ + 1, fec_group_number_);
- QuicPacketHeader header;
- FillPacketHeader(should_fec_protect_ ? fec_group_number_ : 0, false, &header);
-
- MaybeAddPadding();
-
- size_t max_plaintext_size =
- framer_->GetMaxPlaintextSize(max_packet_length_);
- DCHECK_GE(max_plaintext_size, packet_size_);
- // ACK Frames will be truncated due to length only if they're the only frame
- // in the packet, and if packet_size_ was set to max_plaintext_size. If
- // truncation due to length occurred, then GetSerializedFrameLength will have
- // returned all bytes free.
- bool possibly_truncated_by_length = packet_size_ == max_plaintext_size &&
- queued_frames_.size() == 1 &&
- queued_frames_.back().type == ACK_FRAME;
- char buffer[kMaxPacketSize];
- scoped_ptr<QuicPacket> packet;
- // Use the packet_size_ instead of the buffer size to ensure smaller
- // packet sizes are properly used.
- scoped_ptr<char[]> large_buffer;
- if (packet_size_ <= kMaxPacketSize) {
- packet.reset(
- framer_->BuildDataPacket(header, queued_frames_, buffer, packet_size_));
- } else {
- large_buffer.reset(new char[packet_size_]);
- packet.reset(framer_->BuildDataPacket(header, queued_frames_,
- large_buffer.get(), packet_size_));
- }
- LOG_IF(DFATAL, packet == nullptr) << "Failed to serialize "
- << queued_frames_.size() << " frames.";
- // Because of possible truncation, we can't be confident that our
- // packet size calculation worked correctly.
- if (!possibly_truncated_by_length) {
- DCHECK_EQ(packet_size_, packet->length());
- }
- // Immediately encrypt the packet, to ensure we don't encrypt the same packet
- // sequence number multiple times.
- QuicEncryptedPacket* encrypted =
- framer_->EncryptPacket(encryption_level_, sequence_number_, *packet);
- if (encrypted == nullptr) {
- LOG(DFATAL) << "Failed to encrypt packet number " << sequence_number_;
- SerializedPacket kNoPacket(0, PACKET_1BYTE_SEQUENCE_NUMBER, nullptr, 0,
- nullptr);
- return kNoPacket;
- }
-
- packet_size_ = 0;
- queued_frames_.clear();
- return SerializedPacket(header.packet_sequence_number,
- header.public_header.sequence_number_length,
- encrypted, QuicFramer::GetPacketEntropyHash(header),
- queued_retransmittable_frames_.release());
-}
-
-SerializedPacket QuicPacketCreator::SerializeFec() {
- if (fec_group_.get() == nullptr || fec_group_->NumReceivedPackets() <= 0) {
- LOG(DFATAL) << "SerializeFEC called but no group or zero packets in group.";
- // TODO(jri): Make this a public method of framer?
- SerializedPacket kNoPacket(0, PACKET_1BYTE_SEQUENCE_NUMBER, nullptr, 0,
- nullptr);
- return kNoPacket;
- }
- DCHECK_EQ(0u, queued_frames_.size());
- QuicPacketHeader header;
- FillPacketHeader(fec_group_number_, true, &header);
- QuicFecData fec_data;
- fec_data.fec_group = fec_group_->min_protected_packet();
- fec_data.redundancy = fec_group_->payload_parity();
- scoped_ptr<QuicPacket> packet(framer_->BuildFecPacket(header, fec_data));
- fec_group_.reset(nullptr);
- packet_size_ = 0;
- LOG_IF(DFATAL, packet == nullptr)
- << "Failed to serialize fec packet for group:" << fec_data.fec_group;
- DCHECK_GE(max_packet_length_, packet->length());
- // Immediately encrypt the packet, to ensure we don't encrypt the same packet
- // sequence number multiple times.
- QuicEncryptedPacket* encrypted =
- framer_->EncryptPacket(encryption_level_, sequence_number_, *packet);
- if (encrypted == nullptr) {
- LOG(DFATAL) << "Failed to encrypt packet number " << sequence_number_;
- SerializedPacket kNoPacket(0, PACKET_1BYTE_SEQUENCE_NUMBER, nullptr, 0,
- nullptr);
- return kNoPacket;
- }
- SerializedPacket serialized(
- header.packet_sequence_number,
- header.public_header.sequence_number_length, encrypted,
- QuicFramer::GetPacketEntropyHash(header), nullptr);
- serialized.is_fec_packet = true;
- return serialized;
-}
-
-SerializedPacket QuicPacketCreator::SerializeConnectionClose(
- QuicConnectionCloseFrame* close_frame) {
- QuicFrames frames;
- frames.push_back(QuicFrame(close_frame));
- return SerializeAllFrames(frames);
-}
-
-QuicEncryptedPacket* QuicPacketCreator::SerializeVersionNegotiationPacket(
- const QuicVersionVector& supported_versions) {
- DCHECK(framer_->is_server());
- QuicPacketPublicHeader header;
- header.connection_id = connection_id_;
- header.reset_flag = false;
- header.version_flag = true;
- header.versions = supported_versions;
- QuicEncryptedPacket* encrypted =
- framer_->BuildVersionNegotiationPacket(header, supported_versions);
- DCHECK(encrypted);
- DCHECK_GE(max_packet_length_, encrypted->length());
- return encrypted;
-}
-
-void QuicPacketCreator::FillPacketHeader(QuicFecGroupNumber fec_group,
- bool fec_flag,
- QuicPacketHeader* header) {
- header->public_header.connection_id = connection_id_;
- header->public_header.connection_id_length = connection_id_length_;
- header->public_header.reset_flag = false;
- header->public_header.version_flag = send_version_in_packet_;
- header->fec_flag = fec_flag;
- header->packet_sequence_number = ++sequence_number_;
- header->public_header.sequence_number_length = sequence_number_length_;
- header->entropy_flag = random_bool_source_->RandBool();
- header->is_in_fec_group = fec_group == 0 ? NOT_IN_FEC_GROUP : IN_FEC_GROUP;
- header->fec_group = fec_group;
-}
-
-bool QuicPacketCreator::ShouldRetransmit(const QuicFrame& frame) {
- switch (frame.type) {
- case ACK_FRAME:
- case PADDING_FRAME:
- case STOP_WAITING_FRAME:
- return false;
- default:
- return true;
- }
-}
-
-bool QuicPacketCreator::AddFrame(const QuicFrame& frame,
- bool save_retransmittable_frames) {
- DVLOG(1) << "Adding frame: " << frame;
- InFecGroup is_in_fec_group = MaybeUpdateLengthsAndStartFec();
-
- size_t frame_len = framer_->GetSerializedFrameLength(
- frame, BytesFree(), queued_frames_.empty(), true, is_in_fec_group,
- sequence_number_length_);
- if (frame_len == 0) {
- return false;
- }
- DCHECK_LT(0u, packet_size_);
- packet_size_ += ExpansionOnNewFrame() + frame_len;
-
- if (save_retransmittable_frames && ShouldRetransmit(frame)) {
- if (queued_retransmittable_frames_.get() == nullptr) {
- queued_retransmittable_frames_.reset(new RetransmittableFrames());
- }
- if (frame.type == STREAM_FRAME) {
- queued_frames_.push_back(
- queued_retransmittable_frames_->AddStreamFrame(frame.stream_frame));
- } else {
- queued_frames_.push_back(
- queued_retransmittable_frames_->AddNonStreamFrame(frame));
- }
- } else {
- queued_frames_.push_back(frame);
- }
- return true;
-}
-
-void QuicPacketCreator::MaybeAddPadding() {
- if (BytesFree() == 0) {
- // Don't pad full packets.
- return;
- }
-
- // Since ReserializeAllFrames does not populate queued_retransmittable_frames_
- // it's not sufficient to simply call
- // queued_retransmittable_frames_->HasCryptoHandshake().
- // TODO(rch): we should really make ReserializeAllFrames not be a special
- // case!
-
- // If any of the frames in the current packet are on the crypto stream
- // then they contain handshake messagses, and we should pad them.
- bool is_handshake = false;
- for (const QuicFrame& frame : queued_frames_) {
- if (frame.type == STREAM_FRAME &&
- frame.stream_frame->stream_id == kCryptoStreamId) {
- is_handshake = true;
- break;
- }
- }
- if (!is_handshake) {
- return;
- }
-
- QuicPaddingFrame padding;
- bool success = AddFrame(QuicFrame(&padding), false);
- DCHECK(success);
-}
-
-} // namespace net
« no previous file with comments | « net/quic/quic_packet_creator.h ('k') | net/quic/quic_packet_creator_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698