// Copyright (c) 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/quic/quic_packet_reader.h" #include "base/metrics/histogram.h" #include "net/base/net_errors.h" namespace net { QuicPacketReader::QuicPacketReader(DatagramClientSocket* socket, Visitor* visitor, const BoundNetLog& net_log) : socket_(socket), visitor_(visitor), read_pending_(false), num_packets_read_(0), read_buffer_(new IOBufferWithSize(static_cast(kMaxPacketSize))), net_log_(net_log), weak_factory_(this) { } QuicPacketReader::~QuicPacketReader() { } void QuicPacketReader::StartReading() { if (read_pending_) return; DCHECK(socket_); read_pending_ = true; int rv = socket_->Read(read_buffer_.get(), read_buffer_->size(), base::Bind(&QuicPacketReader::OnReadComplete, weak_factory_.GetWeakPtr())); UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.AsyncRead", rv == ERR_IO_PENDING); if (rv == ERR_IO_PENDING) { num_packets_read_ = 0; return; } if (++num_packets_read_ > 32) { num_packets_read_ = 0; // Data was read, process it. // Schedule the work through the message loop to 1) prevent infinite // recursion and 2) avoid blocking the thread for too long. base::MessageLoop::current()->PostTask( FROM_HERE, base::Bind(&QuicPacketReader::OnReadComplete, weak_factory_.GetWeakPtr(), rv)); } else { OnReadComplete(rv); } } void QuicPacketReader::OnReadComplete(int result) { read_pending_ = false; if (result == 0) result = ERR_CONNECTION_CLOSED; if (result < 0) { visitor_->OnReadError(result); return; } QuicEncryptedPacket packet(read_buffer_->data(), result); IPEndPoint local_address; IPEndPoint peer_address; socket_->GetLocalAddress(&local_address); socket_->GetPeerAddress(&peer_address); if (!visitor_->OnPacket(packet, local_address, peer_address)) return; StartReading(); } } // namespace net