blob: 32160132db460e6fd26bebffd077a0623ab770c9 [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -05001// Copyright 2015 The Chromium Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
5#include "net/third_party/quiche/src/quic/core/quic_packet_reader.h"
6
7#include <errno.h>
8#ifndef __APPLE__
9// This is a GNU header that is not present on Apple platforms
10#include <features.h>
11#endif
12#include <string.h>
13#include <sys/socket.h>
14
15#include "net/third_party/quiche/src/quic/core/quic_packets.h"
16#include "net/third_party/quiche/src/quic/core/quic_process_packet_interface.h"
17#include "net/third_party/quiche/src/quic/platform/api/quic_arraysize.h"
18#include "net/third_party/quiche/src/quic/platform/api/quic_bug_tracker.h"
19#include "net/third_party/quiche/src/quic/platform/api/quic_flag_utils.h"
20#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
21#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
22#include "net/third_party/quiche/src/quic/platform/api/quic_server_stats.h"
23#include "net/third_party/quiche/src/quic/platform/api/quic_socket_address.h"
24#include "net/quic/platform/impl/quic_socket_utils.h"
25
26#ifndef SO_RXQ_OVFL
27#define SO_RXQ_OVFL 40
28#endif
29
30namespace quic {
31
32QuicPacketReader::QuicPacketReader() {
33 Initialize();
34}
35
36void QuicPacketReader::Initialize() {
37#if MMSG_MORE
38 // Zero initialize uninitialized memory.
39 memset(mmsg_hdr_, 0, sizeof(mmsg_hdr_));
40
41 for (int i = 0; i < kNumPacketsPerReadMmsgCall; ++i) {
42 packets_[i].iov.iov_base = packets_[i].buf;
43 packets_[i].iov.iov_len = sizeof(packets_[i].buf);
44 memset(&packets_[i].raw_address, 0, sizeof(packets_[i].raw_address));
45 memset(packets_[i].cbuf, 0, sizeof(packets_[i].cbuf));
46 memset(packets_[i].buf, 0, sizeof(packets_[i].buf));
47
48 msghdr* hdr = &mmsg_hdr_[i].msg_hdr;
49 hdr->msg_name = &packets_[i].raw_address;
50 hdr->msg_namelen = sizeof(sockaddr_storage);
51 hdr->msg_iov = &packets_[i].iov;
52 hdr->msg_iovlen = 1;
53
54 hdr->msg_control = packets_[i].cbuf;
55 hdr->msg_controllen = kCmsgSpaceForReadPacket;
56 }
57#endif
58}
59
60QuicPacketReader::~QuicPacketReader() = default;
61
62bool QuicPacketReader::ReadAndDispatchPackets(
63 int fd,
64 int port,
65 const QuicClock& clock,
66 ProcessPacketInterface* processor,
67 QuicPacketCount* packets_dropped) {
68#if MMSG_MORE_NO_ANDROID
69 return ReadAndDispatchManyPackets(fd, port, clock, processor,
70 packets_dropped);
71#else
72 return ReadAndDispatchSinglePacket(fd, port, clock, processor,
73 packets_dropped);
74#endif
75}
76
77bool QuicPacketReader::ReadAndDispatchManyPackets(
78 int fd,
79 int port,
80 const QuicClock& clock,
81 ProcessPacketInterface* processor,
82 QuicPacketCount* packets_dropped) {
83#if MMSG_MORE_NO_ANDROID
84 // Re-set the length fields in case recvmmsg has changed them.
85 for (int i = 0; i < kNumPacketsPerReadMmsgCall; ++i) {
86 DCHECK_LE(kMaxPacketSize, packets_[i].iov.iov_len);
87 msghdr* hdr = &mmsg_hdr_[i].msg_hdr;
88 hdr->msg_namelen = sizeof(sockaddr_storage);
89 DCHECK_EQ(1, hdr->msg_iovlen);
90 hdr->msg_controllen = kCmsgSpaceForReadPacket;
91 hdr->msg_flags = 0;
92 }
93
94 int packets_read =
95 recvmmsg(fd, mmsg_hdr_, kNumPacketsPerReadMmsgCall, MSG_TRUNC, nullptr);
96
97 if (packets_read <= 0) {
98 return false; // recvmmsg failed.
99 }
100
101 bool use_quic_time =
102 GetQuicReloadableFlag(quic_use_quic_time_for_received_timestamp);
103 QuicTime fallback_timestamp(QuicTime::Zero());
104 QuicWallTime fallback_walltimestamp = QuicWallTime::Zero();
105 for (int i = 0; i < packets_read; ++i) {
106 if (mmsg_hdr_[i].msg_len == 0) {
107 continue;
108 }
109
110 if (QUIC_PREDICT_FALSE(mmsg_hdr_[i].msg_hdr.msg_flags & MSG_CTRUNC)) {
111 QUIC_BUG << "Incorrectly set control length: "
112 << mmsg_hdr_[i].msg_hdr.msg_controllen << ", expected "
113 << kCmsgSpaceForReadPacket;
114 continue;
115 }
116
117 if (QUIC_PREDICT_FALSE(mmsg_hdr_[i].msg_hdr.msg_flags & MSG_TRUNC)) {
118 QUIC_LOG_FIRST_N(WARNING, 100)
119 << "Dropping truncated QUIC packet: buffer size:"
120 << packets_[i].iov.iov_len << " packet size:" << mmsg_hdr_[i].msg_len;
121 QUIC_SERVER_HISTOGRAM_COUNTS(
122 "QuicPacketReader.DroppedPacketSize", mmsg_hdr_[i].msg_len, 1, 10000,
123 20, "In QuicPacketReader, the size of big packets that are dropped.");
124 continue;
125 }
126
127 QuicSocketAddress peer_address(packets_[i].raw_address);
128 QuicIpAddress self_ip;
129 QuicWallTime packet_walltimestamp = QuicWallTime::Zero();
130 QuicSocketUtils::GetAddressAndTimestampFromMsghdr(
131 &mmsg_hdr_[i].msg_hdr, &self_ip, &packet_walltimestamp);
132 if (!self_ip.IsInitialized()) {
133 QUIC_BUG << "Unable to get self IP address.";
134 continue;
135 }
136
137 // This isn't particularly desirable, but not all platforms support socket
138 // timestamping.
139 QuicTime timestamp(QuicTime::Zero());
140 if (!use_quic_time) {
141 if (packet_walltimestamp.IsZero()) {
142 if (fallback_walltimestamp.IsZero()) {
143 fallback_walltimestamp = clock.WallNow();
144 }
145 packet_walltimestamp = fallback_walltimestamp;
146 }
147 timestamp = clock.ConvertWallTimeToQuicTime(packet_walltimestamp);
148
149 } else {
150 QUIC_RELOADABLE_FLAG_COUNT(quic_use_quic_time_for_received_timestamp);
151 if (packet_walltimestamp.IsZero()) {
152 if (!fallback_timestamp.IsInitialized()) {
153 fallback_timestamp = clock.Now();
154 }
155 timestamp = fallback_timestamp;
156 } else {
157 timestamp = clock.ConvertWallTimeToQuicTime(packet_walltimestamp);
158 }
159 }
160 int ttl = 0;
161 bool has_ttl =
162 QuicSocketUtils::GetTtlFromMsghdr(&mmsg_hdr_[i].msg_hdr, &ttl);
163 char* headers = nullptr;
164 size_t headers_length = 0;
165 QuicSocketUtils::GetPacketHeadersFromMsghdr(&mmsg_hdr_[i].msg_hdr, &headers,
166 &headers_length);
167 QuicReceivedPacket packet(reinterpret_cast<char*>(packets_[i].iov.iov_base),
168 mmsg_hdr_[i].msg_len, timestamp, false, ttl,
169 has_ttl, headers, headers_length, false);
170 QuicSocketAddress self_address(self_ip, port);
171 processor->ProcessPacket(self_address, peer_address, packet);
172 }
173
174 if (packets_dropped != nullptr) {
175 QuicSocketUtils::GetOverflowFromMsghdr(&mmsg_hdr_[0].msg_hdr,
176 packets_dropped);
177 }
178
179 // We may not have read all of the packets available on the socket.
180 return packets_read == kNumPacketsPerReadMmsgCall;
181#else
182 QUIC_LOG(FATAL) << "Unsupported";
183 return false;
184#endif
185}
186
187/* static */
188bool QuicPacketReader::ReadAndDispatchSinglePacket(
189 int fd,
190 int port,
191 const QuicClock& clock,
192 ProcessPacketInterface* processor,
193 QuicPacketCount* packets_dropped) {
194 char buf[kMaxV4PacketSize];
195
196 QuicSocketAddress peer_address;
197 QuicIpAddress self_ip;
198 QuicWallTime walltimestamp = QuicWallTime::Zero();
199 int bytes_read =
200 QuicSocketUtils::ReadPacket(fd, buf, QUIC_ARRAYSIZE(buf), packets_dropped,
201 &self_ip, &walltimestamp, &peer_address);
202 if (bytes_read < 0) {
203 return false; // ReadPacket failed.
204 }
205
206 if (!self_ip.IsInitialized()) {
207 QUIC_BUG << "Unable to get self IP address.";
208 return false;
209 }
210 // This isn't particularly desirable, but not all platforms support socket
211 // timestamping.
212 if (walltimestamp.IsZero()) {
213 walltimestamp = clock.WallNow();
214 }
215 QuicTime timestamp = clock.ConvertWallTimeToQuicTime(walltimestamp);
216
217 QuicReceivedPacket packet(buf, bytes_read, timestamp, false);
218 QuicSocketAddress self_address(self_ip, port);
219 processor->ProcessPacket(self_address, peer_address, packet);
220
221 // The socket read was successful, so return true even if packet dispatch
222 // failed.
223 return true;
224}
225
226} // namespace quic