| Index: net/quic/quic_framer.cc
|
| diff --git a/net/quic/quic_framer.cc b/net/quic/quic_framer.cc
|
| index 2329605dcc181e8c47f73b302f9c9a32f9665e44..462172cbac4f36df3896e9ead530530e75b330a3 100644
|
| --- a/net/quic/quic_framer.cc
|
| +++ b/net/quic/quic_framer.cc
|
| @@ -45,15 +45,17 @@ QuicPacketSequenceNumber ClosestTo(QuicPacketSequenceNumber target,
|
|
|
| QuicFramer::QuicFramer(QuicVersionTag version,
|
| QuicDecrypter* decrypter,
|
| - QuicEncrypter* encrypter)
|
| + QuicEncrypter* encrypter,
|
| + bool is_server)
|
| : visitor_(NULL),
|
| fec_builder_(NULL),
|
| error_(QUIC_NO_ERROR),
|
| last_sequence_number_(0),
|
| quic_version_(version),
|
| decrypter_(decrypter),
|
| - encrypter_(encrypter) {
|
| - DCHECK_EQ(kQuicVersion1, version);
|
| + encrypter_(encrypter),
|
| + is_server_(is_server) {
|
| + DCHECK(IsSupportedVersion(version));
|
| }
|
|
|
| QuicFramer::~QuicFramer() {}
|
| @@ -96,6 +98,15 @@ size_t QuicFramer::GetMinGoAwayFrameSize() {
|
| kQuicStreamIdSize;
|
| }
|
|
|
| +bool QuicFramer::IsSupportedVersion(QuicVersionTag version) {
|
| + return version == kQuicVersion1;
|
| +}
|
| +
|
| +size_t QuicFramer::GetVersionNegotiationPacketSize(size_t number_versions) {
|
| + return kQuicGuidSize + kPublicFlagsSize +
|
| + number_versions * kQuicVersionSize;
|
| +}
|
| +
|
| size_t QuicFramer::GetSerializedFrameLength(
|
| const QuicFrame& frame, size_t free_bytes, bool first_frame) {
|
| if (frame.type == PADDING_FRAME) {
|
| @@ -245,7 +256,6 @@ SerializedPacket QuicFramer::ConstructFecPacket(const QuicPacketHeader& header,
|
| QuicEncryptedPacket* QuicFramer::ConstructPublicResetPacket(
|
| const QuicPublicResetPacket& packet) {
|
| DCHECK(packet.public_header.reset_flag);
|
| - DCHECK(!packet.public_header.version_flag);
|
| size_t len = GetPublicResetPacketSize();
|
| QuicDataWriter writer(len);
|
|
|
| @@ -270,23 +280,56 @@ QuicEncryptedPacket* QuicFramer::ConstructPublicResetPacket(
|
| return new QuicEncryptedPacket(writer.take(), len, true);
|
| }
|
|
|
| +QuicEncryptedPacket* QuicFramer::ConstructVersionNegotiationPacket(
|
| + const QuicPacketPublicHeader& header,
|
| + const QuicVersionTagList& supported_versions) {
|
| + DCHECK(header.version_flag);
|
| + size_t len = GetVersionNegotiationPacketSize(supported_versions.size());
|
| + QuicDataWriter writer(len);
|
| +
|
| + if (!writer.WriteUInt64(header.guid)) {
|
| + return NULL;
|
| + }
|
| +
|
| + uint8 flags = static_cast<uint8>(PACKET_PUBLIC_FLAGS_VERSION);
|
| + if (!writer.WriteUInt8(flags)) {
|
| + return NULL;
|
| + }
|
| +
|
| + for (size_t i = 0; i < supported_versions.size(); ++i) {
|
| + if (!writer.WriteUInt32(supported_versions[i])) {
|
| + return NULL;
|
| + }
|
| + }
|
| +
|
| + return new QuicEncryptedPacket(writer.take(), len, true);
|
| +}
|
| +
|
| bool QuicFramer::ProcessPacket(const QuicEncryptedPacket& packet) {
|
| DCHECK(!reader_.get());
|
| reader_.reset(new QuicDataReader(packet.data(), packet.length()));
|
|
|
| + visitor_->OnPacket();
|
| +
|
| // First parse the public header.
|
| QuicPacketPublicHeader public_header;
|
| if (!ProcessPublicHeader(&public_header)) {
|
| DLOG(WARNING) << "Unable to process public header.";
|
| return RaiseError(QUIC_INVALID_PACKET_HEADER);
|
| }
|
| - // TODO(satyamshekhar): Handle version negotiation.
|
| - if (public_header.version_flag && public_header.version != quic_version_) {
|
| - return false;
|
| +
|
| + if (is_server_ && public_header.version_flag &&
|
| + public_header.versions[0] != quic_version_) {
|
| + if (!visitor_->OnProtocolVersionMismatch(public_header.versions[0])) {
|
| + reader_.reset(NULL);
|
| + return true;
|
| + }
|
| }
|
|
|
| bool rv;
|
| - if (public_header.reset_flag) {
|
| + if (!is_server_ && public_header.version_flag) {
|
| + rv = ProcessVersionNegotiationPacket(&public_header);
|
| + } else if (public_header.reset_flag) {
|
| rv = ProcessPublicResetPacket(public_header);
|
| } else {
|
| rv = ProcessDataPacket(public_header, packet);
|
| @@ -296,11 +339,26 @@ bool QuicFramer::ProcessPacket(const QuicEncryptedPacket& packet) {
|
| return rv;
|
| }
|
|
|
| +bool QuicFramer::ProcessVersionNegotiationPacket(
|
| + QuicPacketPublicHeader* public_header) {
|
| + DCHECK(!is_server_);
|
| + // Try reading at least once to raise error if the packet is invalid.
|
| + do {
|
| + QuicVersionTag version;
|
| + if (!reader_->ReadBytes(&version, kQuicVersionSize)) {
|
| + set_detailed_error("Unable to read supported version in negotiation.");
|
| + return RaiseError(QUIC_INVALID_VERSION_NEGOTIATION_PACKET);
|
| + }
|
| + public_header->versions.push_back(version);
|
| + } while (!reader_->IsDoneReading());
|
| +
|
| + visitor_->OnVersionNegotiationPacket(*public_header);
|
| + return true;
|
| +}
|
| +
|
| bool QuicFramer::ProcessDataPacket(
|
| const QuicPacketPublicHeader& public_header,
|
| const QuicEncryptedPacket& packet) {
|
| - visitor_->OnPacket();
|
| -
|
| QuicPacketHeader header(public_header);
|
| if (!ProcessPacketHeader(&header, packet)) {
|
| DCHECK_NE(QUIC_NO_ERROR, error_); // ProcessPacketHeader sets the error.
|
| @@ -344,6 +402,7 @@ bool QuicFramer::ProcessPublicResetPacket(
|
| const QuicPacketPublicHeader& public_header) {
|
| QuicPublicResetPacket packet(public_header);
|
| if (!reader_->ReadUInt64(&packet.nonce_proof)) {
|
| + // TODO(satyamshekhar): Raise error.
|
| set_detailed_error("Unable to read nonce proof.");
|
| return false;
|
| }
|
| @@ -403,6 +462,7 @@ bool QuicFramer::WritePacketHeader(const QuicPacketHeader& header,
|
| }
|
|
|
| if (header.public_header.version_flag) {
|
| + DCHECK(!is_server_);
|
| writer->WriteUInt32(quic_version_);
|
| }
|
|
|
| @@ -481,12 +541,21 @@ bool QuicFramer::ProcessPublicHeader(QuicPacketPublicHeader* public_header) {
|
| public_header->version_flag =
|
| (public_flags & PACKET_PUBLIC_FLAGS_VERSION) != 0;
|
|
|
| - if (public_header->version_flag &&
|
| - !reader_->ReadUInt32(&public_header->version)) {
|
| - set_detailed_error("Unable to read protocol version.");
|
| + if (public_header->reset_flag && public_header->version_flag) {
|
| + set_detailed_error("Got version flag in reset packet");
|
| return false;
|
| }
|
|
|
| + if (public_header->version_flag && is_server_) {
|
| + QuicVersionTag version;
|
| + if (!reader_->ReadUInt32(&version)) {
|
| + // Read the version only if the packet is from the client.
|
| + // version flag from the server means version negotiation packet.
|
| + set_detailed_error("Unable to read protocol version.");
|
| + return false;
|
| + }
|
| + public_header->versions.push_back(version);
|
| + }
|
| return true;
|
| }
|
|
|
| @@ -673,6 +742,7 @@ bool QuicFramer::ProcessReceivedInfo(ReceivedPacketInfo* received_info) {
|
| set_detailed_error("Unable to read largest observed.");
|
| return false;
|
| }
|
| + // TODO(pwestin): read and update delta_time_largest_observed.
|
|
|
| uint8 num_missing_packets;
|
| if (!reader_->ReadBytes(&num_missing_packets, 1)) {
|
| @@ -889,8 +959,8 @@ bool QuicFramer::ProcessGoAwayFrame() {
|
| StringPiece QuicFramer::GetAssociatedDataFromEncryptedPacket(
|
| const QuicEncryptedPacket& encrypted, bool includes_version) {
|
| return StringPiece(encrypted.data() + kStartOfHashData,
|
| - GetStartOfEncryptedData(includes_version)
|
| - - kStartOfHashData);
|
| + GetStartOfEncryptedData(includes_version) -
|
| + kStartOfHashData);
|
| }
|
|
|
| QuicEncryptedPacket* QuicFramer::EncryptPacket(
|
| @@ -1076,6 +1146,8 @@ bool QuicFramer::AppendAckFramePayload(
|
| writer)) {
|
| return false;
|
| }
|
| + // TODO(pwestin): calculate and add delta_time_largest_observed to the
|
| + // message.
|
|
|
| // 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.
|
|
|