quic_chromium_packet_reader.cc 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118
  1. // Copyright (c) 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. #include "net/quic/quic_chromium_packet_reader.h"
  5. #include "base/bind.h"
  6. #include "base/location.h"
  7. #include "base/metrics/histogram_macros.h"
  8. #include "base/task/single_thread_task_runner.h"
  9. #include "base/threading/thread_task_runner_handle.h"
  10. #include "net/base/net_errors.h"
  11. #include "net/quic/address_utils.h"
  12. #include "net/third_party/quiche/src/quiche/quic/core/quic_clock.h"
  13. namespace net {
  14. namespace {
  15. // Add 1 because some of our UDP socket implementations do not read successfully
  16. // when the packet length is equal to the read buffer size.
  17. const size_t kReadBufferSize =
  18. static_cast<size_t>(quic::kMaxIncomingPacketSize + 1);
  19. } // namespace
  20. QuicChromiumPacketReader::QuicChromiumPacketReader(
  21. DatagramClientSocket* socket,
  22. const quic::QuicClock* clock,
  23. Visitor* visitor,
  24. int yield_after_packets,
  25. quic::QuicTime::Delta yield_after_duration,
  26. const NetLogWithSource& net_log)
  27. : socket_(socket),
  28. visitor_(visitor),
  29. clock_(clock),
  30. yield_after_packets_(yield_after_packets),
  31. yield_after_duration_(yield_after_duration),
  32. yield_after_(quic::QuicTime::Infinite()),
  33. read_buffer_(base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize)),
  34. net_log_(net_log) {}
  35. QuicChromiumPacketReader::~QuicChromiumPacketReader() = default;
  36. void QuicChromiumPacketReader::StartReading() {
  37. for (;;) {
  38. if (read_pending_)
  39. return;
  40. if (num_packets_read_ == 0)
  41. yield_after_ = clock_->Now() + yield_after_duration_;
  42. CHECK(socket_);
  43. read_pending_ = true;
  44. int rv =
  45. socket_->Read(read_buffer_.get(), read_buffer_->size(),
  46. base::BindOnce(&QuicChromiumPacketReader::OnReadComplete,
  47. weak_factory_.GetWeakPtr()));
  48. UMA_HISTOGRAM_BOOLEAN("Net.QuicSession.AsyncRead", rv == ERR_IO_PENDING);
  49. if (rv == ERR_IO_PENDING) {
  50. num_packets_read_ = 0;
  51. return;
  52. }
  53. if (++num_packets_read_ > yield_after_packets_ ||
  54. clock_->Now() > yield_after_) {
  55. num_packets_read_ = 0;
  56. // Data was read, process it.
  57. // Schedule the work through the message loop to 1) prevent infinite
  58. // recursion and 2) avoid blocking the thread for too long.
  59. base::ThreadTaskRunnerHandle::Get()->PostTask(
  60. FROM_HERE, base::BindOnce(&QuicChromiumPacketReader::OnReadComplete,
  61. weak_factory_.GetWeakPtr(), rv));
  62. } else {
  63. if (!ProcessReadResult(rv)) {
  64. return;
  65. }
  66. }
  67. }
  68. }
  69. bool QuicChromiumPacketReader::ProcessReadResult(int result) {
  70. read_pending_ = false;
  71. if (result <= 0 && net_log_.IsCapturing()) {
  72. net_log_.AddEventWithIntParams(NetLogEventType::QUIC_READ_ERROR,
  73. "net_error", result);
  74. }
  75. if (result == 0) {
  76. // 0-length UDP packets are legal but useless, ignore them.
  77. return true;
  78. }
  79. if (result == ERR_MSG_TOO_BIG) {
  80. // This indicates that we received a UDP packet larger than our receive
  81. // buffer, ignore it.
  82. return true;
  83. }
  84. if (result < 0) {
  85. // Report all other errors to the visitor.
  86. return visitor_->OnReadError(result, socket_);
  87. }
  88. quic::QuicReceivedPacket packet(read_buffer_->data(), result, clock_->Now());
  89. IPEndPoint local_address;
  90. IPEndPoint peer_address;
  91. socket_->GetLocalAddress(&local_address);
  92. socket_->GetPeerAddress(&peer_address);
  93. auto self = weak_factory_.GetWeakPtr();
  94. // Notifies the visitor that |this| reader gets a new packet, which may delete
  95. // |this| if |this| is a connectivity probing reader.
  96. return visitor_->OnPacket(packet, ToQuicSocketAddress(local_address),
  97. ToQuicSocketAddress(peer_address)) &&
  98. self;
  99. }
  100. void QuicChromiumPacketReader::OnReadComplete(int result) {
  101. if (ProcessReadResult(result))
  102. StartReading();
  103. }
  104. } // namespace net