Upstream version 7.36.149.0
[platform/framework/web/crosswalk.git] / src / net / tools / quic / quic_server.cc
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
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       server_initial_flow_control_receive_window_(
47           kServerInitialFlowControlWindow) {
48   // Use hardcoded crypto parameters for now.
49   config_.SetDefaults();
50   Initialize();
51 }
52
53 QuicServer::QuicServer(const QuicConfig& config,
54                        const QuicVersionVector& supported_versions,
55                        uint32 server_initial_flow_control_receive_window)
56     : port_(0),
57       fd_(-1),
58       packets_dropped_(0),
59       overflow_supported_(false),
60       use_recvmmsg_(false),
61       config_(config),
62       crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance()),
63       supported_versions_(supported_versions),
64       server_initial_flow_control_receive_window_(
65           server_initial_flow_control_receive_window) {
66   Initialize();
67 }
68
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
85 QuicServer::~QuicServer() {
86 }
87
88 bool QuicServer::Listen(const IPEndPoint& address) {
89   port_ = address.port();
90   int address_family = address.GetSockAddrFamily();
91   fd_ = socket(address_family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
92   if (fd_ < 0) {
93     LOG(ERROR) << "CreateSocket() failed: " << strerror(errno);
94     return false;
95   }
96
97   int rc = QuicSocketUtils::SetGetAddressInfo(fd_, address_family);
98
99   if (rc < 0) {
100     LOG(ERROR) << "IP detection not supported" << strerror(errno);
101     return false;
102   }
103
104   int get_overflow = 1;
105   rc = setsockopt(
106       fd_, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow, sizeof(get_overflow));
107
108   if (rc < 0) {
109     DLOG(WARNING) << "Socket overflow detection not supported";
110   } else {
111     overflow_supported_ = true;
112   }
113
114   // These send and receive buffer sizes are sized for a single connection,
115   // because the default usage of QuicServer is as a test server with one or
116   // two clients.  Adjust higher for use with many clients.
117   if (!QuicSocketUtils::SetReceiveBufferSize(fd_,
118                                              TcpReceiver::kReceiveWindowTCP)) {
119     return false;
120   }
121
122   if (!QuicSocketUtils::SetSendBufferSize(fd_,
123                                           TcpReceiver::kReceiveWindowTCP)) {
124     return false;
125   }
126
127   // Enable the socket option that allows the local address to be
128   // returned if the socket is bound to more than on address.
129   int get_local_ip = 1;
130   rc = setsockopt(fd_, IPPROTO_IP, IP_PKTINFO,
131                   &get_local_ip, sizeof(get_local_ip));
132   if (rc == 0 && address_family == AF_INET6) {
133     rc = setsockopt(fd_, IPPROTO_IPV6, IPV6_RECVPKTINFO,
134                     &get_local_ip, sizeof(get_local_ip));
135   }
136   if (rc != 0) {
137     LOG(ERROR) << "Failed to set required socket options";
138     return false;
139   }
140
141   sockaddr_storage raw_addr;
142   socklen_t raw_addr_len = sizeof(raw_addr);
143   CHECK(address.ToSockAddr(reinterpret_cast<sockaddr*>(&raw_addr),
144                            &raw_addr_len));
145   rc = bind(fd_,
146             reinterpret_cast<const sockaddr*>(&raw_addr),
147             sizeof(raw_addr));
148   if (rc < 0) {
149     LOG(ERROR) << "Bind failed: " << strerror(errno);
150     return false;
151   }
152
153   DVLOG(1) << "Listening on " << address.ToString();
154   if (port_ == 0) {
155     SockaddrStorage storage;
156     IPEndPoint server_address;
157     if (getsockname(fd_, storage.addr, &storage.addr_len) != 0 ||
158         !server_address.FromSockAddr(storage.addr, storage.addr_len)) {
159       LOG(ERROR) << "Unable to get self address.  Error: " << strerror(errno);
160       return false;
161     }
162     port_ = server_address.port();
163     DVLOG(1) << "Kernel assigned port is " << port_;
164   }
165
166   epoll_server_.RegisterFD(fd_, this, kEpollFlags);
167   dispatcher_.reset(new QuicDispatcher(
168       config_,
169       crypto_config_,
170       supported_versions_,
171       &epoll_server_,
172       server_initial_flow_control_receive_window_));
173   dispatcher_->Initialize(fd_);
174
175   return true;
176 }
177
178 void QuicServer::WaitForEvents() {
179   epoll_server_.WaitForEventsAndExecuteCallbacks();
180 }
181
182 void QuicServer::Shutdown() {
183   // Before we shut down the epoll server, give all active sessions a chance to
184   // notify clients that they're closing.
185   dispatcher_->Shutdown();
186
187   close(fd_);
188   fd_ = -1;
189 }
190
191 void QuicServer::OnEvent(int fd, EpollEvent* event) {
192   DCHECK_EQ(fd, fd_);
193   event->out_ready_mask = 0;
194
195   if (event->in_events & EPOLLIN) {
196     DVLOG(1) << "EPOLLIN";
197     bool read = true;
198     while (read) {
199         read = ReadAndDispatchSinglePacket(
200             fd_, port_, dispatcher_.get(),
201             overflow_supported_ ? &packets_dropped_ : NULL);
202     }
203   }
204   if (event->in_events & EPOLLOUT) {
205     dispatcher_->OnCanWrite();
206     if (dispatcher_->HasPendingWrites()) {
207       event->out_ready_mask |= EPOLLOUT;
208     }
209   }
210   if (event->in_events & EPOLLERR) {
211   }
212 }
213
214 /* static */
215 bool QuicServer::ReadAndDispatchSinglePacket(int fd,
216                                              int port,
217                                              QuicDispatcher* dispatcher,
218                                              uint32* packets_dropped) {
219   // Allocate some extra space so we can send an error if the client goes over
220   // the limit.
221   char buf[2 * kMaxPacketSize];
222
223   IPEndPoint client_address;
224   IPAddressNumber server_ip;
225   int bytes_read =
226       QuicSocketUtils::ReadPacket(fd, buf, arraysize(buf),
227                                   packets_dropped,
228                                   &server_ip, &client_address);
229
230   if (bytes_read < 0) {
231     return false;  // We failed to read.
232   }
233
234   QuicEncryptedPacket packet(buf, bytes_read, false);
235
236   IPEndPoint server_address(server_ip, port);
237   dispatcher->ProcessPacket(server_address, client_address, packet);
238
239   return true;
240 }
241
242 }  // namespace tools
243 }  // namespace net