blob: cc37c111d7e4e5e5f33e4acb6229bdf0330449b4 [file] [log] [blame]
// 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_protocol.h"
#include "base/stl_util.h"
#include "net/quic/quic_utils.h"
using base::StringPiece;
using std::map;
using std::numeric_limits;
using std::ostream;
using std::string;
namespace net {
size_t GetPacketHeaderSize(QuicPacketHeader header) {
return GetPacketHeaderSize(header.public_header.guid_length,
header.public_header.version_flag,
header.public_header.sequence_number_length,
header.is_in_fec_group);
}
size_t GetPacketHeaderSize(QuicGuidLength guid_length,
bool include_version,
QuicSequenceNumberLength sequence_number_length,
InFecGroup is_in_fec_group) {
return kPublicFlagsSize + guid_length +
(include_version ? kQuicVersionSize : 0) + sequence_number_length +
kPrivateFlagsSize + (is_in_fec_group == IN_FEC_GROUP ? kFecGroupSize : 0);
}
size_t GetPublicResetPacketSize() {
return kPublicFlagsSize + PACKET_8BYTE_GUID + kPublicResetNonceSize +
PACKET_6BYTE_SEQUENCE_NUMBER;
}
size_t GetStartOfFecProtectedData(
QuicGuidLength guid_length,
bool include_version,
QuicSequenceNumberLength sequence_number_length) {
return GetPacketHeaderSize(
guid_length, include_version, sequence_number_length, IN_FEC_GROUP);
}
size_t GetStartOfEncryptedData(
QuicGuidLength guid_length,
bool include_version,
QuicSequenceNumberLength sequence_number_length) {
// Don't include the fec size, since encryption starts before private flags.
return GetPacketHeaderSize(
guid_length, include_version, sequence_number_length, NOT_IN_FEC_GROUP) -
kPrivateFlagsSize;
}
QuicPacketPublicHeader::QuicPacketPublicHeader()
: guid(0),
guid_length(PACKET_8BYTE_GUID),
reset_flag(false),
version_flag(false),
sequence_number_length(PACKET_6BYTE_SEQUENCE_NUMBER) {
}
QuicPacketPublicHeader::QuicPacketPublicHeader(
const QuicPacketPublicHeader& other)
: guid(other.guid),
guid_length(other.guid_length),
reset_flag(other.reset_flag),
version_flag(other.version_flag),
sequence_number_length(other.sequence_number_length),
versions(other.versions) {
}
QuicPacketPublicHeader::~QuicPacketPublicHeader() {}
QuicPacketHeader::QuicPacketHeader()
: fec_flag(false),
entropy_flag(false),
entropy_hash(0),
packet_sequence_number(0),
is_in_fec_group(NOT_IN_FEC_GROUP),
fec_group(0) {
}
QuicPacketHeader::QuicPacketHeader(const QuicPacketPublicHeader& header)
: public_header(header),
fec_flag(false),
entropy_flag(false),
entropy_hash(0),
packet_sequence_number(0),
is_in_fec_group(NOT_IN_FEC_GROUP),
fec_group(0) {
}
QuicStreamFrame::QuicStreamFrame() {}
QuicStreamFrame::QuicStreamFrame(const QuicStreamFrame& frame)
: stream_id(frame.stream_id),
fin(frame.fin),
offset(frame.offset),
data(frame.data),
notifier(frame.notifier) {
}
QuicStreamFrame::QuicStreamFrame(QuicStreamId stream_id,
bool fin,
QuicStreamOffset offset,
IOVector data)
: stream_id(stream_id),
fin(fin),
offset(offset),
data(data),
notifier(NULL) {
}
string* QuicStreamFrame::GetDataAsString() const {
string* data_string = new string();
data_string->reserve(data.TotalBufferSize());
for (size_t i = 0; i < data.Size(); ++i) {
data_string->append(static_cast<char*>(data.iovec()[i].iov_base),
data.iovec()[i].iov_len);
}
DCHECK_EQ(data_string->size(), data.TotalBufferSize());
return data_string;
}
uint32 MakeQuicTag(char a, char b, char c, char d) {
return static_cast<uint32>(a) |
static_cast<uint32>(b) << 8 |
static_cast<uint32>(c) << 16 |
static_cast<uint32>(d) << 24;
}
QuicVersionVector QuicSupportedVersions() {
QuicVersionVector supported_versions;
for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
supported_versions.push_back(kSupportedQuicVersions[i]);
}
return supported_versions;
}
QuicTag QuicVersionToQuicTag(const QuicVersion version) {
switch (version) {
case QUIC_VERSION_12:
return MakeQuicTag('Q', '0', '1', '2');
default:
// This shold be an ERROR because we should never attempt to convert an
// invalid QuicVersion to be written to the wire.
LOG(ERROR) << "Unsupported QuicVersion: " << version;
return 0;
}
}
QuicVersion QuicTagToQuicVersion(const QuicTag version_tag) {
for (size_t i = 0; i < arraysize(kSupportedQuicVersions); ++i) {
if (version_tag == QuicVersionToQuicTag(kSupportedQuicVersions[i])) {
return kSupportedQuicVersions[i];
}
}
// Reading from the client so this should not be considered an ERROR.
DVLOG(1) << "Unsupported QuicTag version: "
<< QuicUtils::TagToString(version_tag);
return QUIC_VERSION_UNSUPPORTED;
}
#define RETURN_STRING_LITERAL(x) \
case x: \
return #x
string QuicVersionToString(const QuicVersion version) {
switch (version) {
RETURN_STRING_LITERAL(QUIC_VERSION_12);
default:
return "QUIC_VERSION_UNSUPPORTED";
}
}
string QuicVersionVectorToString(const QuicVersionVector& versions) {
string result = "";
for (size_t i = 0; i < versions.size(); ++i) {
if (i != 0) {
result.append(",");
}
result.append(QuicVersionToString(versions[i]));
}
return result;
}
ostream& operator<<(ostream& os, const QuicPacketHeader& header) {
os << "{ guid: " << header.public_header.guid
<< ", guid_length:" << header.public_header.guid_length
<< ", sequence_number_length:"
<< header.public_header.sequence_number_length
<< ", reset_flag: " << header.public_header.reset_flag
<< ", version_flag: " << header.public_header.version_flag;
if (header.public_header.version_flag) {
os << " version: ";
for (size_t i = 0; i < header.public_header.versions.size(); ++i) {
os << header.public_header.versions[0] << " ";
}
}
os << ", fec_flag: " << header.fec_flag
<< ", entropy_flag: " << header.entropy_flag
<< ", entropy hash: " << static_cast<int>(header.entropy_hash)
<< ", sequence_number: " << header.packet_sequence_number
<< ", is_in_fec_group:" << header.is_in_fec_group
<< ", fec_group: " << header.fec_group<< "}\n";
return os;
}
ReceivedPacketInfo::ReceivedPacketInfo()
: largest_observed(0),
delta_time_largest_observed(QuicTime::Delta::Infinite()),
is_truncated(false) {
}
ReceivedPacketInfo::~ReceivedPacketInfo() {}
bool IsAwaitingPacket(const ReceivedPacketInfo& received_info,
QuicPacketSequenceNumber sequence_number) {
return sequence_number > received_info.largest_observed ||
ContainsKey(received_info.missing_packets, sequence_number);
}
void InsertMissingPacketsBetween(ReceivedPacketInfo* received_info,
QuicPacketSequenceNumber lower,
QuicPacketSequenceNumber higher) {
for (QuicPacketSequenceNumber i = lower; i < higher; ++i) {
received_info->missing_packets.insert(i);
}
}
SentPacketInfo::SentPacketInfo() {}
SentPacketInfo::~SentPacketInfo() {}
// Testing convenience method.
QuicAckFrame::QuicAckFrame(QuicPacketSequenceNumber largest_observed,
QuicTime largest_observed_receive_time,
QuicPacketSequenceNumber least_unacked) {
received_info.largest_observed = largest_observed;
received_info.entropy_hash = 0;
sent_info.least_unacked = least_unacked;
sent_info.entropy_hash = 0;
}
ostream& operator<<(ostream& os, const SentPacketInfo& sent_info) {
os << "entropy_hash: " << static_cast<int>(sent_info.entropy_hash)
<< " least_unacked: " << sent_info.least_unacked;
return os;
}
ostream& operator<<(ostream& os, const ReceivedPacketInfo& received_info) {
os << "entropy_hash: " << static_cast<int>(received_info.entropy_hash)
<< " largest_observed: " << received_info.largest_observed
<< " missing_packets: [ ";
for (SequenceNumberSet::const_iterator it =
received_info.missing_packets.begin();
it != received_info.missing_packets.end(); ++it) {
os << *it << " ";
}
os << " ] ";
return os;
}
QuicCongestionFeedbackFrame::QuicCongestionFeedbackFrame() {
}
QuicCongestionFeedbackFrame::~QuicCongestionFeedbackFrame() {
}
ostream& operator<<(ostream& os,
const QuicCongestionFeedbackFrame& congestion_frame) {
os << "type: " << congestion_frame.type;
switch (congestion_frame.type) {
case kInterArrival: {
const CongestionFeedbackMessageInterArrival& inter_arrival =
congestion_frame.inter_arrival;
os << " accumulated_number_of_lost_packets: "
<< inter_arrival.accumulated_number_of_lost_packets;
os << " received packets: [ ";
for (TimeMap::const_iterator it =
inter_arrival.received_packet_times.begin();
it != inter_arrival.received_packet_times.end(); ++it) {
os << it->first << "@" << it->second.ToDebuggingValue() << " ";
}
os << "]";
break;
}
case kFixRate: {
os << " bitrate_in_bytes_per_second: "
<< congestion_frame.fix_rate.bitrate.ToBytesPerSecond();
break;
}
case kTCP: {
const CongestionFeedbackMessageTCP& tcp = congestion_frame.tcp;
os << " accumulated_number_of_lost_packets: "
<< congestion_frame.tcp.accumulated_number_of_lost_packets;
os << " receive_window: " << tcp.receive_window;
break;
}
}
return os;
}
ostream& operator<<(ostream& os, const QuicAckFrame& ack_frame) {
os << "sent info { " << ack_frame.sent_info << " } "
<< "received info { " << ack_frame.received_info << " }\n";
return os;
}
CongestionFeedbackMessageFixRate::CongestionFeedbackMessageFixRate()
: bitrate(QuicBandwidth::Zero()) {
}
CongestionFeedbackMessageInterArrival::
CongestionFeedbackMessageInterArrival() {}
CongestionFeedbackMessageInterArrival::
~CongestionFeedbackMessageInterArrival() {}
QuicGoAwayFrame::QuicGoAwayFrame(QuicErrorCode error_code,
QuicStreamId last_good_stream_id,
const string& reason)
: error_code(error_code),
last_good_stream_id(last_good_stream_id),
reason_phrase(reason) {
DCHECK_LE(error_code, numeric_limits<uint8>::max());
}
QuicFecData::QuicFecData() {}
QuicData::~QuicData() {
if (owns_buffer_) {
delete [] const_cast<char*>(buffer_);
}
}
StringPiece QuicPacket::FecProtectedData() const {
const size_t start_of_fec = GetStartOfFecProtectedData(
guid_length_, includes_version_, sequence_number_length_);
return StringPiece(data() + start_of_fec, length() - start_of_fec);
}
StringPiece QuicPacket::AssociatedData() const {
return StringPiece(
data() + kStartOfHashData,
GetStartOfEncryptedData(
guid_length_, includes_version_, sequence_number_length_) -
kStartOfHashData);
}
StringPiece QuicPacket::BeforePlaintext() const {
return StringPiece(data(), GetStartOfEncryptedData(guid_length_,
includes_version_,
sequence_number_length_));
}
StringPiece QuicPacket::Plaintext() const {
const size_t start_of_encrypted_data =
GetStartOfEncryptedData(
guid_length_, includes_version_, sequence_number_length_);
return StringPiece(data() + start_of_encrypted_data,
length() - start_of_encrypted_data);
}
RetransmittableFrames::RetransmittableFrames()
: encryption_level_(NUM_ENCRYPTION_LEVELS) {
}
RetransmittableFrames::~RetransmittableFrames() {
for (QuicFrames::iterator it = frames_.begin(); it != 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;
}
}
STLDeleteElements(&stream_data_);
}
const QuicFrame& RetransmittableFrames::AddStreamFrame(
QuicStreamFrame* stream_frame) {
// Make an owned copy of the stream frame's data.
stream_data_.push_back(stream_frame->GetDataAsString());
// Ensure the stream frame's IOVector points to the owned copy of the data.
stream_frame->data.Clear();
stream_frame->data.Append(const_cast<char*>(stream_data_.back()->data()),
stream_data_.back()->size());
frames_.push_back(QuicFrame(stream_frame));
return frames_.back();
}
const QuicFrame& RetransmittableFrames::AddNonStreamFrame(
const QuicFrame& frame) {
DCHECK_NE(frame.type, STREAM_FRAME);
frames_.push_back(frame);
return frames_.back();
}
void RetransmittableFrames::set_encryption_level(EncryptionLevel level) {
encryption_level_ = level;
}
SerializedPacket::SerializedPacket(
QuicPacketSequenceNumber sequence_number,
QuicSequenceNumberLength sequence_number_length,
QuicPacket* packet,
QuicPacketEntropyHash entropy_hash,
RetransmittableFrames* retransmittable_frames)
: sequence_number(sequence_number),
sequence_number_length(sequence_number_length),
packet(packet),
entropy_hash(entropy_hash),
retransmittable_frames(retransmittable_frames) {
}
SerializedPacket::~SerializedPacket() {}
QuicEncryptedPacket* QuicEncryptedPacket::Clone() const {
char* buffer = new char[this->length()];
memcpy(buffer, this->data(), this->length());
return new QuicEncryptedPacket(buffer, this->length(), true);
}
ostream& operator<<(ostream& os, const QuicEncryptedPacket& s) {
os << s.length() << "-byte data";
return os;
}
ostream& operator<<(ostream& os, const QuicConsumedData& s) {
os << "bytes_consumed: " << s.bytes_consumed
<< " fin_consumed: " << s.fin_consumed;
return os;
}
} // namespace net