OLD | NEW |
| (Empty) |
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/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_per_connection_packet_writer.h" | |
16 #include "net/quic/quic_protocol.h" | |
17 #include "net/quic/quic_server_packet_writer.h" | |
18 #include "net/tools/quic/quic_dispatcher.h" | |
19 #include "net/udp/udp_server_socket.h" | |
20 | |
21 namespace net { | |
22 | |
23 using tools::QuicDispatcher; | |
24 | |
25 namespace { | |
26 | |
27 const char kSourceAddressTokenSecret[] = "secret"; | |
28 | |
29 // Allocate some extra space so we can send an error if the client goes over | |
30 // the limit. | |
31 const int kReadBufferSize = 2 * kMaxPacketSize; | |
32 | |
33 // A packet writer factory which wraps a shared QuicServerPacketWriter | |
34 // inside of a QuicPerConnectionPacketWriter. Instead of checking that | |
35 // the shared_writer is the expected writer, this could instead cast | |
36 // from QuicPacketWriter to QuicServerPacketWriter. | |
37 class CustomPacketWriterFactory : public QuicDispatcher::PacketWriterFactory { | |
38 public: | |
39 ~CustomPacketWriterFactory() override {} | |
40 | |
41 QuicPacketWriter* Create(QuicPacketWriter* writer, | |
42 QuicConnection* connection) override { | |
43 if (writer == nullptr) { | |
44 LOG(DFATAL) << "shared_writer not initialized"; | |
45 return nullptr; | |
46 } | |
47 if (writer != shared_writer_) { | |
48 LOG(DFATAL) << "writer mismatch"; | |
49 return nullptr; | |
50 } | |
51 return new QuicPerConnectionPacketWriter(shared_writer_, connection); | |
52 } | |
53 | |
54 void set_shared_writer(QuicServerPacketWriter* shared_writer) { | |
55 shared_writer_ = shared_writer; | |
56 } | |
57 | |
58 private: | |
59 QuicServerPacketWriter* shared_writer_; // Not owned. | |
60 }; | |
61 | |
62 } // namespace | |
63 | |
64 QuicServer::QuicServer(const QuicConfig& config, | |
65 const QuicVersionVector& supported_versions) | |
66 : helper_(base::MessageLoop::current()->message_loop_proxy().get(), | |
67 &clock_, | |
68 QuicRandom::GetInstance()), | |
69 config_(config), | |
70 crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance()), | |
71 supported_versions_(supported_versions), | |
72 read_pending_(false), | |
73 synchronous_read_count_(0), | |
74 read_buffer_(new IOBufferWithSize(kReadBufferSize)), | |
75 weak_factory_(this) { | |
76 Initialize(); | |
77 } | |
78 | |
79 void QuicServer::Initialize() { | |
80 #if MMSG_MORE | |
81 use_recvmmsg_ = true; | |
82 #endif | |
83 | |
84 // If an initial flow control window has not explicitly been set, then use a | |
85 // sensible value for a server: 1 MB for session, 64 KB for each stream. | |
86 const uint32 kInitialSessionFlowControlWindow = 1 * 1024 * 1024; // 1 MB | |
87 const uint32 kInitialStreamFlowControlWindow = 64 * 1024; // 64 KB | |
88 if (config_.GetInitialStreamFlowControlWindowToSend() == | |
89 kMinimumFlowControlSendWindow) { | |
90 config_.SetInitialStreamFlowControlWindowToSend( | |
91 kInitialStreamFlowControlWindow); | |
92 } | |
93 if (config_.GetInitialSessionFlowControlWindowToSend() == | |
94 kMinimumFlowControlSendWindow) { | |
95 config_.SetInitialSessionFlowControlWindowToSend( | |
96 kInitialSessionFlowControlWindow); | |
97 } | |
98 | |
99 scoped_ptr<CryptoHandshakeMessage> scfg( | |
100 crypto_config_.AddDefaultConfig( | |
101 helper_.GetRandomGenerator(), helper_.GetClock(), | |
102 QuicCryptoServerConfig::ConfigOptions())); | |
103 } | |
104 | |
105 QuicServer::~QuicServer() { | |
106 } | |
107 | |
108 int QuicServer::Listen(const IPEndPoint& address) { | |
109 scoped_ptr<UDPServerSocket> socket( | |
110 new UDPServerSocket(&net_log_, NetLog::Source())); | |
111 | |
112 socket->AllowAddressReuse(); | |
113 | |
114 int rc = socket->Listen(address); | |
115 if (rc < 0) { | |
116 LOG(ERROR) << "Listen() failed: " << ErrorToString(rc); | |
117 return rc; | |
118 } | |
119 | |
120 // These send and receive buffer sizes are sized for a single connection, | |
121 // because the default usage of QuicServer is as a test server with one or | |
122 // two clients. Adjust higher for use with many clients. | |
123 rc = socket->SetReceiveBufferSize( | |
124 static_cast<int32>(kDefaultSocketReceiveBuffer)); | |
125 if (rc < 0) { | |
126 LOG(ERROR) << "SetReceiveBufferSize() failed: " << ErrorToString(rc); | |
127 return rc; | |
128 } | |
129 | |
130 rc = socket->SetSendBufferSize(20 * kMaxPacketSize); | |
131 if (rc < 0) { | |
132 LOG(ERROR) << "SetSendBufferSize() failed: " << ErrorToString(rc); | |
133 return rc; | |
134 } | |
135 | |
136 rc = socket->GetLocalAddress(&server_address_); | |
137 if (rc < 0) { | |
138 LOG(ERROR) << "GetLocalAddress() failed: " << ErrorToString(rc); | |
139 return rc; | |
140 } | |
141 | |
142 DVLOG(1) << "Listening on " << server_address_.ToString(); | |
143 | |
144 socket_.swap(socket); | |
145 | |
146 CustomPacketWriterFactory* factory = new CustomPacketWriterFactory(); | |
147 dispatcher_.reset( | |
148 new QuicDispatcher(config_, | |
149 crypto_config_, | |
150 supported_versions_, | |
151 factory, | |
152 &helper_)); | |
153 QuicServerPacketWriter* writer = new QuicServerPacketWriter( | |
154 socket_.get(), | |
155 dispatcher_.get()); | |
156 factory->set_shared_writer(writer); | |
157 dispatcher_->InitializeWithWriter(writer); | |
158 | |
159 StartReading(); | |
160 | |
161 return OK; | |
162 } | |
163 | |
164 void QuicServer::Shutdown() { | |
165 // Before we shut down the epoll server, give all active sessions a chance to | |
166 // notify clients that they're closing. | |
167 dispatcher_->Shutdown(); | |
168 | |
169 socket_->Close(); | |
170 socket_.reset(); | |
171 } | |
172 | |
173 void QuicServer::StartReading() { | |
174 if (read_pending_) { | |
175 return; | |
176 } | |
177 read_pending_ = true; | |
178 | |
179 int result = socket_->RecvFrom( | |
180 read_buffer_.get(), | |
181 read_buffer_->size(), | |
182 &client_address_, | |
183 base::Bind(&QuicServer::OnReadComplete, base::Unretained(this))); | |
184 | |
185 if (result == ERR_IO_PENDING) { | |
186 synchronous_read_count_ = 0; | |
187 return; | |
188 } | |
189 | |
190 if (++synchronous_read_count_ > 32) { | |
191 synchronous_read_count_ = 0; | |
192 // Schedule the processing through the message loop to 1) prevent infinite | |
193 // recursion and 2) avoid blocking the thread for too long. | |
194 base::MessageLoop::current()->PostTask( | |
195 FROM_HERE, | |
196 base::Bind(&QuicServer::OnReadComplete, | |
197 weak_factory_.GetWeakPtr(), | |
198 result)); | |
199 } else { | |
200 OnReadComplete(result); | |
201 } | |
202 } | |
203 | |
204 void QuicServer::OnReadComplete(int result) { | |
205 read_pending_ = false; | |
206 if (result == 0) | |
207 result = ERR_CONNECTION_CLOSED; | |
208 | |
209 if (result < 0) { | |
210 LOG(ERROR) << "QuicServer read failed: " << ErrorToString(result); | |
211 Shutdown(); | |
212 return; | |
213 } | |
214 | |
215 QuicEncryptedPacket packet(read_buffer_->data(), result, false); | |
216 dispatcher_->ProcessPacket(server_address_, client_address_, packet); | |
217 | |
218 StartReading(); | |
219 } | |
220 | |
221 } // namespace net | |
OLD | NEW |