#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_flags.h"
#include "net/quic/quic_socket_address_coder.h"
using base::StringPiece;
using std::numeric_limits;
using std::string;
-bool FLAGS_quic_allow_oversized_packets_for_test = false;
-
namespace net {
namespace {
last_sequence_number_(0),
last_serialized_connection_id_(0),
supported_versions_(supported_versions),
+ decrypter_level_(ENCRYPTION_NONE),
+ alternative_decrypter_level_(ENCRYPTION_NONE),
alternative_decrypter_latch_(false),
is_server_(is_server),
+ validate_flags_(true),
creation_time_(creation_time) {
DCHECK(!supported_versions.empty());
quic_version_ = supported_versions_[0];
size_t QuicFramer::GetMinStreamFrameSize(QuicVersion version,
QuicStreamId stream_id,
QuicStreamOffset offset,
- bool last_frame_in_packet) {
+ bool last_frame_in_packet,
+ InFecGroup is_in_fec_group) {
+ bool no_stream_frame_length = last_frame_in_packet &&
+ is_in_fec_group == NOT_IN_FEC_GROUP;
return kQuicFrameTypeSize + GetStreamIdSize(stream_id) +
GetStreamOffsetSize(offset) +
- (last_frame_in_packet ? 0 : kQuicStreamPayloadLengthSize);
+ (no_stream_frame_length ? 0 : kQuicStreamPayloadLengthSize);
}
// static
// static
size_t QuicFramer::GetMinRstStreamFrameSize(QuicVersion quic_version) {
- if (quic_version > QUIC_VERSION_13) {
- return kQuicFrameTypeSize + kQuicMaxStreamIdSize +
- kQuicMaxStreamOffsetSize + kQuicErrorCodeSize +
- kQuicErrorDetailsLengthSize;
- } else {
- return kQuicFrameTypeSize + kQuicMaxStreamIdSize + kQuicErrorCodeSize +
- kQuicErrorDetailsLengthSize;
- }
+ return kQuicFrameTypeSize + kQuicMaxStreamIdSize +
+ kQuicMaxStreamOffsetSize + kQuicErrorCodeSize +
+ kQuicErrorDetailsLengthSize;
}
// static
size_t free_bytes,
bool first_frame,
bool last_frame,
+ InFecGroup is_in_fec_group,
QuicSequenceNumberLength sequence_number_length) {
if (frame.type == PADDING_FRAME) {
// PADDING implies end of packet.
return free_bytes;
}
size_t frame_len =
- ComputeFrameLength(frame, last_frame, sequence_number_length);
+ ComputeFrameLength(frame, last_frame, is_in_fec_group,
+ sequence_number_length);
if (frame_len > free_bytes) {
// Only truncate the first frame in a packet, so if subsequent ones go
// over, stop including more frames.
bool last_frame = i == frames.size() - 1;
const size_t frame_size = GetSerializedFrameLength(
frames[i], max_plaintext_size - packet_size, first_frame, last_frame,
+ header.is_in_fec_group,
header.public_header.sequence_number_length);
DCHECK(frame_size);
packet_size += frame_size;
for (size_t i = 0; i < frames.size(); ++i) {
const QuicFrame& frame = frames[i];
- const bool last_frame_in_packet = i == (frames.size() - 1);
- if (!AppendTypeByte(frame, last_frame_in_packet, &writer)) {
+ // Determine if we should write stream frame length in header.
+ const bool no_stream_frame_length =
+ (header.is_in_fec_group == NOT_IN_FEC_GROUP) &&
+ (i == frames.size() - 1);
+ if (!AppendTypeByte(frame, no_stream_frame_length, &writer)) {
LOG(DFATAL) << "AppendTypeByte failed";
return kNoPacket;
}
break;
case STREAM_FRAME:
if (!AppendStreamFrame(
- *frame.stream_frame, last_frame_in_packet, &writer)) {
+ *frame.stream_frame, no_stream_frame_length, &writer)) {
LOG(DFATAL) << "AppendStreamFrame failed";
return kNoPacket;
}
return kNoPacket;
}
break;
+ case PING_FRAME:
+ if (quic_version_ <= QUIC_VERSION_17) {
+ LOG(DFATAL) << "Attempt to add a PingFrame in "
+ << QuicVersionToString(quic_version_);
+ return kNoPacket;
+ }
+ // Ping has no payload.
+ break;
case RST_STREAM_FRAME:
if (!AppendRstStreamFrame(*frame.rst_stream_frame, &writer)) {
LOG(DFATAL) << "AppendRstStreamFrame failed";
}
break;
case WINDOW_UPDATE_FRAME:
- if (quic_version_ > QUIC_VERSION_13) {
- if (!AppendWindowUpdateFrame(*frame.window_update_frame, &writer)) {
- LOG(DFATAL) << "AppendWindowUpdateFrame failed";
- return kNoPacket;
- }
- } else {
- LOG(DFATAL) << "Attempt to add a WindowUpdateFrame in "
- << QuicVersionToString(quic_version_);
+ if (!AppendWindowUpdateFrame(*frame.window_update_frame, &writer)) {
+ LOG(DFATAL) << "AppendWindowUpdateFrame failed";
return kNoPacket;
}
break;
case BLOCKED_FRAME:
- if (quic_version_ > QUIC_VERSION_13) {
- if (!AppendBlockedFrame(*frame.blocked_frame, &writer)) {
- LOG(DFATAL) << "AppendBlockedFrame failed";
- return kNoPacket;
- }
- } else {
- LOG(DFATAL) << "Attempt to add a BlockedFrame in "
- << QuicVersionToString(quic_version_);
+ if (!AppendBlockedFrame(*frame.blocked_frame, &writer)) {
+ LOG(DFATAL) << "AppendBlockedFrame failed";
return kNoPacket;
}
break;
const QuicPacketPublicHeader& public_header) {
QuicPublicResetPacket packet(public_header);
- if (public_header.sequence_number_length == PACKET_6BYTE_SEQUENCE_NUMBER) {
- // An old-style public reset packet has the
- // PACKET_PUBLIC_FLAGS_6BYTE_SEQUENCE bits set in the public flags.
- // TODO(wtc): remove this when we drop support for QUIC_VERSION_13.
- if (!reader_->ReadUInt64(&packet.nonce_proof)) {
- set_detailed_error("Unable to read nonce proof.");
- return RaiseError(QUIC_INVALID_PUBLIC_RST_PACKET);
- }
-
- if (!reader_->ReadUInt48(&packet.rejected_sequence_number)) {
- set_detailed_error("Unable to read rejected sequence number.");
- return RaiseError(QUIC_INVALID_PUBLIC_RST_PACKET);
- }
-
- visitor_->OnPublicResetPacket(packet);
- return true;
- }
-
scoped_ptr<CryptoHandshakeMessage> reset(
CryptoFramer::ParseMessage(reader_->ReadRemainingPayload()));
if (!reset.get()) {
public_header->version_flag =
(public_flags & PACKET_PUBLIC_FLAGS_VERSION) != 0;
- if (!public_header->version_flag && public_flags > PACKET_PUBLIC_FLAGS_MAX) {
+ if (validate_flags_ &&
+ !public_header->version_flag && public_flags > PACKET_PUBLIC_FLAGS_MAX) {
set_detailed_error("Illegal public flags value.");
return false;
}
}
case WINDOW_UPDATE_FRAME: {
- if (quic_version_ > QUIC_VERSION_13) {
- QuicWindowUpdateFrame window_update_frame;
- if (!ProcessWindowUpdateFrame(&window_update_frame)) {
- return RaiseError(QUIC_INVALID_WINDOW_UPDATE_DATA);
- }
- if (!visitor_->OnWindowUpdateFrame(window_update_frame)) {
- DVLOG(1) << "Visitor asked to stop further processing.";
- // Returning true since there was no parsing error.
- return true;
- }
- } else {
- LOG(DFATAL) << "Trying to read a WindowUpdateFrame in "
- << QuicVersionToString(quic_version_);
- return RaiseError(QUIC_INTERNAL_ERROR);
+ QuicWindowUpdateFrame window_update_frame;
+ if (!ProcessWindowUpdateFrame(&window_update_frame)) {
+ return RaiseError(QUIC_INVALID_WINDOW_UPDATE_DATA);
+ }
+ if (!visitor_->OnWindowUpdateFrame(window_update_frame)) {
+ DVLOG(1) << "Visitor asked to stop further processing.";
+ // Returning true since there was no parsing error.
+ return true;
}
continue;
}
case BLOCKED_FRAME: {
- if (quic_version_ > QUIC_VERSION_13) {
- QuicBlockedFrame blocked_frame;
- if (!ProcessBlockedFrame(&blocked_frame)) {
- return RaiseError(QUIC_INVALID_BLOCKED_DATA);
- }
- if (!visitor_->OnBlockedFrame(blocked_frame)) {
- DVLOG(1) << "Visitor asked to stop further processing.";
- // Returning true since there was no parsing error.
- return true;
- }
- } else {
- LOG(DFATAL) << "Trying to read a BlockedFrame in "
- << QuicVersionToString(quic_version_);
- return RaiseError(QUIC_INTERNAL_ERROR);
+ QuicBlockedFrame blocked_frame;
+ if (!ProcessBlockedFrame(&blocked_frame)) {
+ return RaiseError(QUIC_INVALID_BLOCKED_DATA);
+ }
+ if (!visitor_->OnBlockedFrame(blocked_frame)) {
+ DVLOG(1) << "Visitor asked to stop further processing.";
+ // Returning true since there was no parsing error.
+ return true;
}
continue;
}
}
continue;
}
+ case PING_FRAME: {
+ if (quic_version_ <= QUIC_VERSION_17) {
+ LOG(DFATAL) << "Trying to read a Ping in "
+ << QuicVersionToString(quic_version_);
+ return RaiseError(QUIC_INTERNAL_ERROR);
+ }
+ // Ping has no payload.
+ QuicPingFrame ping_frame;
+ if (!visitor_->OnPingFrame(ping_frame)) {
+ DVLOG(1) << "Visitor asked to stop further processing.";
+ // Returning true since there was no parsing error.
+ return true;
+ }
+ continue;
+ }
default:
set_detailed_error("Illegal frame type.");
last_sequence_number -= (range_length + 1);
}
- if (quic_version_ != QUIC_VERSION_13) {
- // Parse the revived packets list.
- uint8 num_revived_packets;
- if (!reader_->ReadBytes(&num_revived_packets, 1)) {
- set_detailed_error("Unable to read num revived packets.");
+ // Parse the revived packets list.
+ uint8 num_revived_packets;
+ if (!reader_->ReadBytes(&num_revived_packets, 1)) {
+ set_detailed_error("Unable to read num revived packets.");
+ return false;
+ }
+
+ for (size_t i = 0; i < num_revived_packets; ++i) {
+ QuicPacketSequenceNumber revived_packet = 0;
+ if (!reader_->ReadBytes(&revived_packet,
+ largest_observed_sequence_number_length)) {
+ set_detailed_error("Unable to read revived packet.");
return false;
}
- for (size_t i = 0; i < num_revived_packets; ++i) {
- QuicPacketSequenceNumber revived_packet = 0;
- if (!reader_->ReadBytes(&revived_packet,
- largest_observed_sequence_number_length)) {
- set_detailed_error("Unable to read revived packet.");
- return false;
- }
-
- received_info->revived_packets.insert(revived_packet);
- }
+ received_info->revived_packets.insert(revived_packet);
}
return true;
case kInterArrival: {
CongestionFeedbackMessageInterArrival* inter_arrival =
&frame->inter_arrival;
- if (quic_version_ == QUIC_VERSION_13) {
- uint16 unused_accumulated_number_of_lost_packets;
- if (!reader_->ReadUInt16(
- &unused_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.");
}
case kTCP: {
CongestionFeedbackMessageTCP* tcp = &frame->tcp;
- if (quic_version_ == QUIC_VERSION_13) {
- uint16 unused_accumulated_number_of_lost_packets;
- if (!reader_->ReadUInt16(&unused_accumulated_number_of_lost_packets)) {
- set_detailed_error(
- "Unable to read accumulated number of lost packets.");
- return false;
- }
- }
// TODO(ianswett): Remove receive window, since it's constant.
uint16 receive_window = 0;
if (!reader_->ReadUInt16(&receive_window)) {
return false;
}
- if (quic_version_ > QUIC_VERSION_13) {
- if (!reader_->ReadUInt64(&frame->byte_offset)) {
- set_detailed_error("Unable to read rst stream sent byte offset.");
- return false;
- }
+ if (!reader_->ReadUInt64(&frame->byte_offset)) {
+ set_detailed_error("Unable to read rst stream sent byte offset.");
+ return false;
}
uint32 error_code;
- kStartOfHashData);
}
-void QuicFramer::SetDecrypter(QuicDecrypter* decrypter) {
+void QuicFramer::SetDecrypter(QuicDecrypter* decrypter,
+ EncryptionLevel level) {
DCHECK(alternative_decrypter_.get() == NULL);
+ DCHECK_GE(level, decrypter_level_);
decrypter_.reset(decrypter);
+ decrypter_level_ = level;
}
void QuicFramer::SetAlternativeDecrypter(QuicDecrypter* decrypter,
+ EncryptionLevel level,
bool latch_once_used) {
alternative_decrypter_.reset(decrypter);
+ alternative_decrypter_level_ = level;
alternative_decrypter_latch_ = latch_once_used;
}
return encrypter_[level].get();
}
-void QuicFramer::SwapCryptersForTest(QuicFramer* other) {
- for (int i = ENCRYPTION_NONE; i < NUM_ENCRYPTION_LEVELS; i++) {
- encrypter_[i].swap(other->encrypter_[i]);
- }
- decrypter_.swap(other->decrypter_);
- alternative_decrypter_.swap(other->alternative_decrypter_);
-
- const bool other_latch = other->alternative_decrypter_latch_;
- other->alternative_decrypter_latch_ = alternative_decrypter_latch_;
- alternative_decrypter_latch_ = other_latch;
-}
-
QuicEncryptedPacket* QuicFramer::EncryptPacket(
EncryptionLevel level,
QuicPacketSequenceNumber packet_sequence_number,
header.public_header.version_flag,
header.public_header.sequence_number_length),
encrypted));
- if (decrypted_.get() == NULL && alternative_decrypter_.get() != NULL) {
+ if (decrypted_.get() != NULL) {
+ visitor_->OnDecryptedPacket(decrypter_level_);
+ } else if (alternative_decrypter_.get() != NULL) {
decrypted_.reset(alternative_decrypter_->DecryptPacket(
header.packet_sequence_number,
GetAssociatedDataFromEncryptedPacket(
header.public_header.sequence_number_length),
encrypted));
if (decrypted_.get() != NULL) {
+ visitor_->OnDecryptedPacket(alternative_decrypter_level_);
if (alternative_decrypter_latch_) {
// Switch to the alternative decrypter and latch so that we cannot
// switch back.
decrypter_.reset(alternative_decrypter_.release());
+ decrypter_level_ = alternative_decrypter_level_;
+ alternative_decrypter_level_ = ENCRYPTION_NONE;
} else {
// Switch the alternative decrypter so that we use it first next time.
decrypter_.swap(alternative_decrypter_);
+ EncryptionLevel level = alternative_decrypter_level_;
+ alternative_decrypter_level_ = decrypter_level_;
+ decrypter_level_ = level;
}
}
}
if (decrypted_.get() == NULL) {
+ DLOG(WARNING) << "DecryptPacket failed for sequence_number:"
+ << header.packet_sequence_number;
return false;
}
sequence_number_length,
largest_observed_length);
if (!ack_info.nack_ranges.empty()) {
- ack_size += kNumberOfMissingPacketsSize +
- (quic_version_ == QUIC_VERSION_13 ? 0 : kNumberOfRevivedPacketsSize);
+ ack_size += kNumberOfMissingPacketsSize + kNumberOfRevivedPacketsSize;
ack_size += ack_info.nack_ranges.size() *
(missing_sequence_number_length + PACKET_1BYTE_SEQUENCE_NUMBER);
ack_size +=
size_t QuicFramer::ComputeFrameLength(
const QuicFrame& frame,
bool last_frame_in_packet,
+ InFecGroup is_in_fec_group,
QuicSequenceNumberLength sequence_number_length) {
switch (frame.type) {
case STREAM_FRAME:
return GetMinStreamFrameSize(quic_version_,
frame.stream_frame->stream_id,
frame.stream_frame->offset,
- last_frame_in_packet) +
+ last_frame_in_packet,
+ is_in_fec_group) +
frame.stream_frame->data.TotalBufferSize();
case ACK_FRAME: {
return GetAckFrameSize(*frame.ack_frame, sequence_number_length);
case kInterArrival: {
const CongestionFeedbackMessageInterArrival& inter_arrival =
congestion_feedback.inter_arrival;
- if (quic_version_ == QUIC_VERSION_13) {
- len += 2; // Accumulated number of lost packets.
- }
len += 1; // Number received packets.
if (inter_arrival.received_packet_times.size() > 0) {
len += PACKET_6BYTE_SEQUENCE_NUMBER; // Smallest received.
len += 4; // Bitrate.
break;
case kTCP:
- if (quic_version_ == QUIC_VERSION_13) {
- len += 2; // Accumulated number of lost packets.
- }
len += 2; // Receive window.
break;
default:
}
case STOP_WAITING_FRAME:
return GetStopWaitingFrameSize(sequence_number_length);
+ case PING_FRAME:
+ // Ping has no payload.
+ return kQuicFrameTypeSize;
case RST_STREAM_FRAME:
return GetMinRstStreamFrameSize(quic_version_) +
frame.rst_stream_frame->error_details.size();
}
bool QuicFramer::AppendTypeByte(const QuicFrame& frame,
- bool last_frame_in_packet,
+ bool no_stream_frame_length,
QuicDataWriter* writer) {
uint8 type_byte = 0;
switch (frame.type) {
// Data Length bit.
type_byte <<= kQuicStreamDataLengthShift;
- type_byte |= last_frame_in_packet ? 0 : kQuicStreamDataLengthMask;
+ type_byte |= no_stream_frame_length ? 0: kQuicStreamDataLengthMask;
// Offset 3 bits.
type_byte <<= kQuicStreamOffsetShift;
bool QuicFramer::AppendStreamFrame(
const QuicStreamFrame& frame,
- bool last_frame_in_packet,
+ bool no_stream_frame_length,
QuicDataWriter* writer) {
if (!writer->WriteBytes(&frame.stream_id, GetStreamIdSize(frame.stream_id))) {
+ LOG(DFATAL) << "Writing stream id size failed.";
return false;
}
if (!writer->WriteBytes(&frame.offset, GetStreamOffsetSize(frame.offset))) {
+ LOG(DFATAL) << "Writing offset size failed.";
return false;
}
- if (!last_frame_in_packet) {
+ if (!no_stream_frame_length) {
if (!writer->WriteUInt16(frame.data.TotalBufferSize())) {
+ LOG(DFATAL) << "Writing stream frame length failed";
return false;
}
}
if (!writer->WriteIOVector(frame.data)) {
+ LOG(DFATAL) << "Writing frame data failed.";
return false;
}
return true;
size_t available_range_bytes = writer->capacity() - writer->length() -
GetMinAckFrameSize(quic_version_,
header.public_header.sequence_number_length,
- largest_observed_length) -
- (quic_version_ == QUIC_VERSION_13 ? 0 : kNumberOfRevivedPacketsSize);
+ largest_observed_length) - kNumberOfRevivedPacketsSize;
size_t max_num_ranges = available_range_bytes /
(missing_sequence_number_length + PACKET_1BYTE_SEQUENCE_NUMBER);
max_num_ranges =
}
DCHECK_EQ(num_missing_ranges, num_ranges_written);
- if (quic_version_ != QUIC_VERSION_13) {
- // Append revived packets.
- // If not all the revived packets fit, only mention the ones that do.
- uint8 num_revived_packets =
- min(received_info.revived_packets.size(),
- static_cast<size_t>(numeric_limits<uint8>::max()));
- num_revived_packets = min(
- static_cast<size_t>(num_revived_packets),
- (writer->capacity() - writer->length()) / largest_observed_length);
- if (!writer->WriteBytes(&num_revived_packets, 1)) {
- return false;
- }
+ // Append revived packets.
+ // If not all the revived packets fit, only mention the ones that do.
+ uint8 num_revived_packets =
+ min(received_info.revived_packets.size(),
+ static_cast<size_t>(numeric_limits<uint8>::max()));
+ num_revived_packets = min(
+ static_cast<size_t>(num_revived_packets),
+ (writer->capacity() - writer->length()) / largest_observed_length);
+ if (!writer->WriteBytes(&num_revived_packets, 1)) {
+ return false;
+ }
- SequenceNumberSet::const_iterator iter =
- received_info.revived_packets.begin();
- for (int i = 0; i < num_revived_packets; ++i, ++iter) {
- LOG_IF(DFATAL, !ContainsKey(received_info.missing_packets, *iter));
- if (!AppendPacketSequenceNumber(largest_observed_length,
- *iter, writer)) {
- return false;
- }
+ SequenceNumberSet::const_iterator iter =
+ received_info.revived_packets.begin();
+ for (int i = 0; i < num_revived_packets; ++i, ++iter) {
+ LOG_IF(DFATAL, !ContainsKey(received_info.missing_packets, *iter));
+ if (!AppendPacketSequenceNumber(largest_observed_length,
+ *iter, writer)) {
+ return false;
}
}
case kInterArrival: {
const CongestionFeedbackMessageInterArrival& inter_arrival =
frame.inter_arrival;
- if (quic_version_ == QUIC_VERSION_13) {
- // accumulated_number_of_lost_packets is removed. Always write 0.
- if (!writer->WriteUInt16(0)) {
- return false;
- }
- }
DCHECK_GE(numeric_limits<uint8>::max(),
inter_arrival.received_packet_times.size());
if (inter_arrival.received_packet_times.size() >
DCHECK_LE(tcp.receive_window, 1u << 20);
// Simple bit packing, don't send the 4 least significant bits.
uint16 receive_window = static_cast<uint16>(tcp.receive_window >> 4);
- if (quic_version_ == QUIC_VERSION_13) {
- // accumulated_number_of_lost_packets is removed. Always write 0.
- if (!writer->WriteUInt16(0)) {
- return false;
- }
- }
if (!writer->WriteUInt16(receive_window)) {
return false;
}
return false;
}
- if (quic_version_ > QUIC_VERSION_13) {
- if (!writer->WriteUInt64(frame.byte_offset)) {
- return false;
- }
+ if (!writer->WriteUInt64(frame.byte_offset)) {
+ return false;
}
uint32 error_code = static_cast<uint32>(frame.error_code);