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.
5 #include "net/quic/quic_server.h"
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"
26 const char kSourceAddressTokenSecret
[] = "secret";
28 // Allocate some extra space so we can send an error if the client goes over
30 const int kReadBufferSize
= 2 * kMaxPacketSize
;
32 const uint32 kServerInitialFlowControlWindow
= 100 * kMaxPacketSize
;
36 QuicServer::QuicServer(const QuicConfig
& config
,
37 const QuicVersionVector
& supported_versions
)
38 : helper_(base::MessageLoop::current()->message_loop_proxy().get(),
40 QuicRandom::GetInstance()),
42 crypto_config_(kSourceAddressTokenSecret
, QuicRandom::GetInstance()),
43 supported_versions_(supported_versions
),
45 synchronous_read_count_(0),
46 read_buffer_(new IOBufferWithSize(kReadBufferSize
)),
51 void QuicServer::Initialize() {
52 // Initialize the in memory cache now.
53 QuicInMemoryCache::GetInstance();
55 scoped_ptr
<CryptoHandshakeMessage
> scfg(
56 crypto_config_
.AddDefaultConfig(helper_
.GetRandomGenerator(),
58 QuicCryptoServerConfig::ConfigOptions()));
60 config_
.SetInitialCongestionWindowToSend(kServerInitialFlowControlWindow
);
63 QuicServer::~QuicServer() {
66 int QuicServer::Listen(const IPEndPoint
& address
) {
67 scoped_ptr
<UDPServerSocket
> socket(
68 new UDPServerSocket(&net_log_
, NetLog::Source()));
70 socket
->AllowAddressReuse();
72 int rc
= socket
->Listen(address
);
74 LOG(ERROR
) << "Listen() failed: " << ErrorToString(rc
);
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
);
83 LOG(ERROR
) << "SetReceiveBufferSize() failed: " << ErrorToString(rc
);
87 rc
= socket
->SetSendBufferSize(20 * kMaxPacketSize
);
89 LOG(ERROR
) << "SetSendBufferSize() failed: " << ErrorToString(rc
);
93 rc
= socket
->GetLocalAddress(&server_address_
);
95 LOG(ERROR
) << "GetLocalAddress() failed: " << ErrorToString(rc
);
99 DVLOG(1) << "Listening on " << server_address_
.ToString();
101 socket_
.swap(socket
);
104 new QuicDispatcher(config_
,
107 new QuicDispatcher::DefaultPacketWriterFactory(),
109 QuicServerPacketWriter
* writer
= new QuicServerPacketWriter(
112 dispatcher_
->Initialize(writer
);
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();
128 void QuicServer::StartReading() {
132 read_pending_
= true;
134 int result
= socket_
->RecvFrom(
136 read_buffer_
->size(),
138 base::Bind(&QuicServer::OnReadComplete
, base::Unretained(this)));
140 if (result
== ERR_IO_PENDING
) {
141 synchronous_read_count_
= 0;
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(
151 base::Bind(&QuicServer::OnReadComplete
,
152 weak_factory_
.GetWeakPtr(),
155 OnReadComplete(result
);
159 void QuicServer::OnReadComplete(int result
) {
160 read_pending_
= false;
162 result
= ERR_CONNECTION_CLOSED
;
165 LOG(ERROR
) << "QuicServer read failed: " << ErrorToString(result
);
170 QuicEncryptedPacket
packet(read_buffer_
->data(), result
, false);
171 dispatcher_
->ProcessPacket(server_address_
, client_address_
, packet
);