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