• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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