// 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_framer.h" #include "base/hash_tables.h" #include "net/quic/crypto/quic_decrypter.h" #include "net/quic/crypto/quic_encrypter.h" #include "net/quic/quic_data_reader.h" #include "net/quic/quic_data_writer.h" #include "net/quic/quic_utils.h" using base::StringPiece; using std::make_pair; using std::map; using std::numeric_limits; namespace net { namespace { // Mask to select the lowest 48 bits of a sequence number. const QuicPacketSequenceNumber kSequenceNumberMask = GG_UINT64_C(0x0000FFFFFFFFFFFF); // Returns the absolute value of the difference between |a| and |b|. QuicPacketSequenceNumber Delta(QuicPacketSequenceNumber a, QuicPacketSequenceNumber b) { // Since these are unsigned numbers, we can't just return abs(a - b) if (a < b) { return b - a; } return a - b; } QuicPacketSequenceNumber ClosestTo(QuicPacketSequenceNumber target, QuicPacketSequenceNumber a, QuicPacketSequenceNumber b) { return (Delta(target, a) < Delta(target, b)) ? a : b; } } // namespace QuicFramer::QuicFramer(QuicDecrypter* decrypter, QuicEncrypter* encrypter) : visitor_(NULL), fec_builder_(NULL), error_(QUIC_NO_ERROR), last_sequence_number_(0), decrypter_(decrypter), encrypter_(encrypter) { } QuicFramer::~QuicFramer() {} bool CanTruncate(const QuicFrame& frame) { if (frame.type == ACK_FRAME || frame.type == CONNECTION_CLOSE_FRAME) { return true; } return false; } QuicPacket* QuicFramer::ConstructFrameDataPacket( const QuicPacketHeader& header, const QuicFrames& frames) { size_t num_consumed = 0; QuicPacket* packet = ConstructMaxFrameDataPacket(header, frames, &num_consumed); DCHECK_EQ(frames.size(), num_consumed); return packet; } QuicPacket* QuicFramer::ConstructMaxFrameDataPacket( const QuicPacketHeader& header, const QuicFrames& frames, size_t* num_consumed) { DCHECK(!frames.empty()); // Compute the length of the packet. We use "magic numbers" here because // sizeof(member_) is not necessarily the same as sizeof(member_wire_format). const size_t max_plaintext_size = GetMaxPlaintextSize(kMaxPacketSize); size_t len = kPacketHeaderSize; bool truncating = false; for (size_t i = 0; i < frames.size(); ++i) { if (frames[i].type == PADDING_FRAME) { // PADDING implies end of packet so make sure we don't have // more frames on the list. DCHECK_EQ(i, frames.size() - 1); len = max_plaintext_size; *num_consumed = i + 1; break; } size_t frame_len = 1; // Space for the 8 bit type. frame_len += ComputeFramePayloadLength(frames[i]); if (len + frame_len > max_plaintext_size) { // Only truncate the first frame in a packet, so if subsequent ones go // over, stop including more frames. if (i > 0) { break; } if (CanTruncate(frames[0])) { // Truncate the frame so the packet will not exceed kMaxPacketSize. // Note that we may not use every byte of the writer in this case. len = max_plaintext_size; *num_consumed = 1; truncating = true; DLOG(INFO) << "Truncating large frame"; break; } else { return NULL; } } len += frame_len; *num_consumed = i + 1; } if (truncating) { DCHECK_EQ(1u, *num_consumed); } QuicDataWriter writer(len); if (!WritePacketHeader(header, &writer)) { return NULL; } // frame count if (*num_consumed > 256u) { return NULL; } for (size_t i = 0; i < *num_consumed; ++i) { const QuicFrame& frame = frames[i]; if (!writer.WriteUInt8(frame.type)) { return NULL; } switch (frame.type) { case PADDING_FRAME: writer.WritePadding(); break; case STREAM_FRAME: if (!AppendStreamFramePayload(*frame.stream_frame, &writer)) { return NULL; } break; case ACK_FRAME: if (!AppendAckFramePayload(*frame.ack_frame, &writer)) { return NULL; } break; case CONGESTION_FEEDBACK_FRAME: if (!AppendQuicCongestionFeedbackFramePayload( *frame.congestion_feedback_frame, &writer)) { return NULL; } break; case RST_STREAM_FRAME: if (!AppendRstStreamFramePayload(*frame.rst_stream_frame, &writer)) { return NULL; } break; case CONNECTION_CLOSE_FRAME: if (!AppendConnectionCloseFramePayload( *frame.connection_close_frame, &writer)) { return NULL; } break; default: RaiseError(QUIC_INVALID_FRAME_DATA); return NULL; } } DCHECK(truncating || len == writer.length()); // Save the length before writing, because take clears it. len = writer.length(); QuicPacket* packet = QuicPacket::NewDataPacket(writer.take(), len, true); if (fec_builder_) { fec_builder_->OnBuiltFecProtectedPayload(header, packet->FecProtectedData()); } return packet; } QuicPacket* QuicFramer::ConstructFecPacket(const QuicPacketHeader& header, const QuicFecData& fec) { size_t len = kPacketHeaderSize; len += fec.redundancy.length(); QuicDataWriter writer(len); if (!WritePacketHeader(header, &writer)) { return NULL; } if (!writer.WriteBytes(fec.redundancy.data(), fec.redundancy.length())) { return NULL; } return QuicPacket::NewFecPacket(writer.take(), len, true); } // static QuicEncryptedPacket* QuicFramer::ConstructPublicResetPacket( const QuicPublicResetPacket& packet) { DCHECK_EQ(PACKET_PUBLIC_FLAGS_RST, PACKET_PUBLIC_FLAGS_RST & packet.public_header.flags); size_t len = kPublicResetPacketSize; QuicDataWriter writer(len); if (!writer.WriteUInt64(packet.public_header.guid)) { return NULL; } uint8 flags = static_cast(packet.public_header.flags); if (!writer.WriteUInt8(flags)) { return NULL; } if (!writer.WriteUInt64(packet.nonce_proof)) { return NULL; } if (!AppendPacketSequenceNumber(packet.rejected_sequence_number, &writer)) { return NULL; } return new QuicEncryptedPacket(writer.take(), len, true); } // TODO(satyamshekhar): Framer doesn't need addresses. Get rid of them. bool QuicFramer::ProcessPacket(const IPEndPoint& self_address, const IPEndPoint& peer_address, const QuicEncryptedPacket& packet) { DCHECK(!reader_.get()); reader_.reset(new QuicDataReader(packet.data(), packet.length())); // First parse the public header. QuicPacketPublicHeader public_header; if (!ProcessPublicHeader(&public_header)) { DLOG(WARNING) << "Unable to process public header."; reader_.reset(NULL); return RaiseError(QUIC_INVALID_PACKET_HEADER); } bool rv; if (public_header.flags & PACKET_PUBLIC_FLAGS_RST) { rv = ProcessPublicResetPacket(public_header); } else { rv = ProcessDataPacket(public_header, self_address, peer_address, packet); } reader_.reset(NULL); return rv; } bool QuicFramer::ProcessDataPacket( const QuicPacketPublicHeader& public_header, const IPEndPoint& self_address, const IPEndPoint& peer_address, const QuicEncryptedPacket& packet) { visitor_->OnPacket(self_address, peer_address); QuicPacketHeader header(public_header); if (!ProcessPacketHeader(&header, packet)) { DLOG(WARNING) << "Unable to process data packet header."; return RaiseError(QUIC_INVALID_PACKET_HEADER); } if (!visitor_->OnPacketHeader(header)) { return true; } if (packet.length() > kMaxPacketSize) { DLOG(WARNING) << "Packet too large: " << packet.length(); return RaiseError(QUIC_PACKET_TOO_LARGE); } // Handle the payload. if ((header.private_flags & PACKET_PRIVATE_FLAGS_FEC) == 0) { if (header.fec_group != 0) { StringPiece payload = reader_->PeekRemainingPayload(); visitor_->OnFecProtectedPayload(payload); } if (!ProcessFrameData()) { DCHECK_NE(QUIC_NO_ERROR, error_); // ProcessFrameData sets the error. DLOG(WARNING) << "Unable to process frame data."; return false; } } else { QuicFecData fec_data; fec_data.fec_group = header.fec_group; fec_data.redundancy = reader_->ReadRemainingPayload(); visitor_->OnFecData(fec_data); } visitor_->OnPacketComplete(); return true; } bool QuicFramer::ProcessPublicResetPacket( const QuicPacketPublicHeader& public_header) { QuicPublicResetPacket packet(public_header); if (!reader_->ReadUInt64(&packet.nonce_proof)) { set_detailed_error("Unable to read nonce proof."); return false; } // TODO(satyamshekhar): validate nonce to protect against DoS. if (!reader_->ReadUInt48(&packet.rejected_sequence_number)) { set_detailed_error("Unable to read rejected sequence number."); return false; } visitor_->OnPublicResetPacket(packet); return true; } bool QuicFramer::ProcessRevivedPacket(const QuicPacketHeader& header, StringPiece payload) { DCHECK(!reader_.get()); visitor_->OnRevivedPacket(); visitor_->OnPacketHeader(header); if (payload.length() > kMaxPacketSize) { set_detailed_error("Revived packet too large."); return RaiseError(QUIC_PACKET_TOO_LARGE); } reader_.reset(new QuicDataReader(payload.data(), payload.length())); if (!ProcessFrameData()) { DCHECK_NE(QUIC_NO_ERROR, error_); // ProcessFrameData sets the error. DLOG(WARNING) << "Unable to process frame data."; return false; } visitor_->OnPacketComplete(); reader_.reset(NULL); return true; } bool QuicFramer::WritePacketHeader(const QuicPacketHeader& header, QuicDataWriter* writer) { if (!writer->WriteUInt64(header.public_header.guid)) { return false; } uint8 flags =static_cast(header.public_header.flags); if (!writer->WriteUInt8(flags)) { return false; } if (!AppendPacketSequenceNumber(header.packet_sequence_number, writer)) { return false; } flags = static_cast(header.private_flags); if (!writer->WriteUInt8(flags)) { return false; } // Offset from the current packet sequence number to the first fec // protected packet, or kNoFecOffset to signal no FEC protection. uint8 first_fec_protected_packet_offset = kNoFecOffset; // The FEC group number is the sequence number of the first fec // protected packet, or 0 if this packet is not protected. if (header.fec_group != 0) { DCHECK_GE(header.packet_sequence_number, header.fec_group); DCHECK_GT(255u, header.packet_sequence_number - header.fec_group); first_fec_protected_packet_offset = header.packet_sequence_number - header.fec_group; } if (!writer->WriteBytes(&first_fec_protected_packet_offset, 1)) { return false; } return true; } QuicPacketSequenceNumber QuicFramer::CalculatePacketSequenceNumberFromWire( QuicPacketSequenceNumber packet_sequence_number) const { // The new sequence number might have wrapped to the next epoc, or // it might have reverse wrapped to the previous epoch, or it might // remain in the same epoch. Select the sequence number closest to the // previous sequence number. QuicPacketSequenceNumber epoch = last_sequence_number_ & ~kSequenceNumberMask; QuicPacketSequenceNumber prev_epoch = epoch - (GG_UINT64_C(1) << 48); QuicPacketSequenceNumber next_epoch = epoch + (GG_UINT64_C(1) << 48); return ClosestTo(last_sequence_number_, epoch + packet_sequence_number, ClosestTo(last_sequence_number_, prev_epoch + packet_sequence_number, next_epoch + packet_sequence_number)); } /* static */ bool QuicFramer::ReadGuidFromPacket(const QuicEncryptedPacket& packet, QuicGuid* guid) { QuicDataReader reader(packet.data(), packet.length()); return reader.ReadUInt64(guid); } bool QuicFramer::ProcessPublicHeader(QuicPacketPublicHeader* public_header) { if (!reader_->ReadUInt64(&public_header->guid)) { set_detailed_error("Unable to read GUID."); return false; } uint8 public_flags; if (!reader_->ReadBytes(&public_flags, 1)) { set_detailed_error("Unable to read public flags."); return false; } if (public_flags > PACKET_PUBLIC_FLAGS_MAX) { set_detailed_error("Illegal public flags value."); return false; } public_header->flags = static_cast(public_flags); return true; } bool QuicFramer::ProcessPacketHeader( QuicPacketHeader* header, const QuicEncryptedPacket& packet) { if (!ProcessPacketSequenceNumber(&header->packet_sequence_number)) { set_detailed_error("Unable to read sequence number."); return false; } if (header->packet_sequence_number == 0u) { set_detailed_error("Packet sequence numbers cannot be 0."); return false; } if (!DecryptPayload(packet)) { DLOG(WARNING) << "Unable to decrypt payload."; return RaiseError(QUIC_DECRYPTION_FAILURE); } uint8 private_flags; if (!reader_->ReadBytes(&private_flags, 1)) { set_detailed_error("Unable to read private flags."); return false; } if (private_flags > PACKET_PRIVATE_FLAGS_MAX) { set_detailed_error("Illegal private flags value."); return false; } header->private_flags = static_cast(private_flags); uint8 first_fec_protected_packet_offset; if (!reader_->ReadBytes(&first_fec_protected_packet_offset, 1)) { set_detailed_error("Unable to read first fec protected packet offset."); return false; } header->fec_group = first_fec_protected_packet_offset == kNoFecOffset ? 0 : header->packet_sequence_number - first_fec_protected_packet_offset; // Set the last sequence number after we have decrypted the packet // so we are confident is not attacker controlled. last_sequence_number_ = header->packet_sequence_number; return true; } bool QuicFramer::ProcessPacketSequenceNumber( QuicPacketSequenceNumber* sequence_number) { QuicPacketSequenceNumber wire_sequence_number; if (!reader_->ReadUInt48(&wire_sequence_number)) { return false; } *sequence_number = CalculatePacketSequenceNumberFromWire(wire_sequence_number); return true; } bool QuicFramer::ProcessFrameData() { if (reader_->IsDoneReading()) { set_detailed_error("Unable to read frame type."); return RaiseError(QUIC_INVALID_FRAME_DATA); } while (!reader_->IsDoneReading()) { uint8 frame_type; if (!reader_->ReadBytes(&frame_type, 1)) { set_detailed_error("Unable to read frame type."); return RaiseError(QUIC_INVALID_FRAME_DATA); } switch (frame_type) { case PADDING_FRAME: // We're done with the packet return true; case STREAM_FRAME: if (!ProcessStreamFrame()) { return RaiseError(QUIC_INVALID_FRAME_DATA); } break; case ACK_FRAME: { QuicAckFrame frame; if (!ProcessAckFrame(&frame)) { return RaiseError(QUIC_INVALID_FRAME_DATA); } break; } case CONGESTION_FEEDBACK_FRAME: { QuicCongestionFeedbackFrame frame; if (!ProcessQuicCongestionFeedbackFrame(&frame)) { return RaiseError(QUIC_INVALID_FRAME_DATA); } break; } case RST_STREAM_FRAME: if (!ProcessRstStreamFrame()) { return RaiseError(QUIC_INVALID_RST_STREAM_DATA); } break; case CONNECTION_CLOSE_FRAME: if (!ProcessConnectionCloseFrame()) { return RaiseError(QUIC_INVALID_CONNECTION_CLOSE_DATA); } break; default: set_detailed_error("Illegal frame type."); DLOG(WARNING) << "Illegal frame type: " << static_cast(frame_type); return RaiseError(QUIC_INVALID_FRAME_DATA); } } return true; } bool QuicFramer::ProcessStreamFrame() { QuicStreamFrame frame; if (!reader_->ReadUInt32(&frame.stream_id)) { set_detailed_error("Unable to read stream_id."); return false; } uint8 fin; if (!reader_->ReadBytes(&fin, 1)) { set_detailed_error("Unable to read fin."); return false; } if (fin > 1) { set_detailed_error("Invalid fin value."); return false; } frame.fin = (fin == 1); if (!reader_->ReadUInt64(&frame.offset)) { set_detailed_error("Unable to read offset."); return false; } if (!reader_->ReadStringPiece16(&frame.data)) { set_detailed_error("Unable to read frame data."); return false; } visitor_->OnStreamFrame(frame); return true; } bool QuicFramer::ProcessAckFrame(QuicAckFrame* frame) { if (!ProcessSentInfo(&frame->sent_info)) { return false; } if (!ProcessReceivedInfo(&frame->received_info)) { return false; } visitor_->OnAckFrame(*frame); return true; } bool QuicFramer::ProcessReceivedInfo(ReceivedPacketInfo* received_info) { if (!ProcessPacketSequenceNumber(&received_info->largest_observed)) { set_detailed_error("Unable to read largest observed."); return false; } uint8 num_missing_packets; if (!reader_->ReadBytes(&num_missing_packets, 1)) { set_detailed_error("Unable to read num missing packets."); return false; } for (int i = 0; i < num_missing_packets; ++i) { QuicPacketSequenceNumber sequence_number; if (!ProcessPacketSequenceNumber(&sequence_number)) { set_detailed_error("Unable to read sequence number in missing packets."); return false; } received_info->missing_packets.insert(sequence_number); } return true; } bool QuicFramer::ProcessSentInfo(SentPacketInfo* sent_info) { if (!ProcessPacketSequenceNumber(&sent_info->least_unacked)) { set_detailed_error("Unable to read least unacked."); return false; } return true; } bool QuicFramer::ProcessQuicCongestionFeedbackFrame( QuicCongestionFeedbackFrame* frame) { uint8 feedback_type; if (!reader_->ReadBytes(&feedback_type, 1)) { set_detailed_error("Unable to read congestion feedback type."); return false; } frame->type = static_cast(feedback_type); switch (frame->type) { case kInterArrival: { CongestionFeedbackMessageInterArrival* inter_arrival = &frame->inter_arrival; if (!reader_->ReadUInt16( &inter_arrival->accumulated_number_of_lost_packets)) { set_detailed_error( "Unable to read accumulated number of lost packets."); return false; } uint8 num_received_packets; if (!reader_->ReadBytes(&num_received_packets, 1)) { set_detailed_error("Unable to read num received packets."); return false; } if (num_received_packets > 0u) { uint64 smallest_received; if (!ProcessPacketSequenceNumber(&smallest_received)) { set_detailed_error("Unable to read smallest received."); return false; } uint64 time_received_us; if (!reader_->ReadUInt64(&time_received_us)) { set_detailed_error("Unable to read time received."); return false; } inter_arrival->received_packet_times.insert( make_pair(smallest_received, QuicTime::FromMicroseconds(time_received_us))); for (int i = 0; i < num_received_packets - 1; ++i) { uint16 sequence_delta; if (!reader_->ReadUInt16(&sequence_delta)) { set_detailed_error( "Unable to read sequence delta in received packets."); return false; } int32 time_delta_us; if (!reader_->ReadBytes(&time_delta_us, sizeof(time_delta_us))) { set_detailed_error( "Unable to read time delta in received packets."); return false; } QuicPacketSequenceNumber packet = smallest_received + sequence_delta; inter_arrival->received_packet_times.insert( make_pair(packet, QuicTime::FromMicroseconds(time_received_us + time_delta_us))); } } break; } case kFixRate: { CongestionFeedbackMessageFixRate* fix_rate = &frame->fix_rate; if (!reader_->ReadUInt32(&fix_rate->bitrate_in_bytes_per_second)) { set_detailed_error("Unable to read bitrate."); return false; } break; } case kTCP: { CongestionFeedbackMessageTCP* tcp = &frame->tcp; if (!reader_->ReadUInt16(&tcp->accumulated_number_of_lost_packets)) { set_detailed_error( "Unable to read accumulated number of lost packets."); return false; } if (!reader_->ReadUInt16(&tcp->receive_window)) { set_detailed_error("Unable to read receive window."); return false; } break; } default: set_detailed_error("Illegal congestion feedback type."); DLOG(WARNING) << "Illegal congestion feedback type: " << frame->type; return RaiseError(QUIC_INVALID_FRAME_DATA); } visitor_->OnCongestionFeedbackFrame(*frame); return true; } bool QuicFramer::ProcessRstStreamFrame() { QuicRstStreamFrame frame; if (!reader_->ReadUInt32(&frame.stream_id)) { set_detailed_error("Unable to read stream_id."); return false; } if (!reader_->ReadUInt64(&frame.offset)) { set_detailed_error("Unable to read offset in rst frame."); return false; } uint32 error_code; if (!reader_->ReadUInt32(&error_code)) { set_detailed_error("Unable to read rst stream error code."); return false; } frame.error_code = static_cast(error_code); StringPiece error_details; if (!reader_->ReadStringPiece16(&error_details)) { set_detailed_error("Unable to read rst stream error details."); return false; } frame.error_details = error_details.as_string(); visitor_->OnRstStreamFrame(frame); return true; } bool QuicFramer::ProcessConnectionCloseFrame() { QuicConnectionCloseFrame frame; uint32 error_code; if (!reader_->ReadUInt32(&error_code)) { set_detailed_error("Unable to read connection close error code."); return false; } frame.error_code = static_cast(error_code); StringPiece error_details; if (!reader_->ReadStringPiece16(&error_details)) { set_detailed_error("Unable to read connection close error details."); return false; } frame.error_details = error_details.as_string(); if (!ProcessAckFrame(&frame.ack_frame)) { DLOG(WARNING) << "Unable to process ack frame."; return false; } visitor_->OnConnectionCloseFrame(frame); return true; } QuicEncryptedPacket* QuicFramer::EncryptPacket(const QuicPacket& packet) { scoped_ptr out(encrypter_->Encrypt(packet.AssociatedData(), packet.Plaintext())); if (out.get() == NULL) { RaiseError(QUIC_ENCRYPTION_FAILURE); return NULL; } size_t len = kStartOfEncryptedData + out->length(); char* buffer = new char[len]; // TODO(rch): eliminate this buffer copy by passing in a buffer to Encrypt(). memcpy(buffer, packet.data(), kStartOfEncryptedData); memcpy(buffer + kStartOfEncryptedData, out->data(), out->length()); return new QuicEncryptedPacket(buffer, len, true); } size_t QuicFramer::GetMaxPlaintextSize(size_t ciphertext_size) { return encrypter_->GetMaxPlaintextSize(ciphertext_size); } bool QuicFramer::DecryptPayload(const QuicEncryptedPacket& packet) { StringPiece encrypted; if (!reader_->ReadStringPiece(&encrypted, reader_->BytesRemaining())) { return false; } DCHECK(decrypter_.get() != NULL); decrypted_.reset(decrypter_->Decrypt(packet.AssociatedData(), encrypted)); if (decrypted_.get() == NULL) { return false; } reader_.reset(new QuicDataReader(decrypted_->data(), decrypted_->length())); return true; } size_t QuicFramer::ComputeFramePayloadLength(const QuicFrame& frame) { size_t len = 0; // We use "magic numbers" here because sizeof(member_) is not necessarily the // same as sizeof(member_wire_format). switch (frame.type) { case STREAM_FRAME: len += 4; // stream id len += 1; // fin len += 8; // offset len += 2; // space for the 16 bit length len += frame.stream_frame->data.size(); break; case ACK_FRAME: { const QuicAckFrame& ack = *frame.ack_frame; len += 6; // largest observed packet sequence number len += 1; // num missing packets len += 6 * ack.received_info.missing_packets.size(); len += 6; // least packet sequence number awaiting an ack break; } case CONGESTION_FEEDBACK_FRAME: { const QuicCongestionFeedbackFrame& congestion_feedback = *frame.congestion_feedback_frame; len += 1; // congestion feedback type switch (congestion_feedback.type) { case kInterArrival: { const CongestionFeedbackMessageInterArrival& inter_arrival = congestion_feedback.inter_arrival; len += 2; len += 1; // num received packets if (inter_arrival.received_packet_times.size() > 0) { len += 6; // smallest received len += 8; // time // 2 bytes per sequence number delta plus 4 bytes per delta time. len += 6 * (inter_arrival.received_packet_times.size() - 1); } break; } case kFixRate: len += 4; break; case kTCP: len += 4; break; default: set_detailed_error("Illegal feedback type."); DLOG(INFO) << "Illegal feedback type: " << congestion_feedback.type; break; } break; } case RST_STREAM_FRAME: len += 4; // stream id len += 8; // offset len += 4; // error code len += 2; // error details size len += frame.rst_stream_frame->error_details.size(); break; case CONNECTION_CLOSE_FRAME: len += 4; // error code len += 2; // error details size len += frame.connection_close_frame->error_details.size(); len += ComputeFramePayloadLength( QuicFrame(&frame.connection_close_frame->ack_frame)); break; default: set_detailed_error("Illegal frame type."); DLOG(INFO) << "Illegal frame type: " << frame.type; break; } return len; } // static bool QuicFramer::AppendPacketSequenceNumber( QuicPacketSequenceNumber packet_sequence_number, QuicDataWriter* writer) { // Ensure the entire sequence number can be written. if (writer->capacity() - writer->length() < kSequenceNumberSize) { return false; } return writer->WriteUInt48(packet_sequence_number & kSequenceNumberMask); } bool QuicFramer::AppendStreamFramePayload( const QuicStreamFrame& frame, QuicDataWriter* writer) { if (!writer->WriteUInt32(frame.stream_id)) { return false; } if (!writer->WriteUInt8(frame.fin)) { return false; } if (!writer->WriteUInt64(frame.offset)) { return false; } if (!writer->WriteUInt16(frame.data.size())) { return false; } if (!writer->WriteBytes(frame.data.data(), frame.data.size())) { return false; } return true; } QuicPacketSequenceNumber QuicFramer::CalculateLargestObserved( const SequenceSet& missing_packets, SequenceSet::const_iterator largest_written) { SequenceSet::const_iterator it = largest_written; QuicPacketSequenceNumber previous_missing = *it; ++it; // See if the next thing is a gap in the missing packets: if it's a // non-missing packet we can return it. if (it != missing_packets.end() && previous_missing + 1 != *it) { return *it - 1; } // Otherwise return the largest missing packet, as indirectly observed. return *largest_written; } // TODO(ianswett): Use varints or another more compact approach for all deltas. bool QuicFramer::AppendAckFramePayload( const QuicAckFrame& frame, QuicDataWriter* writer) { if (!AppendPacketSequenceNumber(frame.sent_info.least_unacked, writer)) { return false; } size_t largest_observed_offset = writer->length(); if (!AppendPacketSequenceNumber(frame.received_info.largest_observed, writer)) { return false; } // We don't check for overflowing uint8 here, because we only can fit 192 acks // per packet, so if we overflow we will be truncated. uint8 num_missing_packets = frame.received_info.missing_packets.size(); size_t num_missing_packets_offset = writer->length(); if (!writer->WriteBytes(&num_missing_packets, 1)) { return false; } SequenceSet::const_iterator it = frame.received_info.missing_packets.begin(); int num_missing_packets_written = 0; for (; it != frame.received_info.missing_packets.end(); ++it) { if (!AppendPacketSequenceNumber(*it, writer)) { // We are truncating. Overwrite largest_observed. QuicPacketSequenceNumber largest_observed = CalculateLargestObserved(frame.received_info.missing_packets, --it); writer->WriteUInt48ToOffset(largest_observed & kSequenceNumberMask, largest_observed_offset); writer->WriteUInt8ToOffset(num_missing_packets_written, num_missing_packets_offset); return true; } ++num_missing_packets_written; DCHECK_GE(numeric_limits::max(), num_missing_packets_written); } return true; } bool QuicFramer::AppendQuicCongestionFeedbackFramePayload( const QuicCongestionFeedbackFrame& frame, QuicDataWriter* writer) { if (!writer->WriteBytes(&frame.type, 1)) { return false; } switch (frame.type) { case kInterArrival: { const CongestionFeedbackMessageInterArrival& inter_arrival = frame.inter_arrival; if (!writer->WriteUInt16( inter_arrival.accumulated_number_of_lost_packets)) { return false; } DCHECK_GE(numeric_limits::max(), inter_arrival.received_packet_times.size()); if (inter_arrival.received_packet_times.size() > numeric_limits::max()) { return false; } // TODO(ianswett): Make num_received_packets a varint. uint8 num_received_packets = inter_arrival.received_packet_times.size(); if (!writer->WriteBytes(&num_received_packets, 1)) { return false; } if (num_received_packets > 0) { TimeMap::const_iterator it = inter_arrival.received_packet_times.begin(); QuicPacketSequenceNumber lowest_sequence = it->first; if (!AppendPacketSequenceNumber(lowest_sequence, writer)) { return false; } QuicTime lowest_time = it->second; // TODO(ianswett): Use time deltas from the connection's first received // packet. if (!writer->WriteUInt64(lowest_time.ToMicroseconds())) { return false; } for (++it; it != inter_arrival.received_packet_times.end(); ++it) { QuicPacketSequenceNumber sequence_delta = it->first - lowest_sequence; DCHECK_GE(numeric_limits::max(), sequence_delta); if (sequence_delta > numeric_limits::max()) { return false; } if (!writer->WriteUInt16(static_cast(sequence_delta))) { return false; } int32 time_delta_us = it->second.Subtract(lowest_time).ToMicroseconds(); if (!writer->WriteBytes(&time_delta_us, sizeof(time_delta_us))) { return false; } } } break; } case kFixRate: { const CongestionFeedbackMessageFixRate& fix_rate = frame.fix_rate; if (!writer->WriteUInt32(fix_rate.bitrate_in_bytes_per_second)) { return false; } break; } case kTCP: { const CongestionFeedbackMessageTCP& tcp = frame.tcp; if (!writer->WriteUInt16(tcp.accumulated_number_of_lost_packets)) { return false; } if (!writer->WriteUInt16(tcp.receive_window)) { return false; } break; } default: return false; } return true; } bool QuicFramer::AppendRstStreamFramePayload( const QuicRstStreamFrame& frame, QuicDataWriter* writer) { if (!writer->WriteUInt32(frame.stream_id)) { return false; } if (!writer->WriteUInt64(frame.offset)) { return false; } uint32 error_code = static_cast(frame.error_code); if (!writer->WriteUInt32(error_code)) { return false; } if (!writer->WriteStringPiece16(frame.error_details)) { return false; } return true; } bool QuicFramer::AppendConnectionCloseFramePayload( const QuicConnectionCloseFrame& frame, QuicDataWriter* writer) { uint32 error_code = static_cast(frame.error_code); if (!writer->WriteUInt32(error_code)) { return false; } if (!writer->WriteStringPiece16(frame.error_details)) { return false; } AppendAckFramePayload(frame.ack_frame, writer); return true; } bool QuicFramer::RaiseError(QuicErrorCode error) { DLOG(INFO) << detailed_error_; set_error(error); visitor_->OnError(this); reader_.reset(NULL); return false; } } // namespace net