diff options
Diffstat (limited to 'net/quic/quic_framer.cc')
-rw-r--r-- | net/quic/quic_framer.cc | 260 |
1 files changed, 193 insertions, 67 deletions
diff --git a/net/quic/quic_framer.cc b/net/quic/quic_framer.cc index a794701..db3de8d5 100644 --- a/net/quic/quic_framer.cc +++ b/net/quic/quic_framer.cc @@ -86,8 +86,19 @@ size_t QuicFramer::GetSerializedFrameLength( return frame_len; } -QuicPacket* QuicFramer::ConstructFrameDataPacket(const QuicPacketHeader& header, - const QuicFrames& frames) { +QuicPacketEntropyHash QuicFramer::GetPacketEntropyHash( + const QuicPacketHeader& header) const { + if (!header.entropy_flag) { + // TODO(satyamshekhar): Return some more better value here (something that + // is not a constant). + return 0; + } + return 1 << (header.packet_sequence_number % 8); +} + +SerializedPacket QuicFramer::ConstructFrameDataPacket( + const QuicPacketHeader& header, + const QuicFrames& frames) { const size_t max_plaintext_size = GetMaxPlaintextSize(kMaxPacketSize); size_t packet_size = kPacketHeaderSize; for (size_t i = 0; i < frames.size(); ++i) { @@ -100,18 +111,20 @@ QuicPacket* QuicFramer::ConstructFrameDataPacket(const QuicPacketHeader& header, return ConstructFrameDataPacket(header, frames, packet_size); } -QuicPacket* QuicFramer::ConstructFrameDataPacket(const QuicPacketHeader& header, - const QuicFrames& frames, - size_t packet_size) { +SerializedPacket QuicFramer::ConstructFrameDataPacket( + const QuicPacketHeader& header, + const QuicFrames& frames, + size_t packet_size) { QuicDataWriter writer(packet_size); + SerializedPacket kNoPacket = SerializedPacket(0, NULL, 0, NULL); if (!WritePacketHeader(header, &writer)) { - return NULL; + return kNoPacket; } for (size_t i = 0; i < frames.size(); ++i) { const QuicFrame& frame = frames[i]; if (!writer.WriteUInt8(frame.type)) { - return NULL; + return kNoPacket; } switch (frame.type) { @@ -120,34 +133,39 @@ QuicPacket* QuicFramer::ConstructFrameDataPacket(const QuicPacketHeader& header, break; case STREAM_FRAME: if (!AppendStreamFramePayload(*frame.stream_frame, &writer)) { - return NULL; + return kNoPacket; } break; case ACK_FRAME: if (!AppendAckFramePayload(*frame.ack_frame, &writer)) { - return NULL; + return kNoPacket; } break; case CONGESTION_FEEDBACK_FRAME: if (!AppendQuicCongestionFeedbackFramePayload( *frame.congestion_feedback_frame, &writer)) { - return NULL; + return kNoPacket; } break; case RST_STREAM_FRAME: if (!AppendRstStreamFramePayload(*frame.rst_stream_frame, &writer)) { - return NULL; + return kNoPacket; } break; case CONNECTION_CLOSE_FRAME: if (!AppendConnectionCloseFramePayload( *frame.connection_close_frame, &writer)) { - return NULL; + return kNoPacket; + } + break; + case GOAWAY_FRAME: + if (!AppendGoAwayFramePayload(*frame.goaway_frame, &writer)) { + return kNoPacket; } break; default: RaiseError(QUIC_INVALID_FRAME_DATA); - return NULL; + return kNoPacket; } } @@ -163,32 +181,35 @@ QuicPacket* QuicFramer::ConstructFrameDataPacket(const QuicPacketHeader& header, packet->FecProtectedData()); } - return packet; + return SerializedPacket(header.packet_sequence_number, packet, + GetPacketEntropyHash(header), NULL); } -QuicPacket* QuicFramer::ConstructFecPacket(const QuicPacketHeader& header, - const QuicFecData& fec) { +SerializedPacket QuicFramer::ConstructFecPacket(const QuicPacketHeader& header, + const QuicFecData& fec) { size_t len = kPacketHeaderSize; len += fec.redundancy.length(); QuicDataWriter writer(len); - + SerializedPacket kNoPacket = SerializedPacket(0, NULL, 0, NULL); if (!WritePacketHeader(header, &writer)) { - return NULL; + return kNoPacket; } if (!writer.WriteBytes(fec.redundancy.data(), fec.redundancy.length())) { - return NULL; + return kNoPacket; } - return QuicPacket::NewFecPacket(writer.take(), len, true); + return SerializedPacket(header.packet_sequence_number, + QuicPacket::NewFecPacket(writer.take(), len, true), + GetPacketEntropyHash(header), NULL); } // static QuicEncryptedPacket* QuicFramer::ConstructPublicResetPacket( const QuicPublicResetPacket& packet) { - DCHECK_EQ(PACKET_PUBLIC_FLAGS_RST, - PACKET_PUBLIC_FLAGS_RST & packet.public_header.flags); + DCHECK(packet.public_header.reset_flag); + DCHECK(!packet.public_header.version_flag); size_t len = kPublicResetPacketSize; QuicDataWriter writer(len); @@ -196,7 +217,7 @@ QuicEncryptedPacket* QuicFramer::ConstructPublicResetPacket( return NULL; } - uint8 flags = static_cast<uint8>(packet.public_header.flags); + uint8 flags = static_cast<uint8>(PACKET_PUBLIC_FLAGS_RST); if (!writer.WriteUInt8(flags)) { return NULL; } @@ -226,7 +247,7 @@ bool QuicFramer::ProcessPacket(const QuicEncryptedPacket& packet) { } bool rv; - if (public_header.flags & PACKET_PUBLIC_FLAGS_RST) { + if (public_header.reset_flag) { rv = ProcessPublicResetPacket(public_header); } else { rv = ProcessDataPacket(public_header, packet); @@ -257,7 +278,7 @@ bool QuicFramer::ProcessDataPacket( } // Handle the payload. - if ((header.private_flags & PACKET_PRIVATE_FLAGS_FEC) == 0) { + if (!header.fec_flag) { if (header.fec_group != 0) { StringPiece payload = reader_->PeekRemainingPayload(); visitor_->OnFecProtectedPayload(payload); @@ -295,13 +316,16 @@ bool QuicFramer::ProcessPublicResetPacket( return true; } -bool QuicFramer::ProcessRevivedPacket(const QuicPacketHeader& header, +bool QuicFramer::ProcessRevivedPacket(QuicPacketHeader* header, StringPiece payload) { DCHECK(!reader_.get()); visitor_->OnRevivedPacket(); - visitor_->OnPacketHeader(header); + header->entropy_hash = GetPacketEntropyHash(*header); + + // TODO(satyamshekhar): Don't process if the visitor refuses the header. + visitor_->OnPacketHeader(*header); if (payload.length() > kMaxPacketSize) { set_detailed_error("Revived packet too large."); @@ -326,7 +350,13 @@ bool QuicFramer::WritePacketHeader(const QuicPacketHeader& header, return false; } - uint8 flags = static_cast<uint8>(header.public_header.flags); + uint8 flags = 0; + if (header.public_header.reset_flag) { + flags |= PACKET_PUBLIC_FLAGS_RST; + } + if (header.public_header.version_flag) { + flags |= PACKET_PUBLIC_FLAGS_VERSION; + } if (!writer->WriteUInt8(flags)) { return false; } @@ -335,7 +365,16 @@ bool QuicFramer::WritePacketHeader(const QuicPacketHeader& header, return false; } - flags = static_cast<uint8>(header.private_flags); + flags = 0; + if (header.fec_flag) { + flags |= PACKET_PRIVATE_FLAGS_FEC; + } + if (header.entropy_flag) { + flags |= PACKET_PRIVATE_FLAGS_ENTROPY; + } + if (header.fec_entropy_flag) { + flags |= PACKET_PRIVATE_FLAGS_FEC_ENTROPY; + } if (!writer->WriteUInt8(flags)) { return false; } @@ -361,7 +400,7 @@ bool QuicFramer::WritePacketHeader(const QuicPacketHeader& header, QuicPacketSequenceNumber QuicFramer::CalculatePacketSequenceNumberFromWire( QuicPacketSequenceNumber packet_sequence_number) const { - // The new sequence number might have wrapped to the next epoc, or + // The new sequence number might have wrapped to the next epoch, 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. @@ -393,7 +432,10 @@ bool QuicFramer::ProcessPublicHeader(QuicPacketPublicHeader* public_header) { return false; } - public_header->flags = static_cast<QuicPacketPublicFlags>(public_flags); + public_header->reset_flag = (public_flags & PACKET_PUBLIC_FLAGS_RST) != 0; + public_header->version_flag = + (public_flags & PACKET_PUBLIC_FLAGS_VERSION) != 0; + return true; } @@ -417,7 +459,7 @@ bool QuicFramer::ProcessPacketHeader( return false; } - if (!DecryptPayload(packet)) { + if (!DecryptPayload(header->packet_sequence_number, packet)) { DLOG(WARNING) << "Unable to decrypt payload."; return RaiseError(QUIC_DECRYPTION_FAILURE); } @@ -433,7 +475,10 @@ bool QuicFramer::ProcessPacketHeader( return false; } - header->private_flags = static_cast<QuicPacketPrivateFlags>(private_flags); + header->fec_flag = (private_flags & PACKET_PRIVATE_FLAGS_FEC) != 0; + header->entropy_flag = (private_flags & PACKET_PRIVATE_FLAGS_ENTROPY) != 0; + header->fec_entropy_flag = + (private_flags & PACKET_PRIVATE_FLAGS_FEC_ENTROPY) != 0; uint8 first_fec_protected_packet_offset; if (!reader_->ReadBytes(&first_fec_protected_packet_offset, 1)) { @@ -443,6 +488,7 @@ bool QuicFramer::ProcessPacketHeader( header->fec_group = first_fec_protected_packet_offset == kNoFecOffset ? 0 : header->packet_sequence_number - first_fec_protected_packet_offset; + header->entropy_hash = GetPacketEntropyHash(*header); // 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; @@ -505,6 +551,11 @@ bool QuicFramer::ProcessFrameData() { return RaiseError(QUIC_INVALID_CONNECTION_CLOSE_DATA); } break; + case GOAWAY_FRAME: + if (!ProcessGoAwayFrame()) { + return RaiseError(QUIC_INVALID_GOAWAY_DATA); + } + break; default: set_detailed_error("Illegal frame type."); DLOG(WARNING) << "Illegal frame type: " @@ -560,6 +611,11 @@ bool QuicFramer::ProcessAckFrame(QuicAckFrame* frame) { } bool QuicFramer::ProcessReceivedInfo(ReceivedPacketInfo* received_info) { + if (!reader_->ReadBytes(&received_info->entropy_hash, 1)) { + set_detailed_error("Unable to read entropy hash for received packets."); + return false; + } + if (!ProcessPacketSequenceNumber(&received_info->largest_observed)) { set_detailed_error("Unable to read largest observed."); return false; @@ -584,6 +640,11 @@ bool QuicFramer::ProcessReceivedInfo(ReceivedPacketInfo* received_info) { } bool QuicFramer::ProcessSentInfo(SentPacketInfo* sent_info) { + if (!reader_->ReadBytes(&sent_info->entropy_hash, 1)) { + set_detailed_error("Unable to read entropy hash for sent packets."); + return false; + } + if (!ProcessPacketSequenceNumber(&sent_info->least_unacked)) { set_detailed_error("Unable to read least unacked."); return false; @@ -700,11 +761,6 @@ bool QuicFramer::ProcessRstStreamFrame() { 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."); @@ -749,8 +805,39 @@ bool QuicFramer::ProcessConnectionCloseFrame() { return true; } -QuicEncryptedPacket* QuicFramer::EncryptPacket(const QuicPacket& packet) { - scoped_ptr<QuicData> out(encrypter_->Encrypt(packet.AssociatedData(), +bool QuicFramer::ProcessGoAwayFrame() { + QuicGoAwayFrame frame; + + uint32 error_code; + if (!reader_->ReadUInt32(&error_code)) { + set_detailed_error("Unable to read go away error code."); + return false; + } + frame.error_code = static_cast<QuicErrorCode>(error_code); + + uint32 stream_id; + if (!reader_->ReadUInt32(&stream_id)) { + set_detailed_error("Unable to read last good stream id."); + return false; + } + frame.last_good_stream_id = static_cast<QuicErrorCode>(stream_id); + + StringPiece reason_phrase; + if (!reader_->ReadStringPiece16(&reason_phrase)) { + set_detailed_error("Unable to read goaway reason."); + return false; + } + frame.reason_phrase = reason_phrase.as_string(); + + visitor_->OnGoAwayFrame(frame); + return true; +} + +QuicEncryptedPacket* QuicFramer::EncryptPacket( + QuicPacketSequenceNumber packet_sequence_number, + const QuicPacket& packet) { + scoped_ptr<QuicData> out(encrypter_->Encrypt(packet_sequence_number, + packet.AssociatedData(), packet.Plaintext())); if (out.get() == NULL) { RaiseError(QUIC_ENCRYPTION_FAILURE); @@ -768,13 +855,15 @@ size_t QuicFramer::GetMaxPlaintextSize(size_t ciphertext_size) { return encrypter_->GetMaxPlaintextSize(ciphertext_size); } -bool QuicFramer::DecryptPayload(const QuicEncryptedPacket& packet) { +bool QuicFramer::DecryptPayload(QuicPacketSequenceNumber sequence_number, + const QuicEncryptedPacket& packet) { StringPiece encrypted; if (!reader_->ReadStringPiece(&encrypted, reader_->BytesRemaining())) { return false; } DCHECK(decrypter_.get() != NULL); - decrypted_.reset(decrypter_->Decrypt(packet.AssociatedData(), encrypted)); + decrypted_.reset(decrypter_->Decrypt(sequence_number, + packet.AssociatedData(), encrypted)); if (decrypted_.get() == NULL) { return false; } @@ -789,34 +878,36 @@ size_t QuicFramer::ComputeFramePayloadLength(const QuicFrame& frame) { // 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 += 4; // Stream id of the frame. + len += 1; // A byte for fin. + len += 8; // Byte 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 += 1; // Commutative hash of entropy of the packets received. + len += 6; // Least packet sequence number awaiting an ack. + len += 1; // Hash of entropy of the packets sent up to largest observed. + len += 6; // Largest observed packet sequence number. + len += 1; // Number of 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 + 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 + len += 1; // Number received packets. if (inter_arrival.received_packet_times.size() > 0) { - len += 6; // smallest received - len += 8; // time + 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); } @@ -836,19 +927,24 @@ size_t QuicFramer::ComputeFramePayloadLength(const QuicFrame& frame) { break; } case RST_STREAM_FRAME: - len += 4; // stream id - len += 8; // offset - len += 4; // error code - len += 2; // error details size + len += 4; // Stream id of the frame. + 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 += 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; + case GOAWAY_FRAME: + len += 4; // error code + len += 4; // last good stream id + len += 2; // reason phrase length + len += frame.goaway_frame->reason_phrase.size(); + break; default: set_detailed_error("Illegal frame type."); DLOG(INFO) << "Illegal frame type: " << frame.type; @@ -891,9 +987,9 @@ bool QuicFramer::AppendStreamFramePayload( } QuicPacketSequenceNumber QuicFramer::CalculateLargestObserved( - const SequenceSet& missing_packets, - SequenceSet::const_iterator largest_written) { - SequenceSet::const_iterator it = largest_written; + const SequenceNumberSet& missing_packets, + SequenceNumberSet::const_iterator largest_written) { + SequenceNumberSet::const_iterator it = largest_written; QuicPacketSequenceNumber previous_missing = *it; ++it; @@ -911,10 +1007,21 @@ QuicPacketSequenceNumber QuicFramer::CalculateLargestObserved( bool QuicFramer::AppendAckFramePayload( const QuicAckFrame& frame, QuicDataWriter* writer) { + // TODO(satyamshekhar): Decide how often we really should send this + // entropy_hash update. + if (!writer->WriteUInt8(frame.sent_info.entropy_hash)) { + return false; + } + if (!AppendPacketSequenceNumber(frame.sent_info.least_unacked, writer)) { return false; } + size_t received_entropy_offset = writer->length(); + if (!writer->WriteUInt8(frame.received_info.entropy_hash)) { + return false; + } + size_t largest_observed_offset = writer->length(); if (!AppendPacketSequenceNumber(frame.received_info.largest_observed, writer)) { @@ -929,13 +1036,19 @@ bool QuicFramer::AppendAckFramePayload( return false; } - SequenceSet::const_iterator it = frame.received_info.missing_packets.begin(); + SequenceNumberSet::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. + // We are truncating. QuicPacketSequenceNumber largest_observed = CalculateLargestObserved(frame.received_info.missing_packets, --it); + // Overwrite entropy hash for received packets. + writer->WriteUInt8ToOffset( + entropy_calculator_->ReceivedEntropyHash(largest_observed), + received_entropy_offset); + // Overwrite largest_observed. writer->WriteUInt48ToOffset(largest_observed & kSequenceNumberMask, largest_observed_offset); writer->WriteUInt8ToOffset(num_missing_packets_written, @@ -1045,9 +1158,6 @@ bool QuicFramer::AppendRstStreamFramePayload( if (!writer->WriteUInt32(frame.stream_id)) { return false; } - if (!writer->WriteUInt64(frame.offset)) { - return false; - } uint32 error_code = static_cast<uint32>(frame.error_code); if (!writer->WriteUInt32(error_code)) { @@ -1074,6 +1184,22 @@ bool QuicFramer::AppendConnectionCloseFramePayload( return true; } +bool QuicFramer::AppendGoAwayFramePayload(const QuicGoAwayFrame& frame, + QuicDataWriter* writer) { + uint32 error_code = static_cast<uint32>(frame.error_code); + if (!writer->WriteUInt32(error_code)) { + return false; + } + uint32 stream_id = static_cast<uint32>(frame.last_good_stream_id); + if (!writer->WriteUInt32(stream_id)) { + return false; + } + if (!writer->WriteStringPiece16(frame.reason_phrase)) { + return false; + } + return true; +} + bool QuicFramer::RaiseError(QuicErrorCode error) { DLOG(INFO) << detailed_error_; set_error(error); |