OLD | NEW |
---|---|
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
4 | 4 |
5 #include "net/tools/quic/quic_server.h" | 5 #include "net/quic/quic_server.h" |
6 | 6 |
7 #include <errno.h> | |
8 #include <features.h> | |
9 #include <netinet/in.h> | |
10 #include <string.h> | 7 #include <string.h> |
11 #include <sys/epoll.h> | |
12 #include <sys/socket.h> | |
13 | 8 |
14 #include "net/base/ip_endpoint.h" | 9 #include "net/base/ip_endpoint.h" |
10 #include "net/base/net_errors.h" | |
15 #include "net/quic/congestion_control/tcp_receiver.h" | 11 #include "net/quic/congestion_control/tcp_receiver.h" |
16 #include "net/quic/crypto/crypto_handshake.h" | 12 #include "net/quic/crypto/crypto_handshake.h" |
17 #include "net/quic/crypto/quic_random.h" | 13 #include "net/quic/crypto/quic_random.h" |
18 #include "net/quic/quic_clock.h" | |
19 #include "net/quic/quic_crypto_stream.h" | 14 #include "net/quic/quic_crypto_stream.h" |
20 #include "net/quic/quic_data_reader.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" | |
21 #include "net/quic/quic_protocol.h" | 18 #include "net/quic/quic_protocol.h" |
22 #include "net/tools/quic/quic_in_memory_cache.h" | 19 #include "net/quic/quic_server_packet_writer.h" |
23 #include "net/tools/quic/quic_socket_utils.h" | 20 #include "net/tools/quic/quic_socket_utils.h" |
24 | 21 #include "net/udp/udp_server_socket.h" |
25 #define MMSG_MORE 0 | |
26 | |
27 #ifndef SO_RXQ_OVFL | |
28 #define SO_RXQ_OVFL 40 | |
29 #endif | |
30 | |
31 const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET; | |
32 static const char kSourceAddressTokenSecret[] = "secret"; | |
33 const uint32 kServerInitialFlowControlWindow = 100 * net::kMaxPacketSize; | |
34 | 22 |
35 namespace net { | 23 namespace net { |
36 namespace tools { | |
37 | 24 |
38 QuicServer::QuicServer() | 25 namespace { |
39 : port_(0), | 26 |
40 fd_(-1), | 27 const char kSourceAddressTokenSecret[] = "secret"; |
41 packets_dropped_(0), | 28 |
42 overflow_supported_(false), | 29 // Allocate some extra space so we can send an error if the client goes over |
43 use_recvmmsg_(false), | 30 // the limit. |
44 crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance()), | 31 const int kReadBufferSize = 2 * kMaxPacketSize; |
45 supported_versions_(QuicSupportedVersions()) { | 32 |
46 // Use hardcoded crypto parameters for now. | 33 const int kServerInitialFlowControlWindow = 100 * kMaxPacketSize; |
47 config_.SetDefaults(); | 34 |
48 Initialize(); | |
49 } | 35 } |
wtc
2014/06/23 23:12:16
Add a "namespace" comment, like this:
} // names
dmziegler
2014/06/24 00:08:52
Done.
| |
50 | 36 |
51 QuicServer::QuicServer(const QuicConfig& config, | 37 QuicServer::QuicServer(const QuicConfig& config, |
52 const QuicVersionVector& supported_versions) | 38 const QuicVersionVector& supported_versions) |
53 : port_(0), | 39 : helper_(base::MessageLoop::current()->message_loop_proxy().get(), |
54 fd_(-1), | 40 &clock_, |
55 packets_dropped_(0), | 41 QuicRandom::GetInstance()), |
56 overflow_supported_(false), | |
57 use_recvmmsg_(false), | |
58 config_(config), | 42 config_(config), |
59 crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance()), | 43 crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance()), |
60 supported_versions_(supported_versions) { | 44 supported_versions_(supported_versions), |
45 read_pending_(false), | |
46 synchronous_read_count_(0), | |
47 read_buffer_(new IOBufferWithSize(kReadBufferSize)), | |
48 weak_factory_(this) { | |
61 Initialize(); | 49 Initialize(); |
62 } | 50 } |
63 | 51 |
64 void QuicServer::Initialize() { | 52 void QuicServer::Initialize() { |
65 #if MMSG_MORE | |
66 use_recvmmsg_ = true; | |
67 #endif | |
68 epoll_server_.set_timeout_in_us(50 * 1000); | |
69 // Initialize the in memory cache now. | 53 // Initialize the in memory cache now. |
70 QuicInMemoryCache::GetInstance(); | 54 QuicInMemoryCache::GetInstance(); |
71 | 55 |
72 QuicEpollClock clock(&epoll_server_); | 56 scoped_ptr<CryptoHandshakeMessage> scfg( |
57 crypto_config_.AddDefaultConfig(helper_.GetRandomGenerator(), | |
58 helper_.GetClock(), | |
59 QuicCryptoServerConfig::ConfigOptions())); | |
73 | 60 |
74 scoped_ptr<CryptoHandshakeMessage> scfg( | |
75 crypto_config_.AddDefaultConfig( | |
76 QuicRandom::GetInstance(), &clock, | |
77 QuicCryptoServerConfig::ConfigOptions())); | |
78 | |
79 // Set flow control options in the config. | |
80 config_.SetInitialCongestionWindowToSend(kServerInitialFlowControlWindow); | 61 config_.SetInitialCongestionWindowToSend(kServerInitialFlowControlWindow); |
81 } | 62 } |
82 | 63 |
83 QuicServer::~QuicServer() { | 64 QuicServer::~QuicServer() { |
84 } | 65 } |
85 | 66 |
86 bool QuicServer::Listen(const IPEndPoint& address) { | 67 int QuicServer::Listen(const IPEndPoint& address) { |
87 port_ = address.port(); | 68 scoped_ptr<UDPServerSocket> socket( |
88 int address_family = address.GetSockAddrFamily(); | 69 new UDPServerSocket(&net_log_, NetLog::Source())); |
89 fd_ = socket(address_family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP); | |
90 if (fd_ < 0) { | |
91 LOG(ERROR) << "CreateSocket() failed: " << strerror(errno); | |
92 return false; | |
93 } | |
94 | 70 |
95 int rc = QuicSocketUtils::SetGetAddressInfo(fd_, address_family); | 71 socket->AllowAddressReuse(); |
96 | 72 |
73 int rc = socket->Listen(address); | |
97 if (rc < 0) { | 74 if (rc < 0) { |
98 LOG(ERROR) << "IP detection not supported" << strerror(errno); | 75 LOG(ERROR) << "Listen() failed: " << ErrorToString(rc); |
99 return false; | 76 return rc; |
100 } | |
101 | |
102 int get_overflow = 1; | |
103 rc = setsockopt( | |
104 fd_, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow, sizeof(get_overflow)); | |
105 | |
106 if (rc < 0) { | |
107 DLOG(WARNING) << "Socket overflow detection not supported"; | |
108 } else { | |
109 overflow_supported_ = true; | |
110 } | 77 } |
111 | 78 |
112 // These send and receive buffer sizes are sized for a single connection, | 79 // These send and receive buffer sizes are sized for a single connection, |
113 // because the default usage of QuicServer is as a test server with one or | 80 // because the default usage of QuicServer is as a test server with one or |
114 // two clients. Adjust higher for use with many clients. | 81 // two clients. Adjust higher for use with many clients. |
115 if (!QuicSocketUtils::SetReceiveBufferSize(fd_, | 82 rc = socket->SetReceiveBufferSize(TcpReceiver::kReceiveWindowTCP); |
116 TcpReceiver::kReceiveWindowTCP)) { | 83 if (rc < 0) { |
117 return false; | 84 LOG(ERROR) << "SetReceiveBufferSize() failed: " << ErrorToString(rc); |
85 return rc; | |
118 } | 86 } |
119 | 87 |
120 if (!QuicSocketUtils::SetSendBufferSize(fd_, | 88 rc = socket->SetSendBufferSize(20 * kMaxPacketSize); |
121 TcpReceiver::kReceiveWindowTCP)) { | 89 if (rc < 0) { |
122 return false; | 90 LOG(ERROR) << "SetSendBufferSize() failed: " << ErrorToString(rc); |
91 return rc; | |
123 } | 92 } |
124 | 93 |
125 // Enable the socket option that allows the local address to be | 94 rc = socket->GetLocalAddress(&server_address_); |
126 // returned if the socket is bound to more than on address. | 95 if (rc < 0) { |
127 int get_local_ip = 1; | 96 LOG(ERROR) << "GetLocalAddress() failed: " << ErrorToString(rc); |
128 rc = setsockopt(fd_, IPPROTO_IP, IP_PKTINFO, | 97 return rc; |
129 &get_local_ip, sizeof(get_local_ip)); | |
130 if (rc == 0 && address_family == AF_INET6) { | |
131 rc = setsockopt(fd_, IPPROTO_IPV6, IPV6_RECVPKTINFO, | |
132 &get_local_ip, sizeof(get_local_ip)); | |
133 } | |
134 if (rc != 0) { | |
135 LOG(ERROR) << "Failed to set required socket options"; | |
136 return false; | |
137 } | 98 } |
138 | 99 |
139 sockaddr_storage raw_addr; | 100 DVLOG(1) << "Listening on " << server_address_.ToString(); |
140 socklen_t raw_addr_len = sizeof(raw_addr); | |
141 CHECK(address.ToSockAddr(reinterpret_cast<sockaddr*>(&raw_addr), | |
142 &raw_addr_len)); | |
143 rc = bind(fd_, | |
144 reinterpret_cast<const sockaddr*>(&raw_addr), | |
145 sizeof(raw_addr)); | |
146 if (rc < 0) { | |
147 LOG(ERROR) << "Bind failed: " << strerror(errno); | |
148 return false; | |
149 } | |
150 | 101 |
151 DVLOG(1) << "Listening on " << address.ToString(); | 102 socket_.swap(socket); |
152 if (port_ == 0) { | |
153 SockaddrStorage storage; | |
154 IPEndPoint server_address; | |
155 if (getsockname(fd_, storage.addr, &storage.addr_len) != 0 || | |
156 !server_address.FromSockAddr(storage.addr, storage.addr_len)) { | |
157 LOG(ERROR) << "Unable to get self address. Error: " << strerror(errno); | |
158 return false; | |
159 } | |
160 port_ = server_address.port(); | |
161 DVLOG(1) << "Kernel assigned port is " << port_; | |
162 } | |
163 | 103 |
164 epoll_server_.RegisterFD(fd_, this, kEpollFlags); | 104 dispatcher_.reset( |
165 dispatcher_.reset(CreateQuicDispatcher()); | 105 new QuicDispatcher(config_, |
166 dispatcher_->Initialize(fd_); | 106 crypto_config_, |
107 supported_versions_, | |
108 &helper_)); | |
109 QuicServerPacketWriter* writer = new QuicServerPacketWriter( | |
110 socket_.get(), | |
111 dispatcher_.get()); | |
112 dispatcher_->Initialize(writer); | |
167 | 113 |
168 return true; | 114 StartReading(); |
169 } | |
170 | 115 |
171 QuicDispatcher* QuicServer::CreateQuicDispatcher() { | 116 return OK; |
172 return new QuicDispatcher( | |
173 config_, | |
174 crypto_config_, | |
175 supported_versions_, | |
176 &epoll_server_); | |
177 } | |
178 | |
179 void QuicServer::WaitForEvents() { | |
180 epoll_server_.WaitForEventsAndExecuteCallbacks(); | |
181 } | 117 } |
182 | 118 |
183 void QuicServer::Shutdown() { | 119 void QuicServer::Shutdown() { |
184 // Before we shut down the epoll server, give all active sessions a chance to | 120 // Before we shut down the epoll server, give all active sessions a chance to |
185 // notify clients that they're closing. | 121 // notify clients that they're closing. |
186 dispatcher_->Shutdown(); | 122 dispatcher_->Shutdown(); |
187 | 123 |
188 close(fd_); | 124 socket_->Close(); |
189 fd_ = -1; | 125 socket_.reset(); |
190 } | 126 } |
191 | 127 |
192 void QuicServer::OnEvent(int fd, EpollEvent* event) { | 128 void QuicServer::StartReading() { |
193 DCHECK_EQ(fd, fd_); | 129 if (read_pending_) { |
194 event->out_ready_mask = 0; | 130 return; |
131 } | |
132 read_pending_ = true; | |
195 | 133 |
196 if (event->in_events & EPOLLIN) { | 134 int result = socket_->RecvFrom( |
197 DVLOG(1) << "EPOLLIN"; | 135 read_buffer_.get(), |
198 bool read = true; | 136 read_buffer_->size(), |
199 while (read) { | 137 &client_address_, |
200 read = ReadAndDispatchSinglePacket( | 138 base::Bind(&QuicServer::OnReadComplete, base::Unretained(this))); |
201 fd_, port_, dispatcher_.get(), | 139 |
202 overflow_supported_ ? &packets_dropped_ : NULL); | 140 if (result == ERR_IO_PENDING) { |
203 } | 141 synchronous_read_count_ = 0; |
142 return; | |
204 } | 143 } |
205 if (event->in_events & EPOLLOUT) { | 144 |
206 dispatcher_->OnCanWrite(); | 145 if (++synchronous_read_count_ > 32) { |
207 if (dispatcher_->HasPendingWrites()) { | 146 synchronous_read_count_ = 0; |
208 event->out_ready_mask |= EPOLLOUT; | 147 // Schedule the processing through the message loop to 1) prevent infinite |
209 } | 148 // recursion and 2) avoid blocking the thread for too long. |
210 } | 149 base::MessageLoop::current()->PostTask( |
211 if (event->in_events & EPOLLERR) { | 150 FROM_HERE, |
151 base::Bind(&QuicServer::OnReadComplete, | |
152 weak_factory_.GetWeakPtr(), | |
153 result)); | |
154 } else { | |
155 OnReadComplete(result); | |
212 } | 156 } |
213 } | 157 } |
214 | 158 |
215 /* static */ | 159 void QuicServer::OnReadComplete(int result) { |
216 bool QuicServer::ReadAndDispatchSinglePacket(int fd, | 160 read_pending_ = false; |
217 int port, | 161 if (result == 0) |
218 QuicDispatcher* dispatcher, | 162 result = ERR_CONNECTION_CLOSED; |
219 uint32* packets_dropped) { | |
220 // Allocate some extra space so we can send an error if the client goes over | |
221 // the limit. | |
222 char buf[2 * kMaxPacketSize]; | |
223 | 163 |
224 IPEndPoint client_address; | 164 if (result < 0) { |
225 IPAddressNumber server_ip; | 165 LOG(ERROR) << "QuicServer read failed: " << ErrorToString(result); |
226 int bytes_read = | 166 Shutdown(); |
227 QuicSocketUtils::ReadPacket(fd, buf, arraysize(buf), | 167 return; |
228 packets_dropped, | |
229 &server_ip, &client_address); | |
230 | |
231 if (bytes_read < 0) { | |
232 return false; // We failed to read. | |
233 } | 168 } |
234 | 169 |
235 QuicEncryptedPacket packet(buf, bytes_read, false); | 170 QuicEncryptedPacket packet(read_buffer_->data(), result, false); |
171 dispatcher_->ProcessPacket(server_address_, client_address_, packet); | |
236 | 172 |
237 IPEndPoint server_address(server_ip, port); | 173 StartReading(); |
238 dispatcher->ProcessPacket(server_address, client_address, packet); | |
239 | |
240 return true; | |
241 } | 174 } |
242 | 175 |
243 } // namespace tools | |
244 } // namespace net | 176 } // namespace net |
OLD | NEW |