| // 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 |