OLD | NEW |
| (Empty) |
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 | |
3 // found in the LICENSE file. | |
4 | |
5 #include "net/tools/quic/quic_server.h" | |
6 | |
7 #include <errno.h> | |
8 #include <features.h> | |
9 #include <netinet/in.h> | |
10 #include <string.h> | |
11 #include <sys/epoll.h> | |
12 #include <sys/socket.h> | |
13 | |
14 #include "net/base/ip_endpoint.h" | |
15 #include "net/quic/crypto/crypto_handshake.h" | |
16 #include "net/quic/crypto/quic_random.h" | |
17 #include "net/quic/quic_clock.h" | |
18 #include "net/quic/quic_crypto_stream.h" | |
19 #include "net/quic/quic_data_reader.h" | |
20 #include "net/quic/quic_protocol.h" | |
21 #include "net/tools/quic/quic_dispatcher.h" | |
22 #include "net/tools/quic/quic_in_memory_cache.h" | |
23 #include "net/tools/quic/quic_socket_utils.h" | |
24 | |
25 #define MMSG_MORE 0 | |
26 | |
27 #ifndef SO_RXQ_OVFL | |
28 #define SO_RXQ_OVFL 40 | |
29 #endif | |
30 | |
31 namespace net { | |
32 namespace tools { | |
33 | |
34 namespace { | |
35 | |
36 const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET; | |
37 const char kSourceAddressTokenSecret[] = "secret"; | |
38 | |
39 } // namespace | |
40 | |
41 QuicServer::QuicServer() | |
42 : port_(0), | |
43 fd_(-1), | |
44 packets_dropped_(0), | |
45 overflow_supported_(false), | |
46 use_recvmmsg_(false), | |
47 crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance()), | |
48 supported_versions_(QuicSupportedVersions()) { | |
49 Initialize(); | |
50 } | |
51 | |
52 QuicServer::QuicServer(const QuicConfig& config, | |
53 const QuicVersionVector& supported_versions) | |
54 : port_(0), | |
55 fd_(-1), | |
56 packets_dropped_(0), | |
57 overflow_supported_(false), | |
58 use_recvmmsg_(false), | |
59 config_(config), | |
60 crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance()), | |
61 supported_versions_(supported_versions) { | |
62 Initialize(); | |
63 } | |
64 | |
65 void QuicServer::Initialize() { | |
66 #if MMSG_MORE | |
67 use_recvmmsg_ = true; | |
68 #endif | |
69 | |
70 // If an initial flow control window has not explicitly been set, then use a | |
71 // sensible value for a server: 1 MB for session, 64 KB for each stream. | |
72 const uint32 kInitialSessionFlowControlWindow = 1 * 1024 * 1024; // 1 MB | |
73 const uint32 kInitialStreamFlowControlWindow = 64 * 1024; // 64 KB | |
74 if (config_.GetInitialStreamFlowControlWindowToSend() == | |
75 kMinimumFlowControlSendWindow) { | |
76 config_.SetInitialStreamFlowControlWindowToSend( | |
77 kInitialStreamFlowControlWindow); | |
78 } | |
79 if (config_.GetInitialSessionFlowControlWindowToSend() == | |
80 kMinimumFlowControlSendWindow) { | |
81 config_.SetInitialSessionFlowControlWindowToSend( | |
82 kInitialSessionFlowControlWindow); | |
83 } | |
84 | |
85 epoll_server_.set_timeout_in_us(50 * 1000); | |
86 // Initialize the in memory cache now. | |
87 QuicInMemoryCache::GetInstance(); | |
88 | |
89 QuicEpollClock clock(&epoll_server_); | |
90 | |
91 scoped_ptr<CryptoHandshakeMessage> scfg( | |
92 crypto_config_.AddDefaultConfig( | |
93 QuicRandom::GetInstance(), &clock, | |
94 QuicCryptoServerConfig::ConfigOptions())); | |
95 } | |
96 | |
97 QuicServer::~QuicServer() { | |
98 } | |
99 | |
100 bool QuicServer::Listen(const IPEndPoint& address) { | |
101 port_ = address.port(); | |
102 int address_family = address.GetSockAddrFamily(); | |
103 fd_ = socket(address_family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP); | |
104 if (fd_ < 0) { | |
105 LOG(ERROR) << "CreateSocket() failed: " << strerror(errno); | |
106 return false; | |
107 } | |
108 | |
109 // Enable the socket option that allows the local address to be | |
110 // returned if the socket is bound to more than one address. | |
111 int rc = QuicSocketUtils::SetGetAddressInfo(fd_, address_family); | |
112 | |
113 if (rc < 0) { | |
114 LOG(ERROR) << "IP detection not supported" << strerror(errno); | |
115 return false; | |
116 } | |
117 | |
118 int get_overflow = 1; | |
119 rc = setsockopt( | |
120 fd_, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow, sizeof(get_overflow)); | |
121 | |
122 if (rc < 0) { | |
123 DLOG(WARNING) << "Socket overflow detection not supported"; | |
124 } else { | |
125 overflow_supported_ = true; | |
126 } | |
127 | |
128 // These send and receive buffer sizes are sized for a single connection, | |
129 // because the default usage of QuicServer is as a test server with one or | |
130 // two clients. Adjust higher for use with many clients. | |
131 if (!QuicSocketUtils::SetReceiveBufferSize(fd_, | |
132 kDefaultSocketReceiveBuffer)) { | |
133 return false; | |
134 } | |
135 | |
136 if (!QuicSocketUtils::SetSendBufferSize(fd_, kDefaultSocketReceiveBuffer)) { | |
137 return false; | |
138 } | |
139 | |
140 sockaddr_storage raw_addr; | |
141 socklen_t raw_addr_len = sizeof(raw_addr); | |
142 CHECK(address.ToSockAddr(reinterpret_cast<sockaddr*>(&raw_addr), | |
143 &raw_addr_len)); | |
144 rc = bind(fd_, | |
145 reinterpret_cast<const sockaddr*>(&raw_addr), | |
146 sizeof(raw_addr)); | |
147 if (rc < 0) { | |
148 LOG(ERROR) << "Bind failed: " << strerror(errno); | |
149 return false; | |
150 } | |
151 | |
152 DVLOG(1) << "Listening on " << address.ToString(); | |
153 if (port_ == 0) { | |
154 SockaddrStorage storage; | |
155 IPEndPoint server_address; | |
156 if (getsockname(fd_, storage.addr, &storage.addr_len) != 0 || | |
157 !server_address.FromSockAddr(storage.addr, storage.addr_len)) { | |
158 LOG(ERROR) << "Unable to get self address. Error: " << strerror(errno); | |
159 return false; | |
160 } | |
161 port_ = server_address.port(); | |
162 DVLOG(1) << "Kernel assigned port is " << port_; | |
163 } | |
164 | |
165 epoll_server_.RegisterFD(fd_, this, kEpollFlags); | |
166 dispatcher_.reset(CreateQuicDispatcher()); | |
167 dispatcher_->Initialize(fd_); | |
168 | |
169 return true; | |
170 } | |
171 | |
172 QuicDispatcher* QuicServer::CreateQuicDispatcher() { | |
173 return new QuicDispatcher( | |
174 config_, | |
175 crypto_config_, | |
176 supported_versions_, | |
177 new QuicDispatcher::DefaultPacketWriterFactory(), | |
178 &epoll_server_); | |
179 } | |
180 | |
181 void QuicServer::WaitForEvents() { | |
182 epoll_server_.WaitForEventsAndExecuteCallbacks(); | |
183 } | |
184 | |
185 void QuicServer::Shutdown() { | |
186 // Before we shut down the epoll server, give all active sessions a chance to | |
187 // notify clients that they're closing. | |
188 dispatcher_->Shutdown(); | |
189 | |
190 close(fd_); | |
191 fd_ = -1; | |
192 } | |
193 | |
194 void QuicServer::OnEvent(int fd, EpollEvent* event) { | |
195 DCHECK_EQ(fd, fd_); | |
196 event->out_ready_mask = 0; | |
197 | |
198 if (event->in_events & EPOLLIN) { | |
199 DVLOG(1) << "EPOLLIN"; | |
200 bool read = true; | |
201 while (read) { | |
202 read = ReadAndDispatchSinglePacket( | |
203 fd_, port_, dispatcher_.get(), | |
204 overflow_supported_ ? &packets_dropped_ : nullptr); | |
205 } | |
206 } | |
207 if (event->in_events & EPOLLOUT) { | |
208 dispatcher_->OnCanWrite(); | |
209 if (dispatcher_->HasPendingWrites()) { | |
210 event->out_ready_mask |= EPOLLOUT; | |
211 } | |
212 } | |
213 if (event->in_events & EPOLLERR) { | |
214 } | |
215 } | |
216 | |
217 /* static */ | |
218 bool QuicServer::ReadAndDispatchSinglePacket(int fd, | |
219 int port, | |
220 ProcessPacketInterface* processor, | |
221 QuicPacketCount* packets_dropped) { | |
222 // Allocate some extra space so we can send an error if the client goes over | |
223 // the limit. | |
224 char buf[2 * kMaxPacketSize]; | |
225 | |
226 IPEndPoint client_address; | |
227 IPAddressNumber server_ip; | |
228 int bytes_read = | |
229 QuicSocketUtils::ReadPacket(fd, buf, arraysize(buf), | |
230 packets_dropped, | |
231 &server_ip, &client_address); | |
232 | |
233 if (bytes_read < 0) { | |
234 return false; // We failed to read. | |
235 } | |
236 | |
237 QuicEncryptedPacket packet(buf, bytes_read, false); | |
238 | |
239 IPEndPoint server_address(server_ip, port); | |
240 processor->ProcessPacket(server_address, client_address, packet); | |
241 | |
242 return true; | |
243 } | |
244 | |
245 } // namespace tools | |
246 } // namespace net | |
OLD | NEW |