• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
22 namespace net {
23 
24 namespace {
25 
26 const char kSourceAddressTokenSecret[] = "secret";
27 
28 // Allocate some extra space so we can send an error if the client goes over
29 // the limit.
30 const int kReadBufferSize = 2 * kMaxPacketSize;
31 
32 const uint32 kServerInitialFlowControlWindow = 100 * kMaxPacketSize;
33 
34 } // namespace
35 
QuicServer(const QuicConfig & config,const QuicVersionVector & supported_versions)36 QuicServer::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 
Initialize()51 void 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 
~QuicServer()63 QuicServer::~QuicServer() {
64 }
65 
Listen(const IPEndPoint & address)66 int 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 
Shutdown()119 void 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 
StartReading()128 void 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 
OnReadComplete(int result)159 void 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