123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205 |
- // Copyright 2014 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_simple_server.h"
- #include <string.h>
- #include <memory>
- #include "base/bind.h"
- #include "base/location.h"
- #include "base/run_loop.h"
- #include "base/task/single_thread_task_runner.h"
- #include "base/threading/thread_task_runner_handle.h"
- #include "net/base/ip_endpoint.h"
- #include "net/base/net_errors.h"
- #include "net/log/net_log_source.h"
- #include "net/quic/address_utils.h"
- #include "net/socket/udp_server_socket.h"
- #include "net/third_party/quiche/src/quiche/quic/core/crypto/crypto_handshake.h"
- #include "net/third_party/quiche/src/quiche/quic/core/crypto/quic_random.h"
- #include "net/third_party/quiche/src/quiche/quic/core/quic_crypto_stream.h"
- #include "net/third_party/quiche/src/quiche/quic/core/quic_data_reader.h"
- #include "net/third_party/quiche/src/quiche/quic/core/quic_packets.h"
- #include "net/third_party/quiche/src/quiche/quic/tools/quic_simple_dispatcher.h"
- #include "net/tools/quic/quic_simple_server_packet_writer.h"
- #include "net/tools/quic/quic_simple_server_session_helper.h"
- #include "net/tools/quic/quic_simple_server_socket.h"
- namespace net {
- namespace {
- const char kSourceAddressTokenSecret[] = "secret";
- const size_t kNumSessionsToCreatePerSocketEvent = 16;
- // Allocate some extra space so we can send an error if the client goes over
- // the limit.
- const int kReadBufferSize = 2 * quic::kMaxIncomingPacketSize;
- } // namespace
- QuicSimpleServer::QuicSimpleServer(
- std::unique_ptr<quic::ProofSource> proof_source,
- const quic::QuicConfig& config,
- const quic::QuicCryptoServerConfig::ConfigOptions& crypto_config_options,
- const quic::ParsedQuicVersionVector& supported_versions,
- quic::QuicSimpleServerBackend* quic_simple_server_backend)
- : version_manager_(supported_versions),
- helper_(
- new QuicChromiumConnectionHelper(&clock_,
- quic::QuicRandom::GetInstance())),
- alarm_factory_(new QuicChromiumAlarmFactory(
- base::ThreadTaskRunnerHandle::Get().get(),
- &clock_)),
- config_(config),
- crypto_config_options_(crypto_config_options),
- crypto_config_(kSourceAddressTokenSecret,
- quic::QuicRandom::GetInstance(),
- std::move(proof_source),
- quic::KeyExchangeSource::Default()),
- read_buffer_(base::MakeRefCounted<IOBufferWithSize>(kReadBufferSize)),
- quic_simple_server_backend_(quic_simple_server_backend) {
- DCHECK(quic_simple_server_backend);
- Initialize();
- }
- void QuicSimpleServer::Initialize() {
- #if MMSG_MORE
- use_recvmmsg_ = true;
- #endif
- // If an initial flow control window has not explicitly been set, then use a
- // sensible value for a server: 1 MB for session, 64 KB for each stream.
- const uint32_t kInitialSessionFlowControlWindow = 1 * 1024 * 1024; // 1 MB
- const uint32_t kInitialStreamFlowControlWindow = 64 * 1024; // 64 KB
- if (config_.GetInitialStreamFlowControlWindowToSend() ==
- quic::kMinimumFlowControlSendWindow) {
- config_.SetInitialStreamFlowControlWindowToSend(
- kInitialStreamFlowControlWindow);
- }
- if (config_.GetInitialSessionFlowControlWindowToSend() ==
- quic::kMinimumFlowControlSendWindow) {
- config_.SetInitialSessionFlowControlWindowToSend(
- kInitialSessionFlowControlWindow);
- }
- std::unique_ptr<quic::CryptoHandshakeMessage> scfg(
- crypto_config_.AddDefaultConfig(helper_->GetRandomGenerator(),
- helper_->GetClock(),
- crypto_config_options_));
- }
- QuicSimpleServer::~QuicSimpleServer() = default;
- bool QuicSimpleServer::CreateUDPSocketAndListen(
- const quic::QuicSocketAddress& address) {
- return Listen(ToIPEndPoint(address));
- }
- void QuicSimpleServer::HandleEventsForever() {
- base::RunLoop().Run();
- }
- bool QuicSimpleServer::Listen(const IPEndPoint& address) {
- socket_ = CreateQuicSimpleServerSocket(address, &server_address_);
- if (socket_ == nullptr)
- return false;
- dispatcher_ = std::make_unique<quic::QuicSimpleDispatcher>(
- &config_, &crypto_config_, &version_manager_,
- std::unique_ptr<quic::QuicConnectionHelperInterface>(helper_),
- std::make_unique<QuicSimpleServerSessionHelper>(
- quic::QuicRandom::GetInstance()),
- std::unique_ptr<quic::QuicAlarmFactory>(alarm_factory_),
- quic_simple_server_backend_, quic::kQuicDefaultConnectionIdLength);
- QuicSimpleServerPacketWriter* writer =
- new QuicSimpleServerPacketWriter(socket_.get(), dispatcher_.get());
- dispatcher_->InitializeWithWriter(writer);
- StartReading();
- return true;
- }
- void QuicSimpleServer::Shutdown() {
- DVLOG(1) << "QuicSimpleServer is shutting down";
- // Before we shut down the epoll server, give all active sessions a chance to
- // notify clients that they're closing.
- dispatcher_->Shutdown();
- if (!socket_) {
- return;
- }
- socket_->Close();
- socket_.reset();
- }
- void QuicSimpleServer::StartReading() {
- if (synchronous_read_count_ == 0) {
- // Only process buffered packets once per message loop.
- dispatcher_->ProcessBufferedChlos(kNumSessionsToCreatePerSocketEvent);
- }
- if (read_pending_) {
- return;
- }
- read_pending_ = true;
- int result = socket_->RecvFrom(
- read_buffer_.get(), read_buffer_->size(), &client_address_,
- base::BindOnce(&QuicSimpleServer::OnReadComplete,
- base::Unretained(this)));
- if (result == ERR_IO_PENDING) {
- synchronous_read_count_ = 0;
- if (dispatcher_->HasChlosBuffered()) {
- // No more packets to read, so yield before processing buffered packets.
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&QuicSimpleServer::StartReading,
- weak_factory_.GetWeakPtr()));
- }
- return;
- }
- if (++synchronous_read_count_ > 32) {
- synchronous_read_count_ = 0;
- // Schedule the processing through the message loop to 1) prevent infinite
- // recursion and 2) avoid blocking the thread for too long.
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, base::BindOnce(&QuicSimpleServer::OnReadComplete,
- weak_factory_.GetWeakPtr(), result));
- } else {
- OnReadComplete(result);
- }
- }
- void QuicSimpleServer::OnReadComplete(int result) {
- read_pending_ = false;
- if (result > 0) {
- quic::QuicReceivedPacket packet(read_buffer_->data(), result,
- helper_->GetClock()->Now(), false);
- dispatcher_->ProcessPacket(ToQuicSocketAddress(server_address_),
- ToQuicSocketAddress(client_address_), packet);
- } else {
- LOG(ERROR) << "QuicSimpleServer read failed: " << ErrorToString(result);
- // Do not act on ERR_MSG_TOO_BIG as that indicates that we received a UDP
- // packet whose payload is larger than our receive buffer. Do not act on 0
- // as that indicates that we received a UDP packet with an empty payload.
- // In both cases, the socket should still be usable.
- // Also do not act on ERR_CONNECTION_RESET as this is happening when the
- // network service restarts on Windows.
- if (result != ERR_MSG_TOO_BIG && result != ERR_CONNECTION_RESET &&
- result != 0) {
- Shutdown();
- return;
- }
- }
- StartReading();
- }
- } // namespace net
|