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

Unified Diff: net/quic/quic_packet_generator.cc

Issue 12334063: Land recent QUIC changes. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: more EXPECT_FALSE Created 7 years, 10 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_generator.h ('k') | net/quic/quic_packet_generator_test.cc » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: net/quic/quic_packet_generator.cc
diff --git a/net/quic/quic_packet_generator.cc b/net/quic/quic_packet_generator.cc
new file mode 100644
index 0000000000000000000000000000000000000000..fb4bcf2956d53c42d57e2cdcdb84eca9175d95d0
--- /dev/null
+++ b/net/quic/quic_packet_generator.cc
@@ -0,0 +1,203 @@
+// 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_generator.h"
+
+#include "base/logging.h"
+#include "net/quic/quic_fec_group.h"
+#include "net/quic/quic_utils.h"
+
+using base::StringPiece;
+
+namespace net {
+
+QuicPacketGenerator::QuicPacketGenerator(DelegateInterface* delegate,
+ QuicPacketCreator* creator)
+ : delegate_(delegate),
+ packet_creator_(creator),
+ should_flush_(true),
+ should_send_ack_(false),
+ should_send_feedback_(false) {
+}
+
+QuicPacketGenerator::~QuicPacketGenerator() {
+ for (QuicFrames::iterator it = queued_control_frames_.begin();
+ it != queued_control_frames_.end(); ++it) {
+ switch (it->type) {
+ case PADDING_FRAME:
+ delete it->padding_frame;
+ break;
+ case STREAM_FRAME:
+ delete it->stream_frame;
+ break;
+ case ACK_FRAME:
+ delete it->ack_frame;
+ break;
+ case CONGESTION_FEEDBACK_FRAME:
+ delete it->congestion_feedback_frame;
+ break;
+ case RST_STREAM_FRAME:
+ delete it->rst_stream_frame;
+ break;
+ case CONNECTION_CLOSE_FRAME:
+ delete it->connection_close_frame;
+ break;
+ case GOAWAY_FRAME:
+ delete it->goaway_frame;
+ break;
+ case NUM_FRAME_TYPES:
+ DCHECK(false) << "Cannot delete type: " << it->type;
+ }
+ }
+}
+
+void QuicPacketGenerator::SetShouldSendAck(bool also_send_feedback) {
+ should_send_ack_ = true;
+ should_send_feedback_ = also_send_feedback;
+ SendQueuedData();
+}
+
+
+void QuicPacketGenerator::AddControlFrame(const QuicFrame& frame) {
+ queued_control_frames_.push_back(frame);
+ SendQueuedData();
+}
+
+QuicConsumedData QuicPacketGenerator::ConsumeData(QuicStreamId id,
+ StringPiece data,
+ QuicStreamOffset offset,
+ bool fin) {
+ SendQueuedData();
+
+ size_t total_bytes_consumed = 0;
+ bool fin_consumed = false;
+
+ // Make sure any queued data gets sent before new data.
+ // SendQueuedData();
+
+ while (delegate_->CanWrite(false)) {
+ // TODO(rch) figure out FEC.
+ // packet_creator_.MaybeStartFEC();
+ QuicFrame frame;
+ size_t bytes_consumed = packet_creator_->CreateStreamFrame(
+ id, data, offset + total_bytes_consumed, fin, &frame);
+ bool success = packet_creator_->AddSavedFrame(frame);
+ DCHECK(success);
+
+ total_bytes_consumed += bytes_consumed;
+ fin_consumed = fin && bytes_consumed == data.size();
+ data.remove_prefix(bytes_consumed);
+ DCHECK(data.empty() || packet_creator_->BytesFree() == 0u);
+
+ // TODO(ianswett): Restore packet reordering.
+ if (should_flush_ || !packet_creator_->HasRoomForStreamFrame()) {
+ SerializeAndSendPacket();
+ }
+
+ if (data.empty()) {
+ // We're done writing the data. Exit the loop.
+ // We don't make this a precondition because we could have 0 bytes of data
+ // if we're simply writing a fin.
+ break;
+ }
+ }
+
+ // Ensure the FEC group is closed at the end of this method unless other
+ // writes are pending.
+ if (should_flush_ && packet_creator_->ShouldSendFec(true)) {
+ SerializedPacket serialized_fec = packet_creator_->SerializeFec();
+ DCHECK(serialized_fec.packet);
+ delegate_->OnSerializedPacket(serialized_fec);
+ }
+
+ DCHECK(!should_flush_ || !packet_creator_->HasPendingFrames());
+ return QuicConsumedData(total_bytes_consumed, fin_consumed);
+}
+
+void QuicPacketGenerator::SendQueuedData() {
+ while (HasPendingData() && delegate_->CanWrite(false)) {
+ if (!AddNextPendingFrame()) {
+ // Packet was full, so serialize and send it.
+ SerializeAndSendPacket();
+ }
+ }
+
+ if (should_flush_) {
+ if (packet_creator_->HasPendingFrames()) {
+ SerializeAndSendPacket();
+ }
+
+ // Ensure the FEC group is closed at the end of this method unless other
+ // writes are pending.
+ if (packet_creator_->ShouldSendFec(true)) {
+ SerializedPacket serialized_fec = packet_creator_->SerializeFec();
+ DCHECK(serialized_fec.packet);
+ delegate_->OnSerializedPacket(serialized_fec);
+ }
+ }
+}
+
+void QuicPacketGenerator::StartBatchOperations() {
+ should_flush_ = false;
+}
+
+void QuicPacketGenerator::FinishBatchOperations() {
+ should_flush_ = true;
+ SendQueuedData();
+}
+
+bool QuicPacketGenerator::HasQueuedData() const {
+ return packet_creator_->HasPendingFrames() || HasPendingData();
+}
+
+bool QuicPacketGenerator::HasPendingData() const {
+ return should_send_ack_ || should_send_feedback_ ||
+ !queued_control_frames_.empty();
+}
+
+bool QuicPacketGenerator::AddNextPendingFrame() {
+ if (should_send_ack_) {
+ pending_ack_frame_.reset(delegate_->CreateAckFrame());
+ if (!packet_creator_->AddSavedFrame(QuicFrame(pending_ack_frame_.get()))) {
+ // packet was full
+ return false;
+ }
+ should_send_ack_ = false;
+ return true;
+ }
+
+ if (should_send_feedback_) {
+ pending_feedback_frame_.reset(delegate_->CreateFeedbackFrame());
+ if (!packet_creator_->AddSavedFrame(QuicFrame(
+ pending_feedback_frame_.get()))) {
+ // packet was full
+ return false;
+ }
+ should_send_feedback_ = false;
+ return true;
+ }
+
+ DCHECK(!queued_control_frames_.empty());
+ if (!packet_creator_->AddSavedFrame(queued_control_frames_.back())) {
+ // packet was full
+ return false;
+ }
+ queued_control_frames_.pop_back();
+ return true;
+}
+
+void QuicPacketGenerator::SerializeAndSendPacket() {
+ packet_creator_->MaybeStartFEC();
+ SerializedPacket serialized_packet = packet_creator_->SerializePacket();
+ DCHECK(serialized_packet.packet);
+ delegate_->OnSerializedPacket(serialized_packet);
+
+ if (packet_creator_->ShouldSendFec(false)) {
+ SerializedPacket serialized_fec = packet_creator_->SerializeFec();
+ DCHECK(serialized_fec.packet);
+ delegate_->OnSerializedPacket(serialized_fec);
+ }
+}
+
+} // namespace net
« no previous file with comments | « net/quic/quic_packet_generator.h ('k') | net/quic/quic_packet_generator_test.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698