• 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_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 const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET;
32 static const char kSourceAddressTokenSecret[] = "secret";
33 const uint32 kServerInitialFlowControlWindow = 100 * net::kMaxPacketSize;
34 
35 namespace net {
36 namespace tools {
37 
QuicServer()38 QuicServer::QuicServer()
39     : port_(0),
40       fd_(-1),
41       packets_dropped_(0),
42       overflow_supported_(false),
43       use_recvmmsg_(false),
44       crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance()),
45       supported_versions_(QuicSupportedVersions()) {
46   // Use hardcoded crypto parameters for now.
47   config_.SetDefaults();
48   Initialize();
49 }
50 
QuicServer(const QuicConfig & config,const QuicVersionVector & supported_versions)51 QuicServer::QuicServer(const QuicConfig& config,
52                        const QuicVersionVector& supported_versions)
53     : port_(0),
54       fd_(-1),
55       packets_dropped_(0),
56       overflow_supported_(false),
57       use_recvmmsg_(false),
58       config_(config),
59       crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance()),
60       supported_versions_(supported_versions) {
61   Initialize();
62 }
63 
Initialize()64 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.
70   QuicInMemoryCache::GetInstance();
71 
72   QuicEpollClock clock(&epoll_server_);
73 
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);
81 }
82 
~QuicServer()83 QuicServer::~QuicServer() {
84 }
85 
Listen(const IPEndPoint & address)86 bool QuicServer::Listen(const IPEndPoint& address) {
87   port_ = address.port();
88   int address_family = address.GetSockAddrFamily();
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 
95   int rc = QuicSocketUtils::SetGetAddressInfo(fd_, address_family);
96 
97   if (rc < 0) {
98     LOG(ERROR) << "IP detection not supported" << strerror(errno);
99     return false;
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   }
111 
112   // 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
114   // two clients.  Adjust higher for use with many clients.
115   if (!QuicSocketUtils::SetReceiveBufferSize(fd_,
116                                              TcpReceiver::kReceiveWindowTCP)) {
117     return false;
118   }
119 
120   if (!QuicSocketUtils::SetSendBufferSize(fd_,
121                                           TcpReceiver::kReceiveWindowTCP)) {
122     return false;
123   }
124 
125   // Enable the socket option that allows the local address to be
126   // returned if the socket is bound to more than on address.
127   int get_local_ip = 1;
128   rc = setsockopt(fd_, IPPROTO_IP, IP_PKTINFO,
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   }
138 
139   sockaddr_storage raw_addr;
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 
151   DVLOG(1) << "Listening on " << address.ToString();
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 
164   epoll_server_.RegisterFD(fd_, this, kEpollFlags);
165   dispatcher_.reset(CreateQuicDispatcher());
166   dispatcher_->Initialize(fd_);
167 
168   return true;
169 }
170 
CreateQuicDispatcher()171 QuicDispatcher* QuicServer::CreateQuicDispatcher() {
172   return new QuicDispatcher(
173       config_,
174       crypto_config_,
175       supported_versions_,
176       &epoll_server_);
177 }
178 
WaitForEvents()179 void QuicServer::WaitForEvents() {
180   epoll_server_.WaitForEventsAndExecuteCallbacks();
181 }
182 
Shutdown()183 void QuicServer::Shutdown() {
184   // Before we shut down the epoll server, give all active sessions a chance to
185   // notify clients that they're closing.
186   dispatcher_->Shutdown();
187 
188   close(fd_);
189   fd_ = -1;
190 }
191 
OnEvent(int fd,EpollEvent * event)192 void QuicServer::OnEvent(int fd, EpollEvent* event) {
193   DCHECK_EQ(fd, fd_);
194   event->out_ready_mask = 0;
195 
196   if (event->in_events & EPOLLIN) {
197     DVLOG(1) << "EPOLLIN";
198     bool read = true;
199     while (read) {
200         read = ReadAndDispatchSinglePacket(
201             fd_, port_, dispatcher_.get(),
202             overflow_supported_ ? &packets_dropped_ : NULL);
203     }
204   }
205   if (event->in_events & EPOLLOUT) {
206     dispatcher_->OnCanWrite();
207     if (dispatcher_->HasPendingWrites()) {
208       event->out_ready_mask |= EPOLLOUT;
209     }
210   }
211   if (event->in_events & EPOLLERR) {
212   }
213 }
214 
215 /* static */
ReadAndDispatchSinglePacket(int fd,int port,QuicDispatcher * dispatcher,uint32 * packets_dropped)216 bool QuicServer::ReadAndDispatchSinglePacket(int fd,
217                                              int port,
218                                              QuicDispatcher* dispatcher,
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 
224   IPEndPoint client_address;
225   IPAddressNumber server_ip;
226   int bytes_read =
227       QuicSocketUtils::ReadPacket(fd, buf, arraysize(buf),
228                                   packets_dropped,
229                                   &server_ip, &client_address);
230 
231   if (bytes_read < 0) {
232     return false;  // We failed to read.
233   }
234 
235   QuicEncryptedPacket packet(buf, bytes_read, false);
236 
237   IPEndPoint server_address(server_ip, port);
238   dispatcher->ProcessPacket(server_address, client_address, packet);
239 
240   return true;
241 }
242 
243 }  // namespace tools
244 }  // namespace net
245