blob: d18525f634fcbb9c601a85427e3cce7aa5f9ed72 [file] [log] [blame]
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +01001// 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_in_memory_cache.h"
22#include "net/tools/quic/quic_socket_utils.h"
23
24#define MMSG_MORE 0
25
26#ifndef SO_RXQ_OVFL
27#define SO_RXQ_OVFL 40
28#endif
29
30const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET;
31const int kNumPacketsPerReadCall = 5; // Arbitrary
32static const char kSourceAddressTokenSecret[] = "secret";
33
34namespace net {
35namespace tools {
36
37QuicServer::QuicServer()
38 : port_(0),
39 packets_dropped_(0),
40 overflow_supported_(false),
41 use_recvmmsg_(false),
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010042 crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance()) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010043 // Use hardcoded crypto parameters for now.
44 config_.SetDefaults();
45 Initialize();
46}
47
48QuicServer::QuicServer(const QuicConfig& config)
49 : port_(0),
50 packets_dropped_(0),
51 overflow_supported_(false),
52 use_recvmmsg_(false),
53 config_(config),
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010054 crypto_config_(kSourceAddressTokenSecret, QuicRandom::GetInstance()) {
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010055 Initialize();
56}
57
58void QuicServer::Initialize() {
59#if MMSG_MORE
60 use_recvmmsg_ = true;
61#endif
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010062 epoll_server_.set_timeout_in_us(50 * 1000);
63 // Initialize the in memory cache now.
64 QuicInMemoryCache::GetInstance();
65
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010066 QuicEpollClock clock(&epoll_server_);
67
68 scoped_ptr<CryptoHandshakeMessage> scfg(
Torne (Richard Coles)b2df76e2013-05-13 16:52:09 +010069 crypto_config_.AddDefaultConfig(
Torne (Richard Coles)90dce4d2013-05-29 14:40:03 +010070 QuicRandom::GetInstance(), &clock,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +010071 QuicCryptoServerConfig::ConfigOptions()));
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +010072}
73
74QuicServer::~QuicServer() {
75}
76
77bool QuicServer::Listen(const IPEndPoint& address) {
78 port_ = address.port();
79 int address_family = address.GetSockAddrFamily();
80 fd_ = socket(address_family, SOCK_DGRAM | SOCK_NONBLOCK, IPPROTO_UDP);
81 if (fd_ < 0) {
82 LOG(ERROR) << "CreateSocket() failed: " << strerror(errno);
83 return false;
84 }
85
86 int rc = QuicSocketUtils::SetGetAddressInfo(fd_, address_family);
87
88 if (rc < 0) {
89 LOG(ERROR) << "IP detection not supported" << strerror(errno);
90 return false;
91 }
92
93 int get_overflow = 1;
94 rc = setsockopt(
95 fd_, SOL_SOCKET, SO_RXQ_OVFL, &get_overflow, sizeof(get_overflow));
96
97 if (rc < 0) {
98 DLOG(WARNING) << "Socket overflow detection not supported";
99 } else {
100 overflow_supported_ = true;
101 }
102
103 // Enable the socket option that allows the local address to be
104 // returned if the socket is bound to more than on address.
105 int get_local_ip = 1;
106 rc = setsockopt(fd_, IPPROTO_IP, IP_PKTINFO,
107 &get_local_ip, sizeof(get_local_ip));
108 if (rc == 0 && address_family == AF_INET6) {
109 rc = setsockopt(fd_, IPPROTO_IPV6, IPV6_RECVPKTINFO,
110 &get_local_ip, sizeof(get_local_ip));
111 }
112 if (rc != 0) {
113 LOG(ERROR) << "Failed to set required socket options";
114 return false;
115 }
116
117 sockaddr_storage raw_addr;
118 socklen_t raw_addr_len = sizeof(raw_addr);
119 CHECK(address.ToSockAddr(reinterpret_cast<sockaddr*>(&raw_addr),
120 &raw_addr_len));
121 rc = bind(fd_,
122 reinterpret_cast<const sockaddr*>(&raw_addr),
123 sizeof(raw_addr));
124 if (rc < 0) {
125 LOG(ERROR) << "Bind failed: " << strerror(errno);
126 return false;
127 }
128
129 LOG(INFO) << "Listening on " << address.ToString();
130 if (port_ == 0) {
131 SockaddrStorage storage;
132 IPEndPoint server_address;
133 if (getsockname(fd_, storage.addr, &storage.addr_len) != 0 ||
134 !server_address.FromSockAddr(storage.addr, storage.addr_len)) {
135 LOG(ERROR) << "Unable to get self address. Error: " << strerror(errno);
136 return false;
137 }
138 port_ = server_address.port();
139 LOG(INFO) << "Kernel assigned port is " << port_;
140 }
141
142 epoll_server_.RegisterFD(fd_, this, kEpollFlags);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100143 dispatcher_.reset(new QuicDispatcher(config_, crypto_config_, fd_,
144 &epoll_server_));
145
146 return true;
147}
148
149void QuicServer::WaitForEvents() {
150 epoll_server_.WaitForEventsAndExecuteCallbacks();
151}
152
153void QuicServer::Shutdown() {
154 // Before we shut down the epoll server, give all active sessions a chance to
155 // notify clients that they're closing.
156 dispatcher_->Shutdown();
157}
158
159void QuicServer::OnEvent(int fd, EpollEvent* event) {
160 DCHECK_EQ(fd, fd_);
161 event->out_ready_mask = 0;
162
163 if (event->in_events & EPOLLIN) {
164 LOG(ERROR) << "EPOLLIN";
165 bool read = true;
166 while (read) {
167 read = ReadAndDispatchSinglePacket(
168 fd_, port_, dispatcher_.get(),
169 overflow_supported_ ? &packets_dropped_ : NULL);
170 }
171 }
172 if (event->in_events & EPOLLOUT) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100173 bool can_write_more = dispatcher_->OnCanWrite();
174 if (can_write_more) {
175 event->out_ready_mask |= EPOLLOUT;
176 }
177 }
178 if (event->in_events & EPOLLERR) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100179 }
180}
181
Ben Murdochbb1529c2013-08-08 10:24:53 +0100182/* static */
183void QuicServer::MaybeDispatchPacket(QuicDispatcher* dispatcher,
184 const QuicEncryptedPacket& packet,
185 const IPEndPoint& server_address,
186 const IPEndPoint& client_address) {
187 QuicGuid guid;
188 if (!QuicFramer::ReadGuidFromPacket(packet, &guid)) {
189 return;
190 }
191
192 dispatcher->ProcessPacket(server_address, client_address, guid, packet);
193}
194
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100195bool QuicServer::ReadAndDispatchSinglePacket(int fd,
Torne (Richard Coles)868fa2f2013-06-11 10:57:03 +0100196 int port,
197 QuicDispatcher* dispatcher,
198 int* packets_dropped) {
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100199 // Allocate some extra space so we can send an error if the client goes over
200 // the limit.
201 char buf[2 * kMaxPacketSize];
202
203 IPEndPoint client_address;
204 IPAddressNumber server_ip;
205 int bytes_read =
206 QuicSocketUtils::ReadPacket(fd, buf, arraysize(buf),
207 packets_dropped,
208 &server_ip, &client_address);
209
210 if (bytes_read < 0) {
211 return false; // We failed to read.
212 }
213
214 QuicEncryptedPacket packet(buf, bytes_read, false);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100215
216 IPEndPoint server_address(server_ip, port);
Ben Murdochbb1529c2013-08-08 10:24:53 +0100217 MaybeDispatchPacket(dispatcher, packet, server_address, client_address);
Torne (Richard Coles)c2e0dbd2013-05-09 18:35:53 +0100218
219 return true;
220}
221
222} // namespace tools
223} // namespace net