blob: 3a8a9b4fe3d99974584d5e16df3adf5a80b42bef [file] [log] [blame]
// Copyright 2015 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 "quic/core/quic_packet_reader.h"
#include "absl/base/macros.h"
#include "quic/core/quic_packets.h"
#include "quic/core/quic_process_packet_interface.h"
#include "quic/platform/api/quic_bug_tracker.h"
#include "quic/platform/api/quic_flag_utils.h"
#include "quic/platform/api/quic_flags.h"
#include "quic/platform/api/quic_ip_address.h"
#include "quic/platform/api/quic_logging.h"
#include "quic/platform/api/quic_server_stats.h"
#include "quic/platform/api/quic_socket_address.h"
namespace quic {
QuicPacketReader::QuicPacketReader()
: read_buffers_(kNumPacketsPerReadMmsgCall),
read_results_(kNumPacketsPerReadMmsgCall) {
QUICHE_DCHECK_EQ(read_buffers_.size(), read_results_.size());
for (size_t i = 0; i < read_results_.size(); ++i) {
read_results_[i].packet_buffer.buffer = read_buffers_[i].packet_buffer;
read_results_[i].packet_buffer.buffer_len =
sizeof(read_buffers_[i].packet_buffer);
read_results_[i].control_buffer.buffer = read_buffers_[i].control_buffer;
read_results_[i].control_buffer.buffer_len =
sizeof(read_buffers_[i].control_buffer);
}
}
QuicPacketReader::~QuicPacketReader() = default;
bool QuicPacketReader::ReadAndDispatchPackets(
int fd,
int port,
const QuicClock& clock,
ProcessPacketInterface* processor,
QuicPacketCount* /*packets_dropped*/) {
// Reset all read_results for reuse.
for (size_t i = 0; i < read_results_.size(); ++i) {
read_results_[i].Reset(
/*packet_buffer_length=*/sizeof(read_buffers_[i].packet_buffer));
}
// Use clock.Now() as the packet receipt time, the time between packet
// arriving at the host and now is considered part of the network delay.
QuicTime now = clock.Now();
size_t packets_read = socket_api_.ReadMultiplePackets(
fd,
BitMask64(QuicUdpPacketInfoBit::DROPPED_PACKETS,
QuicUdpPacketInfoBit::PEER_ADDRESS,
QuicUdpPacketInfoBit::V4_SELF_IP,
QuicUdpPacketInfoBit::V6_SELF_IP,
QuicUdpPacketInfoBit::RECV_TIMESTAMP, QuicUdpPacketInfoBit::TTL,
QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER),
&read_results_);
for (size_t i = 0; i < packets_read; ++i) {
auto& result = read_results_[i];
if (!result.ok) {
QUIC_CODE_COUNT(quic_packet_reader_read_failure);
continue;
}
if (!result.packet_info.HasValue(QuicUdpPacketInfoBit::PEER_ADDRESS)) {
QUIC_BUG(quic_bug_10329_1) << "Unable to get peer socket address.";
continue;
}
QuicSocketAddress peer_address =
result.packet_info.peer_address().Normalized();
QuicIpAddress self_ip = GetSelfIpFromPacketInfo(
result.packet_info, peer_address.host().IsIPv6());
if (!self_ip.IsInitialized()) {
QUIC_BUG(quic_bug_10329_2) << "Unable to get self IP address.";
continue;
}
bool has_ttl = result.packet_info.HasValue(QuicUdpPacketInfoBit::TTL);
int ttl = has_ttl ? result.packet_info.ttl() : 0;
if (!has_ttl) {
QUIC_CODE_COUNT(quic_packet_reader_no_ttl);
}
char* headers = nullptr;
size_t headers_length = 0;
if (result.packet_info.HasValue(
QuicUdpPacketInfoBit::GOOGLE_PACKET_HEADER)) {
headers = result.packet_info.google_packet_headers().buffer;
headers_length = result.packet_info.google_packet_headers().buffer_len;
} else {
QUIC_CODE_COUNT(quic_packet_reader_no_google_packet_header);
}
QuicReceivedPacket packet(
result.packet_buffer.buffer, result.packet_buffer.buffer_len, now,
/*owns_buffer=*/false, ttl, has_ttl, headers, headers_length,
/*owns_header_buffer=*/false);
QuicSocketAddress self_address(self_ip, port);
processor->ProcessPacket(self_address, peer_address, packet);
}
// We may not have read all of the packets available on the socket.
return packets_read == kNumPacketsPerReadMmsgCall;
}
// static
QuicIpAddress QuicPacketReader::GetSelfIpFromPacketInfo(
const QuicUdpPacketInfo& packet_info,
bool prefer_v6_ip) {
if (prefer_v6_ip) {
if (packet_info.HasValue(QuicUdpPacketInfoBit::V6_SELF_IP)) {
return packet_info.self_v6_ip();
}
if (packet_info.HasValue(QuicUdpPacketInfoBit::V4_SELF_IP)) {
return packet_info.self_v4_ip();
}
} else {
if (packet_info.HasValue(QuicUdpPacketInfoBit::V4_SELF_IP)) {
return packet_info.self_v4_ip();
}
if (packet_info.HasValue(QuicUdpPacketInfoBit::V6_SELF_IP)) {
return packet_info.self_v6_ip();
}
}
return QuicIpAddress();
}
} // namespace quic