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.
5 #include "net/tools/quic/quic_server.h"
9 #include <netinet/in.h>
11 #include <sys/epoll.h>
12 #include <sys/socket.h>
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"
27 #define SO_RXQ_OVFL 40
30 const int kEpollFlags
= EPOLLIN
| EPOLLOUT
| EPOLLET
;
31 const int kNumPacketsPerReadCall
= 5; // Arbitrary
32 static const char kSourceAddressTokenSecret
[] = "secret";
37 QuicServer::QuicServer()
40 overflow_supported_(false),
42 crypto_config_(kSourceAddressTokenSecret
, QuicRandom::GetInstance()) {
43 // Use hardcoded crypto parameters for now.
44 config_
.SetDefaults();
48 QuicServer::QuicServer(const QuicConfig
& config
)
51 overflow_supported_(false),
54 crypto_config_(kSourceAddressTokenSecret
, QuicRandom::GetInstance()) {
58 void QuicServer::Initialize() {
62 epoll_server_
.set_timeout_in_us(50 * 1000);
63 // Initialize the in memory cache now.
64 QuicInMemoryCache::GetInstance();
66 QuicEpollClock
clock(&epoll_server_
);
68 scoped_ptr
<CryptoHandshakeMessage
> scfg(
69 crypto_config_
.AddDefaultConfig(
70 QuicRandom::GetInstance(), &clock
,
71 QuicCryptoServerConfig::ConfigOptions()));
74 QuicServer::~QuicServer() {
77 bool 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
);
82 LOG(ERROR
) << "CreateSocket() failed: " << strerror(errno
);
86 int rc
= QuicSocketUtils::SetGetAddressInfo(fd_
, address_family
);
89 LOG(ERROR
) << "IP detection not supported" << strerror(errno
);
95 fd_
, SOL_SOCKET
, SO_RXQ_OVFL
, &get_overflow
, sizeof(get_overflow
));
98 DLOG(WARNING
) << "Socket overflow detection not supported";
100 overflow_supported_
= true;
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
));
113 LOG(ERROR
) << "Failed to set required socket options";
117 sockaddr_storage raw_addr
;
118 socklen_t raw_addr_len
= sizeof(raw_addr
);
119 CHECK(address
.ToSockAddr(reinterpret_cast<sockaddr
*>(&raw_addr
),
122 reinterpret_cast<const sockaddr
*>(&raw_addr
),
125 LOG(ERROR
) << "Bind failed: " << strerror(errno
);
129 LOG(INFO
) << "Listening on " << address
.ToString();
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
);
138 port_
= server_address
.port();
139 LOG(INFO
) << "Kernel assigned port is " << port_
;
142 epoll_server_
.RegisterFD(fd_
, this, kEpollFlags
);
143 dispatcher_
.reset(new QuicDispatcher(config_
, crypto_config_
, fd_
,
149 void QuicServer::WaitForEvents() {
150 epoll_server_
.WaitForEventsAndExecuteCallbacks();
153 void 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();
159 void QuicServer::OnEvent(int fd
, EpollEvent
* event
) {
161 event
->out_ready_mask
= 0;
163 if (event
->in_events
& EPOLLIN
) {
164 LOG(ERROR
) << "EPOLLIN";
167 read
= ReadAndDispatchSinglePacket(
168 fd_
, port_
, dispatcher_
.get(),
169 overflow_supported_
? &packets_dropped_
: NULL
);
172 if (event
->in_events
& EPOLLOUT
) {
173 bool can_write_more
= dispatcher_
->OnCanWrite();
174 if (can_write_more
) {
175 event
->out_ready_mask
|= EPOLLOUT
;
178 if (event
->in_events
& EPOLLERR
) {
183 void QuicServer::MaybeDispatchPacket(QuicDispatcher
* dispatcher
,
184 const QuicEncryptedPacket
& packet
,
185 const IPEndPoint
& server_address
,
186 const IPEndPoint
& client_address
) {
188 if (!QuicFramer::ReadGuidFromPacket(packet
, &guid
)) {
192 dispatcher
->ProcessPacket(server_address
, client_address
, guid
, packet
);
195 bool QuicServer::ReadAndDispatchSinglePacket(int fd
,
197 QuicDispatcher
* dispatcher
,
198 int* packets_dropped
) {
199 // Allocate some extra space so we can send an error if the client goes over
201 char buf
[2 * kMaxPacketSize
];
203 IPEndPoint client_address
;
204 IPAddressNumber server_ip
;
206 QuicSocketUtils::ReadPacket(fd
, buf
, arraysize(buf
),
208 &server_ip
, &client_address
);
210 if (bytes_read
< 0) {
211 return false; // We failed to read.
214 QuicEncryptedPacket
packet(buf
, bytes_read
, false);
216 IPEndPoint
server_address(server_ip
, port
);
217 MaybeDispatchPacket(dispatcher
, packet
, server_address
, client_address
);