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