quic_simple_server.cc 7.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. // Copyright 2014 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/tools/quic/quic_simple_server.h"
  5. #include <string.h>
  6. #include <memory>
  7. #include "base/bind.h"
  8. #include "base/location.h"
  9. #include "base/run_loop.h"
  10. #include "base/task/single_thread_task_runner.h"
  11. #include "base/threading/thread_task_runner_handle.h"
  12. #include "net/base/ip_endpoint.h"
  13. #include "net/base/net_errors.h"
  14. #include "net/log/net_log_source.h"
  15. #include "net/quic/address_utils.h"
  16. #include "net/socket/udp_server_socket.h"
  17. #include "net/third_party/quiche/src/quiche/quic/core/crypto/crypto_handshake.h"
  18. #include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_random.h"
  19. #include "net/third_party/quiche/src/quiche/quic/core/quic_crypto_stream.h"
  20. #include "net/third_party/quiche/src/quiche/quic/core/quic_data_reader.h"
  21. #include "net/third_party/quiche/src/quiche/quic/core/quic_packets.h"
  22. #include "net/third_party/quiche/src/quiche/quic/tools/quic_simple_dispatcher.h"
  23. #include "net/tools/quic/quic_simple_server_packet_writer.h"
  24. #include "net/tools/quic/quic_simple_server_session_helper.h"
  25. #include "net/tools/quic/quic_simple_server_socket.h"
  26. namespace net {
  27. namespace {
  28. const char kSourceAddressTokenSecret[] = "secret";
  29. const size_t kNumSessionsToCreatePerSocketEvent = 16;
  30. // Allocate some extra space so we can send an error if the client goes over
  31. // the limit.
  32. const int kReadBufferSize = 2 * quic::kMaxIncomingPacketSize;
  33. } // namespace
  34. QuicSimpleServer::QuicSimpleServer(
  35. std::unique_ptr<quic::ProofSource> proof_source,
  36. const quic::QuicConfig& config,
  37. const quic::QuicCryptoServerConfig::ConfigOptions& crypto_config_options,
  38. const quic::ParsedQuicVersionVector& supported_versions,
  39. quic::QuicSimpleServerBackend* quic_simple_server_backend)
  40. : version_manager_(supported_versions),
  41. helper_(
  42. new QuicChromiumConnectionHelper(&clock_,
  43. quic::QuicRandom::GetInstance())),
  44. alarm_factory_(new QuicChromiumAlarmFactory(
  45. base::ThreadTaskRunnerHandle::Get().get(),
  46. &clock_)),
  47. config_(config),
  48. crypto_config_options_(crypto_config_options),
  49. crypto_config_(kSourceAddressTokenSecret,
  50. quic::QuicRandom::GetInstance(),
  51. std::move(proof_source),
  52. quic::KeyExchangeSource::Default()),
  53. read_buffer_(base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize)),
  54. quic_simple_server_backend_(quic_simple_server_backend) {
  55. DCHECK(quic_simple_server_backend);
  56. Initialize();
  57. }
  58. void QuicSimpleServer::Initialize() {
  59. #if MMSG_MORE
  60. use_recvmmsg_ = true;
  61. #endif
  62. // If an initial flow control window has not explicitly been set, then use a
  63. // sensible value for a server: 1 MB for session, 64 KB for each stream.
  64. const uint32_t kInitialSessionFlowControlWindow = 1 * 1024 * 1024; // 1 MB
  65. const uint32_t kInitialStreamFlowControlWindow = 64 * 1024; // 64 KB
  66. if (config_.GetInitialStreamFlowControlWindowToSend() ==
  67. quic::kMinimumFlowControlSendWindow) {
  68. config_.SetInitialStreamFlowControlWindowToSend(
  69. kInitialStreamFlowControlWindow);
  70. }
  71. if (config_.GetInitialSessionFlowControlWindowToSend() ==
  72. quic::kMinimumFlowControlSendWindow) {
  73. config_.SetInitialSessionFlowControlWindowToSend(
  74. kInitialSessionFlowControlWindow);
  75. }
  76. std::unique_ptr<quic::CryptoHandshakeMessage> scfg(
  77. crypto_config_.AddDefaultConfig(helper_->GetRandomGenerator(),
  78. helper_->GetClock(),
  79. crypto_config_options_));
  80. }
  81. QuicSimpleServer::~QuicSimpleServer() = default;
  82. bool QuicSimpleServer::CreateUDPSocketAndListen(
  83. const quic::QuicSocketAddress& address) {
  84. return Listen(ToIPEndPoint(address));
  85. }
  86. void QuicSimpleServer::HandleEventsForever() {
  87. base::RunLoop().Run();
  88. }
  89. bool QuicSimpleServer::Listen(const IPEndPoint& address) {
  90. socket_ = CreateQuicSimpleServerSocket(address, &server_address_);
  91. if (socket_ == nullptr)
  92. return false;
  93. dispatcher_ = std::make_unique<quic::QuicSimpleDispatcher>(
  94. &config_, &crypto_config_, &version_manager_,
  95. std::unique_ptr<quic::QuicConnectionHelperInterface>(helper_),
  96. std::make_unique<QuicSimpleServerSessionHelper>(
  97. quic::QuicRandom::GetInstance()),
  98. std::unique_ptr<quic::QuicAlarmFactory>(alarm_factory_),
  99. quic_simple_server_backend_, quic::kQuicDefaultConnectionIdLength);
  100. QuicSimpleServerPacketWriter* writer =
  101. new QuicSimpleServerPacketWriter(socket_.get(), dispatcher_.get());
  102. dispatcher_->InitializeWithWriter(writer);
  103. StartReading();
  104. return true;
  105. }
  106. void QuicSimpleServer::Shutdown() {
  107. DVLOG(1) << "QuicSimpleServer is shutting down";
  108. // Before we shut down the epoll server, give all active sessions a chance to
  109. // notify clients that they're closing.
  110. dispatcher_->Shutdown();
  111. if (!socket_) {
  112. return;
  113. }
  114. socket_->Close();
  115. socket_.reset();
  116. }
  117. void QuicSimpleServer::StartReading() {
  118. if (synchronous_read_count_ == 0) {
  119. // Only process buffered packets once per message loop.
  120. dispatcher_->ProcessBufferedChlos(kNumSessionsToCreatePerSocketEvent);
  121. }
  122. if (read_pending_) {
  123. return;
  124. }
  125. read_pending_ = true;
  126. int result = socket_->RecvFrom(
  127. read_buffer_.get(), read_buffer_->size(), &client_address_,
  128. base::BindOnce(&QuicSimpleServer::OnReadComplete,
  129. base::Unretained(this)));
  130. if (result == ERR_IO_PENDING) {
  131. synchronous_read_count_ = 0;
  132. if (dispatcher_->HasChlosBuffered()) {
  133. // No more packets to read, so yield before processing buffered packets.
  134. base::ThreadTaskRunnerHandle::Get()->PostTask(
  135. FROM_HERE, base::BindOnce(&QuicSimpleServer::StartReading,
  136. weak_factory_.GetWeakPtr()));
  137. }
  138. return;
  139. }
  140. if (++synchronous_read_count_ > 32) {
  141. synchronous_read_count_ = 0;
  142. // Schedule the processing through the message loop to 1) prevent infinite
  143. // recursion and 2) avoid blocking the thread for too long.
  144. base::ThreadTaskRunnerHandle::Get()->PostTask(
  145. FROM_HERE, base::BindOnce(&QuicSimpleServer::OnReadComplete,
  146. weak_factory_.GetWeakPtr(), result));
  147. } else {
  148. OnReadComplete(result);
  149. }
  150. }
  151. void QuicSimpleServer::OnReadComplete(int result) {
  152. read_pending_ = false;
  153. if (result > 0) {
  154. quic::QuicReceivedPacket packet(read_buffer_->data(), result,
  155. helper_->GetClock()->Now(), false);
  156. dispatcher_->ProcessPacket(ToQuicSocketAddress(server_address_),
  157. ToQuicSocketAddress(client_address_), packet);
  158. } else {
  159. LOG(ERROR) << "QuicSimpleServer read failed: " << ErrorToString(result);
  160. // Do not act on ERR_MSG_TOO_BIG as that indicates that we received a UDP
  161. // packet whose payload is larger than our receive buffer. Do not act on 0
  162. // as that indicates that we received a UDP packet with an empty payload.
  163. // In both cases, the socket should still be usable.
  164. // Also do not act on ERR_CONNECTION_RESET as this is happening when the
  165. // network service restarts on Windows.
  166. if (result != ERR_MSG_TOO_BIG && result != ERR_CONNECTION_RESET &&
  167. result != 0) {
  168. Shutdown();
  169. return;
  170. }
  171. }
  172. StartReading();
  173. }
  174. } // namespace net