blob: 006098c2bac5fbf491c50d4cc4aa9358d52cbd56 [file] [log] [blame]
QUICHE teamc9b2cec2019-01-07 17:54:15 -05001// 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/third_party/quiche/src/quic/tools/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 <cstdint>
15#include <memory>
16
17#include "net/third_party/quiche/src/quic/core/crypto/crypto_handshake.h"
18#include "net/third_party/quiche/src/quic/core/crypto/quic_random.h"
19#include "net/third_party/quiche/src/quic/core/quic_crypto_stream.h"
20#include "net/third_party/quiche/src/quic/core/quic_data_reader.h"
21#include "net/third_party/quiche/src/quic/core/quic_default_packet_writer.h"
22#include "net/third_party/quiche/src/quic/core/quic_dispatcher.h"
23#include "net/third_party/quiche/src/quic/core/quic_epoll_alarm_factory.h"
24#include "net/third_party/quiche/src/quic/core/quic_packet_reader.h"
25#include "net/third_party/quiche/src/quic/core/quic_packets.h"
26#include "net/third_party/quiche/src/quic/core/tls_server_handshaker.h"
27#include "net/third_party/quiche/src/quic/platform/api/quic_clock.h"
28#include "net/third_party/quiche/src/quic/platform/api/quic_flags.h"
29#include "net/third_party/quiche/src/quic/platform/api/quic_logging.h"
30#include "net/quic/platform/impl/quic_epoll_clock.h"
31#include "net/quic/platform/impl/quic_socket_utils.h"
32#include "net/third_party/quiche/src/quic/tools/quic_simple_crypto_server_stream_helper.h"
33#include "net/third_party/quiche/src/quic/tools/quic_simple_dispatcher.h"
34#include "net/third_party/quiche/src/quic/tools/quic_simple_server_backend.h"
35
36#ifndef SO_RXQ_OVFL
37#define SO_RXQ_OVFL 40
38#endif
39
40namespace quic {
41
42namespace {
43
44const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET;
45const char kSourceAddressTokenSecret[] = "secret";
46
47} // namespace
48
49const size_t kNumSessionsToCreatePerSocketEvent = 16;
50
51QuicServer::QuicServer(std::unique_ptr<ProofSource> proof_source,
52 QuicSimpleServerBackend* quic_simple_server_backend)
53 : QuicServer(std::move(proof_source),
54 QuicConfig(),
55 QuicCryptoServerConfig::ConfigOptions(),
56 AllSupportedVersions(),
57 quic_simple_server_backend) {}
58
59QuicServer::QuicServer(
60 std::unique_ptr<ProofSource> proof_source,
61 const QuicConfig& config,
62 const QuicCryptoServerConfig::ConfigOptions& crypto_config_options,
63 const ParsedQuicVersionVector& supported_versions,
64 QuicSimpleServerBackend* quic_simple_server_backend)
65 : port_(0),
66 fd_(-1),
67 packets_dropped_(0),
68 overflow_supported_(false),
69 silent_close_(false),
70 config_(config),
71 crypto_config_(kSourceAddressTokenSecret,
72 QuicRandom::GetInstance(),
73 std::move(proof_source),
74 KeyExchangeSource::Default(),
75 TlsServerHandshaker::CreateSslCtx()),
76 crypto_config_options_(crypto_config_options),
77 version_manager_(supported_versions),
78 packet_reader_(new QuicPacketReader()),
79 quic_simple_server_backend_(quic_simple_server_backend) {
80 Initialize();
81}
82
83void QuicServer::Initialize() {
84 // If an initial flow control window has not explicitly been set, then use a
85 // sensible value for a server: 1 MB for session, 64 KB for each stream.
86 const uint32_t kInitialSessionFlowControlWindow = 1 * 1024 * 1024; // 1 MB
87 const uint32_t kInitialStreamFlowControlWindow = 64 * 1024; // 64 KB
88 if (config_.GetInitialStreamFlowControlWindowToSend() ==
89 kMinimumFlowControlSendWindow) {
90 config_.SetInitialStreamFlowControlWindowToSend(
91 kInitialStreamFlowControlWindow);
92 }
93 if (config_.GetInitialSessionFlowControlWindowToSend() ==
94 kMinimumFlowControlSendWindow) {
95 config_.SetInitialSessionFlowControlWindowToSend(
96 kInitialSessionFlowControlWindow);
97 }
98
99 epoll_server_.set_timeout_in_us(50 * 1000);
100
101 QuicEpollClock clock(&epoll_server_);
102
103 std::unique_ptr<CryptoHandshakeMessage> scfg(crypto_config_.AddDefaultConfig(
104 QuicRandom::GetInstance(), &clock, crypto_config_options_));
105}
106
107QuicServer::~QuicServer() = default;
108
109bool QuicServer::CreateUDPSocketAndListen(const QuicSocketAddress& address) {
110 fd_ = QuicSocketUtils::CreateUDPSocket(
111 address,
112 /*receive_buffer_size =*/kDefaultSocketReceiveBuffer,
113 /*send_buffer_size =*/kDefaultSocketReceiveBuffer, &overflow_supported_);
114 if (fd_ < 0) {
115 QUIC_LOG(ERROR) << "CreateSocket() failed: " << strerror(errno);
116 return false;
117 }
118
119 sockaddr_storage addr = address.generic_address();
120 int rc = bind(fd_, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
121 if (rc < 0) {
122 QUIC_LOG(ERROR) << "Bind failed: " << strerror(errno);
123 return false;
124 }
125 QUIC_LOG(INFO) << "Listening on " << address.ToString();
126 port_ = address.port();
127 if (port_ == 0) {
128 QuicSocketAddress address;
129 if (address.FromSocket(fd_) != 0) {
130 QUIC_LOG(ERROR) << "Unable to get self address. Error: "
131 << strerror(errno);
132 }
133 port_ = address.port();
134 }
135
136 epoll_server_.RegisterFD(fd_, this, kEpollFlags);
137 dispatcher_.reset(CreateQuicDispatcher());
138 dispatcher_->InitializeWithWriter(CreateWriter(fd_));
139
140 return true;
141}
142
143QuicPacketWriter* QuicServer::CreateWriter(int fd) {
144 return new QuicDefaultPacketWriter(fd);
145}
146
147QuicDispatcher* QuicServer::CreateQuicDispatcher() {
148 QuicEpollAlarmFactory alarm_factory(&epoll_server_);
149 return new QuicSimpleDispatcher(
QUICHE team2bfc7542019-02-26 14:36:06 -0500150 &config_, &crypto_config_, &version_manager_,
QUICHE teamc9b2cec2019-01-07 17:54:15 -0500151 std::unique_ptr<QuicEpollConnectionHelper>(new QuicEpollConnectionHelper(
152 &epoll_server_, QuicAllocator::BUFFER_POOL)),
153 std::unique_ptr<QuicCryptoServerStream::Helper>(
154 new QuicSimpleCryptoServerStreamHelper(QuicRandom::GetInstance())),
155 std::unique_ptr<QuicEpollAlarmFactory>(
156 new QuicEpollAlarmFactory(&epoll_server_)),
157 quic_simple_server_backend_);
158}
159
160void QuicServer::WaitForEvents() {
161 epoll_server_.WaitForEventsAndExecuteCallbacks();
162}
163
164void QuicServer::Start() {
165 Run();
166}
167
168void QuicServer::Run() {
169 WaitForEvents();
170}
171
172void QuicServer::Shutdown() {
173 if (!silent_close_) {
174 // Before we shut down the epoll server, give all active sessions a chance
175 // to notify clients that they're closing.
176 dispatcher_->Shutdown();
177 }
178
179 epoll_server_.Shutdown();
180
181 close(fd_);
182 fd_ = -1;
183}
184
QUICHE teamdc5ce1a2019-01-30 16:01:47 -0500185void QuicServer::OnEvent(int fd, QuicEpollEvent* event) {
QUICHE teamc9b2cec2019-01-07 17:54:15 -0500186 DCHECK_EQ(fd, fd_);
187 event->out_ready_mask = 0;
188
189 if (event->in_events & EPOLLIN) {
190 QUIC_DVLOG(1) << "EPOLLIN";
191
192 dispatcher_->ProcessBufferedChlos(kNumSessionsToCreatePerSocketEvent);
193
194 bool more_to_read = true;
195 while (more_to_read) {
196 more_to_read = packet_reader_->ReadAndDispatchPackets(
197 fd_, port_, QuicEpollClock(&epoll_server_), dispatcher_.get(),
198 overflow_supported_ ? &packets_dropped_ : nullptr);
199 }
200
201 if (dispatcher_->HasChlosBuffered()) {
202 // Register EPOLLIN event to consume buffered CHLO(s).
203 event->out_ready_mask |= EPOLLIN;
204 }
205 }
206 if (event->in_events & EPOLLOUT) {
207 dispatcher_->OnCanWrite();
208 if (dispatcher_->HasPendingWrites()) {
209 event->out_ready_mask |= EPOLLOUT;
210 }
211 }
212 if (event->in_events & EPOLLERR) {
213 }
214}
215
216} // namespace quic