| Index: net/tools/quic/quic_packet_reader.cc
|
| diff --git a/net/tools/quic/quic_packet_reader.cc b/net/tools/quic/quic_packet_reader.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..1982269f30bc3b47c49750d9f745a67a38507ecc
|
| --- /dev/null
|
| +++ b/net/tools/quic/quic_packet_reader.cc
|
| @@ -0,0 +1,143 @@
|
| +// 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 "net/tools/quic/quic_packet_reader.h"
|
| +
|
| +#include <errno.h>
|
| +#ifndef __APPLE__
|
| +// This is a GNU header that is not present in /usr/include on MacOS
|
| +#include <features.h>
|
| +#endif
|
| +#include <string.h>
|
| +#include <sys/epoll.h>
|
| +
|
| +#include "base/logging.h"
|
| +#include "net/base/ip_endpoint.h"
|
| +#include "net/tools/quic/quic_dispatcher.h"
|
| +#include "net/tools/quic/quic_socket_utils.h"
|
| +
|
| +#define MMSG_MORE 0
|
| +
|
| +#ifndef SO_RXQ_OVFL
|
| +#define SO_RXQ_OVFL 40
|
| +#endif
|
| +
|
| +namespace net {
|
| +
|
| +namespace tools {
|
| +
|
| +QuicPacketReader::QuicPacketReader() {
|
| + Initialize();
|
| +}
|
| +
|
| +void QuicPacketReader::Initialize() {
|
| + // Zero initialize uninitialized memory.
|
| + memset(cbuf_, 0, arraysize(cbuf_));
|
| + memset(buf_, 0, arraysize(buf_));
|
| + memset(raw_address_, 0, sizeof(raw_address_));
|
| + memset(mmsg_hdr_, 0, sizeof(mmsg_hdr_));
|
| +
|
| + for (int i = 0; i < kNumPacketsPerReadMmsgCall; ++i) {
|
| + iov_[i].iov_base = buf_ + (2 * kMaxPacketSize * i);
|
| + iov_[i].iov_len = 2 * kMaxPacketSize;
|
| +
|
| + msghdr* hdr = &mmsg_hdr_[i].msg_hdr;
|
| + hdr->msg_name = &raw_address_[i];
|
| + hdr->msg_namelen = sizeof(sockaddr_storage);
|
| + hdr->msg_iov = &iov_[i];
|
| + hdr->msg_iovlen = 1;
|
| +
|
| + hdr->msg_control = cbuf_ + kSpaceForOverflowAndIp * i;
|
| + hdr->msg_controllen = kSpaceForOverflowAndIp;
|
| + }
|
| +}
|
| +
|
| +QuicPacketReader::~QuicPacketReader() {
|
| +}
|
| +
|
| +bool QuicPacketReader::ReadAndDispatchPackets(
|
| + int fd,
|
| + int port,
|
| + ProcessPacketInterface* processor,
|
| + QuicPacketCount* packets_dropped) {
|
| +#if MMSG_MORE
|
| + // Re-set the length fields in case recvmmsg has changed them.
|
| + for (int i = 0; i < kNumPacketsPerReadMmsgCall; ++i) {
|
| + iov_[i].iov_len = 2 * kMaxPacketSize;
|
| + mmsg_hdr_[i].msg_len = 0;
|
| + msghdr* hdr = &mmsg_hdr_[i].msg_hdr;
|
| + hdr->msg_namelen = sizeof(sockaddr_storage);
|
| + hdr->msg_iovlen = 1;
|
| + hdr->msg_controllen = kSpaceForOverflowAndIp;
|
| + }
|
| +
|
| + int packets_read =
|
| + recvmmsg(fd, mmsg_hdr_, kNumPacketsPerReadMmsgCall, 0, nullptr);
|
| +
|
| + if (packets_read <= 0) {
|
| + return false; // recvmmsg failed.
|
| + }
|
| +
|
| + for (int i = 0; i < packets_read; ++i) {
|
| + if (mmsg_hdr_[i].msg_len == 0) {
|
| + continue;
|
| + }
|
| +
|
| + IPEndPoint client_address = IPEndPoint(raw_address_[i]);
|
| + IPAddressNumber server_ip =
|
| + QuicSocketUtils::GetAddressFromMsghdr(&mmsg_hdr_[i].msg_hdr);
|
| + if (!IsInitializedAddress(server_ip)) {
|
| + LOG(DFATAL) << "Unable to get server address.";
|
| + continue;
|
| + }
|
| +
|
| + QuicEncryptedPacket packet(reinterpret_cast<char*>(iov_[i].iov_base),
|
| + mmsg_hdr_[i].msg_len, false);
|
| + IPEndPoint server_address(server_ip, port);
|
| + processor->ProcessPacket(server_address, client_address, packet);
|
| + }
|
| +
|
| + if (packets_dropped != nullptr) {
|
| + QuicSocketUtils::GetOverflowFromMsghdr(&mmsg_hdr_[0].msg_hdr,
|
| + packets_dropped);
|
| + }
|
| +
|
| + return true;
|
| +#else
|
| + LOG(FATAL) << "Unsupported";
|
| + return false;
|
| +#endif
|
| +}
|
| +
|
| +/* static */
|
| +bool QuicPacketReader::ReadAndDispatchSinglePacket(
|
| + int fd,
|
| + int port,
|
| + ProcessPacketInterface* processor,
|
| + QuicPacketCount* packets_dropped) {
|
| + // Allocate some extra space so we can send an error if the packet is larger
|
| + // than kMaxPacketSize.
|
| + char buf[2 * kMaxPacketSize];
|
| +
|
| + IPEndPoint client_address;
|
| + IPAddressNumber server_ip;
|
| + int bytes_read = QuicSocketUtils::ReadPacket(
|
| + fd, buf, arraysize(buf), packets_dropped, &server_ip, &client_address);
|
| +
|
| + if (bytes_read < 0) {
|
| + return false; // ReadPacket failed.
|
| + }
|
| +
|
| + QuicEncryptedPacket packet(buf, bytes_read, false);
|
| + IPEndPoint server_address(server_ip, port);
|
| + processor->ProcessPacket(server_address, client_address, packet);
|
| +
|
| + // The socket read was successful, so return true even if packet dispatch
|
| + // failed.
|
| + return true;
|
| +}
|
| +
|
| +} // namespace tools
|
| +
|
| +} // namespace net
|
|
|