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