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 5#include "net/quic/quic_server.h" 6 7#include <string.h> 8 9#include "net/base/ip_endpoint.h" 10#include "net/base/net_errors.h" 11#include "net/quic/congestion_control/tcp_receiver.h" 12#include "net/quic/crypto/crypto_handshake.h" 13#include "net/quic/crypto/quic_random.h" 14#include "net/quic/quic_crypto_stream.h" 15#include "net/quic/quic_data_reader.h" 16#include "net/quic/quic_dispatcher.h" 17#include "net/quic/quic_in_memory_cache.h" 18#include "net/quic/quic_protocol.h" 19#include "net/quic/quic_server_packet_writer.h" 20#include "net/udp/udp_server_socket.h" 21 22namespace net { 23 24namespace { 25 26const char kSourceAddressTokenSecret[] = "secret"; 27 28// Allocate some extra space so we can send an error if the client goes over 29// the limit. 30const int kReadBufferSize = 2 * kMaxPacketSize; 31 32const uint32 kServerInitialFlowControlWindow = 100 * kMaxPacketSize; 33 34} // namespace 35 36QuicServer::QuicServer(const QuicConfig& config, 37 const QuicVersionVector& supported_versions) 38 : helper_(base::MessageLoop::current()->message_loop_proxy().get(), 39 &clock_, 40 QuicRandom::GetInstance()), 41 config_(config), 42 crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance()), 43 supported_versions_(supported_versions), 44 read_pending_(false), 45 synchronous_read_count_(0), 46 read_buffer_(new IOBufferWithSize(kReadBufferSize)), 47 weak_factory_(this) { 48 Initialize(); 49} 50 51void QuicServer::Initialize() { 52 // Initialize the in memory cache now. 53 QuicInMemoryCache::GetInstance(); 54 55 scoped_ptr<CryptoHandshakeMessage> scfg( 56 crypto_config_.AddDefaultConfig(helper_.GetRandomGenerator(), 57 helper_.GetClock(), 58 QuicCryptoServerConfig::ConfigOptions())); 59 60 config_.SetInitialCongestionWindowToSend(kServerInitialFlowControlWindow); 61} 62 63QuicServer::~QuicServer() { 64} 65 66int QuicServer::Listen(const IPEndPoint& address) { 67 scoped_ptr<UDPServerSocket> socket( 68 new UDPServerSocket(&net_log_, NetLog::Source())); 69 70 socket->AllowAddressReuse(); 71 72 int rc = socket->Listen(address); 73 if (rc < 0) { 74 LOG(ERROR) << "Listen() failed: " << ErrorToString(rc); 75 return rc; 76 } 77 78 // These send and receive buffer sizes are sized for a single connection, 79 // because the default usage of QuicServer is as a test server with one or 80 // two clients. Adjust higher for use with many clients. 81 rc = socket->SetReceiveBufferSize(TcpReceiver::kReceiveWindowTCP); 82 if (rc < 0) { 83 LOG(ERROR) << "SetReceiveBufferSize() failed: " << ErrorToString(rc); 84 return rc; 85 } 86 87 rc = socket->SetSendBufferSize(20 * kMaxPacketSize); 88 if (rc < 0) { 89 LOG(ERROR) << "SetSendBufferSize() failed: " << ErrorToString(rc); 90 return rc; 91 } 92 93 rc = socket->GetLocalAddress(&server_address_); 94 if (rc < 0) { 95 LOG(ERROR) << "GetLocalAddress() failed: " << ErrorToString(rc); 96 return rc; 97 } 98 99 DVLOG(1) << "Listening on " << server_address_.ToString(); 100 101 socket_.swap(socket); 102 103 dispatcher_.reset( 104 new QuicDispatcher(config_, 105 crypto_config_, 106 supported_versions_, 107 new QuicDispatcher::DefaultPacketWriterFactory(), 108 &helper_)); 109 QuicServerPacketWriter* writer = new QuicServerPacketWriter( 110 socket_.get(), 111 dispatcher_.get()); 112 dispatcher_->Initialize(writer); 113 114 StartReading(); 115 116 return OK; 117} 118 119void QuicServer::Shutdown() { 120 // Before we shut down the epoll server, give all active sessions a chance to 121 // notify clients that they're closing. 122 dispatcher_->Shutdown(); 123 124 socket_->Close(); 125 socket_.reset(); 126} 127 128void QuicServer::StartReading() { 129 if (read_pending_) { 130 return; 131 } 132 read_pending_ = true; 133 134 int result = socket_->RecvFrom( 135 read_buffer_.get(), 136 read_buffer_->size(), 137 &client_address_, 138 base::Bind(&QuicServer::OnReadComplete, base::Unretained(this))); 139 140 if (result == ERR_IO_PENDING) { 141 synchronous_read_count_ = 0; 142 return; 143 } 144 145 if (++synchronous_read_count_ > 32) { 146 synchronous_read_count_ = 0; 147 // Schedule the processing through the message loop to 1) prevent infinite 148 // recursion and 2) avoid blocking the thread for too long. 149 base::MessageLoop::current()->PostTask( 150 FROM_HERE, 151 base::Bind(&QuicServer::OnReadComplete, 152 weak_factory_.GetWeakPtr(), 153 result)); 154 } else { 155 OnReadComplete(result); 156 } 157} 158 159void QuicServer::OnReadComplete(int result) { 160 read_pending_ = false; 161 if (result == 0) 162 result = ERR_CONNECTION_CLOSED; 163 164 if (result < 0) { 165 LOG(ERROR) << "QuicServer read failed: " << ErrorToString(result); 166 Shutdown(); 167 return; 168 } 169 170 QuicEncryptedPacket packet(read_buffer_->data(), result, false); 171 dispatcher_->ProcessPacket(server_address_, client_address_, packet); 172 173 StartReading(); 174} 175 176} // namespace net 177