We started redesigning GpuMemoryBuffer interface to handle multiple buffers [0].
[chromium-blink-merge.git] / net / tools / quic / quic_simple_server.cc
blobbbdb823fcbfa103289e972b6e60c6325f860da90
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/tools/quic/quic_simple_server.h"
7 #include <string.h>
9 #include "net/base/ip_endpoint.h"
10 #include "net/base/net_errors.h"
11 #include "net/quic/crypto/crypto_handshake.h"
12 #include "net/quic/crypto/quic_random.h"
13 #include "net/quic/quic_crypto_stream.h"
14 #include "net/quic/quic_data_reader.h"
15 #include "net/quic/quic_protocol.h"
16 #include "net/tools/quic/quic_dispatcher.h"
17 #include "net/tools/quic/quic_simple_per_connection_packet_writer.h"
18 #include "net/tools/quic/quic_simple_server_packet_writer.h"
19 #include "net/udp/udp_server_socket.h"
21 namespace net {
22 namespace tools {
24 namespace {
26 const char kSourceAddressTokenSecret[] = "secret";
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;
32 // A packet writer factory which wraps a shared QuicSimpleServerPacketWriter
33 // inside of a QuicPerConnectionPacketWriter. Instead of checking that
34 // the shared_writer is the expected writer, this could instead cast
35 // from QuicPacketWriter to QuicSimpleServerPacketWriter.
36 class CustomPacketWriterFactory : public QuicDispatcher::PacketWriterFactory {
37 public:
38 ~CustomPacketWriterFactory() override {}
40 QuicPacketWriter* Create(QuicPacketWriter* writer,
41 QuicConnection* connection) override {
42 if (writer == nullptr) {
43 LOG(DFATAL) << "shared_writer not initialized";
44 return nullptr;
46 if (writer != shared_writer_) {
47 LOG(DFATAL) << "writer mismatch";
48 return nullptr;
50 return new QuicSimplePerConnectionPacketWriter(shared_writer_, connection);
53 void set_shared_writer(QuicSimpleServerPacketWriter* shared_writer) {
54 shared_writer_ = shared_writer;
57 private:
58 QuicSimpleServerPacketWriter* shared_writer_; // Not owned.
61 } // namespace
63 QuicSimpleServer::QuicSimpleServer(const QuicConfig& config,
64 const QuicVersionVector& supported_versions)
65 : helper_(base::MessageLoop::current()->message_loop_proxy().get(),
66 &clock_,
67 QuicRandom::GetInstance()),
68 config_(config),
69 crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance()),
70 supported_versions_(supported_versions),
71 read_pending_(false),
72 synchronous_read_count_(0),
73 read_buffer_(new IOBufferWithSize(kReadBufferSize)),
74 weak_factory_(this) {
75 Initialize();
78 void QuicSimpleServer::Initialize() {
79 #if MMSG_MORE
80 use_recvmmsg_ = true;
81 #endif
83 // If an initial flow control window has not explicitly been set, then use a
84 // sensible value for a server: 1 MB for session, 64 KB for each stream.
85 const uint32 kInitialSessionFlowControlWindow = 1 * 1024 * 1024; // 1 MB
86 const uint32 kInitialStreamFlowControlWindow = 64 * 1024; // 64 KB
87 if (config_.GetInitialStreamFlowControlWindowToSend() ==
88 kMinimumFlowControlSendWindow) {
89 config_.SetInitialStreamFlowControlWindowToSend(
90 kInitialStreamFlowControlWindow);
92 if (config_.GetInitialSessionFlowControlWindowToSend() ==
93 kMinimumFlowControlSendWindow) {
94 config_.SetInitialSessionFlowControlWindowToSend(
95 kInitialSessionFlowControlWindow);
98 scoped_ptr<CryptoHandshakeMessage> scfg(
99 crypto_config_.AddDefaultConfig(
100 helper_.GetRandomGenerator(), helper_.GetClock(),
101 QuicCryptoServerConfig::ConfigOptions()));
104 QuicSimpleServer::~QuicSimpleServer() {
107 int QuicSimpleServer::Listen(const IPEndPoint& address) {
108 scoped_ptr<UDPServerSocket> socket(
109 new UDPServerSocket(&net_log_, NetLog::Source()));
111 socket->AllowAddressReuse();
113 int rc = socket->Listen(address);
114 if (rc < 0) {
115 LOG(ERROR) << "Listen() failed: " << ErrorToString(rc);
116 return rc;
119 // These send and receive buffer sizes are sized for a single connection,
120 // because the default usage of QuicSimpleServer is as a test server with
121 // one or two clients. Adjust higher for use with many clients.
122 rc = socket->SetReceiveBufferSize(
123 static_cast<int32>(kDefaultSocketReceiveBuffer));
124 if (rc < 0) {
125 LOG(ERROR) << "SetReceiveBufferSize() failed: " << ErrorToString(rc);
126 return rc;
129 rc = socket->SetSendBufferSize(20 * kMaxPacketSize);
130 if (rc < 0) {
131 LOG(ERROR) << "SetSendBufferSize() failed: " << ErrorToString(rc);
132 return rc;
135 rc = socket->GetLocalAddress(&server_address_);
136 if (rc < 0) {
137 LOG(ERROR) << "GetLocalAddress() failed: " << ErrorToString(rc);
138 return rc;
141 DVLOG(1) << "Listening on " << server_address_.ToString();
143 socket_.swap(socket);
145 CustomPacketWriterFactory* factory = new CustomPacketWriterFactory();
146 dispatcher_.reset(
147 new QuicDispatcher(config_,
148 &crypto_config_,
149 supported_versions_,
150 factory,
151 &helper_));
152 QuicSimpleServerPacketWriter* writer = new QuicSimpleServerPacketWriter(
153 socket_.get(),
154 dispatcher_.get());
155 factory->set_shared_writer(writer);
156 dispatcher_->InitializeWithWriter(writer);
158 StartReading();
160 return OK;
163 void QuicSimpleServer::Shutdown() {
164 // Before we shut down the epoll server, give all active sessions a chance to
165 // notify clients that they're closing.
166 dispatcher_->Shutdown();
168 socket_->Close();
169 socket_.reset();
172 void QuicSimpleServer::StartReading() {
173 if (read_pending_) {
174 return;
176 read_pending_ = true;
178 int result = socket_->RecvFrom(
179 read_buffer_.get(),
180 read_buffer_->size(),
181 &client_address_,
182 base::Bind(&QuicSimpleServer::OnReadComplete, base::Unretained(this)));
184 if (result == ERR_IO_PENDING) {
185 synchronous_read_count_ = 0;
186 return;
189 if (++synchronous_read_count_ > 32) {
190 synchronous_read_count_ = 0;
191 // Schedule the processing through the message loop to 1) prevent infinite
192 // recursion and 2) avoid blocking the thread for too long.
193 base::MessageLoop::current()->PostTask(
194 FROM_HERE,
195 base::Bind(&QuicSimpleServer::OnReadComplete,
196 weak_factory_.GetWeakPtr(),
197 result));
198 } else {
199 OnReadComplete(result);
203 void QuicSimpleServer::OnReadComplete(int result) {
204 read_pending_ = false;
205 if (result == 0)
206 result = ERR_CONNECTION_CLOSED;
208 if (result < 0) {
209 LOG(ERROR) << "QuicSimpleServer read failed: " << ErrorToString(result);
210 Shutdown();
211 return;
214 QuicEncryptedPacket packet(read_buffer_->data(), result, false);
215 dispatcher_->ProcessPacket(server_address_, client_address_, packet);
217 StartReading();
220 } // namespace tools
221 } // namespace net