blob: fe10d12a3898d868f98f0d3f4601413442dbd96e [file] [log] [blame]
QUICHE teama6ef0a62019-03-07 20:34:33 -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
QUICHE team5be974e2020-12-29 18:35:24 -05005#include "quic/tools/quic_server.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -05006
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
QUICHE team5be974e2020-12-29 18:35:24 -050017#include "quic/core/crypto/crypto_handshake.h"
18#include "quic/core/crypto/quic_random.h"
19#include "quic/core/quic_clock.h"
20#include "quic/core/quic_crypto_stream.h"
21#include "quic/core/quic_data_reader.h"
22#include "quic/core/quic_default_packet_writer.h"
23#include "quic/core/quic_dispatcher.h"
24#include "quic/core/quic_epoll_alarm_factory.h"
25#include "quic/core/quic_epoll_connection_helper.h"
26#include "quic/core/quic_packet_reader.h"
27#include "quic/core/quic_packets.h"
28#include "quic/platform/api/quic_flags.h"
29#include "quic/platform/api/quic_logging.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050030#include "net/quic/platform/impl/quic_epoll_clock.h"
QUICHE team5be974e2020-12-29 18:35:24 -050031#include "quic/tools/quic_simple_crypto_server_stream_helper.h"
32#include "quic/tools/quic_simple_dispatcher.h"
33#include "quic/tools/quic_simple_server_backend.h"
QUICHE teama6ef0a62019-03-07 20:34:33 -050034
QUICHE teama6ef0a62019-03-07 20:34:33 -050035namespace quic {
36
37namespace {
38
39const int kEpollFlags = EPOLLIN | EPOLLOUT | EPOLLET;
40const char kSourceAddressTokenSecret[] = "secret";
41
42} // namespace
43
44const size_t kNumSessionsToCreatePerSocketEvent = 16;
45
46QuicServer::QuicServer(std::unique_ptr<ProofSource> proof_source,
47 QuicSimpleServerBackend* quic_simple_server_backend)
48 : QuicServer(std::move(proof_source),
dschinazic5589bd2019-09-12 14:50:11 -070049 quic_simple_server_backend,
50 AllSupportedVersions()) {}
51
52QuicServer::QuicServer(std::unique_ptr<ProofSource> proof_source,
53 QuicSimpleServerBackend* quic_simple_server_backend,
54 const ParsedQuicVersionVector& supported_versions)
55 : QuicServer(std::move(proof_source),
QUICHE teama6ef0a62019-03-07 20:34:33 -050056 QuicConfig(),
57 QuicCryptoServerConfig::ConfigOptions(),
dschinazic5589bd2019-09-12 14:50:11 -070058 supported_versions,
QUICHE teama6ef0a62019-03-07 20:34:33 -050059 quic_simple_server_backend,
60 kQuicDefaultConnectionIdLength) {}
61
62QuicServer::QuicServer(
63 std::unique_ptr<ProofSource> proof_source,
64 const QuicConfig& config,
65 const QuicCryptoServerConfig::ConfigOptions& crypto_config_options,
66 const ParsedQuicVersionVector& supported_versions,
67 QuicSimpleServerBackend* quic_simple_server_backend,
dschinazi8ff74822019-05-28 16:37:20 -070068 uint8_t expected_server_connection_id_length)
QUICHE teama6ef0a62019-03-07 20:34:33 -050069 : port_(0),
70 fd_(-1),
71 packets_dropped_(0),
72 overflow_supported_(false),
73 silent_close_(false),
74 config_(config),
75 crypto_config_(kSourceAddressTokenSecret,
76 QuicRandom::GetInstance(),
77 std::move(proof_source),
nharper6ebe83b2019-06-13 17:43:52 -070078 KeyExchangeSource::Default()),
QUICHE teama6ef0a62019-03-07 20:34:33 -050079 crypto_config_options_(crypto_config_options),
80 version_manager_(supported_versions),
81 packet_reader_(new QuicPacketReader()),
82 quic_simple_server_backend_(quic_simple_server_backend),
dschinazi8ff74822019-05-28 16:37:20 -070083 expected_server_connection_id_length_(
84 expected_server_connection_id_length) {
vasilvvf8035162021-02-01 14:49:14 -080085 QUICHE_DCHECK(quic_simple_server_backend_);
QUICHE teama6ef0a62019-03-07 20:34:33 -050086 Initialize();
87}
88
89void QuicServer::Initialize() {
90 // If an initial flow control window has not explicitly been set, then use a
91 // sensible value for a server: 1 MB for session, 64 KB for each stream.
92 const uint32_t kInitialSessionFlowControlWindow = 1 * 1024 * 1024; // 1 MB
93 const uint32_t kInitialStreamFlowControlWindow = 64 * 1024; // 64 KB
94 if (config_.GetInitialStreamFlowControlWindowToSend() ==
dschinazic7036122019-04-30 12:46:34 -070095 kDefaultFlowControlSendWindow) {
QUICHE teama6ef0a62019-03-07 20:34:33 -050096 config_.SetInitialStreamFlowControlWindowToSend(
97 kInitialStreamFlowControlWindow);
98 }
99 if (config_.GetInitialSessionFlowControlWindowToSend() ==
dschinazic7036122019-04-30 12:46:34 -0700100 kDefaultFlowControlSendWindow) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500101 config_.SetInitialSessionFlowControlWindowToSend(
102 kInitialSessionFlowControlWindow);
103 }
104
105 epoll_server_.set_timeout_in_us(50 * 1000);
106
107 QuicEpollClock clock(&epoll_server_);
108
109 std::unique_ptr<CryptoHandshakeMessage> scfg(crypto_config_.AddDefaultConfig(
110 QuicRandom::GetInstance(), &clock, crypto_config_options_));
111}
112
113QuicServer::~QuicServer() = default;
114
115bool QuicServer::CreateUDPSocketAndListen(const QuicSocketAddress& address) {
wubcfddec82020-01-13 07:45:27 -0800116 QuicUdpSocketApi socket_api;
117 fd_ = socket_api.Create(address.host().AddressFamilyToInt(),
118 /*receive_buffer_size =*/kDefaultSocketReceiveBuffer,
119 /*send_buffer_size =*/kDefaultSocketReceiveBuffer);
120 if (fd_ == kQuicInvalidSocketFd) {
QUICHE teama6ef0a62019-03-07 20:34:33 -0500121 QUIC_LOG(ERROR) << "CreateSocket() failed: " << strerror(errno);
122 return false;
123 }
124
wubcfddec82020-01-13 07:45:27 -0800125 overflow_supported_ = socket_api.EnableDroppedPacketCount(fd_);
126 socket_api.EnableReceiveTimestamp(fd_);
127
QUICHE teama6ef0a62019-03-07 20:34:33 -0500128 sockaddr_storage addr = address.generic_address();
129 int rc = bind(fd_, reinterpret_cast<sockaddr*>(&addr), sizeof(addr));
130 if (rc < 0) {
131 QUIC_LOG(ERROR) << "Bind failed: " << strerror(errno);
132 return false;
133 }
134 QUIC_LOG(INFO) << "Listening on " << address.ToString();
135 port_ = address.port();
136 if (port_ == 0) {
137 QuicSocketAddress address;
138 if (address.FromSocket(fd_) != 0) {
139 QUIC_LOG(ERROR) << "Unable to get self address. Error: "
140 << strerror(errno);
141 }
142 port_ = address.port();
143 }
144
145 epoll_server_.RegisterFD(fd_, this, kEpollFlags);
146 dispatcher_.reset(CreateQuicDispatcher());
147 dispatcher_->InitializeWithWriter(CreateWriter(fd_));
148
149 return true;
150}
151
152QuicPacketWriter* QuicServer::CreateWriter(int fd) {
153 return new QuicDefaultPacketWriter(fd);
154}
155
156QuicDispatcher* QuicServer::CreateQuicDispatcher() {
157 QuicEpollAlarmFactory alarm_factory(&epoll_server_);
158 return new QuicSimpleDispatcher(
159 &config_, &crypto_config_, &version_manager_,
160 std::unique_ptr<QuicEpollConnectionHelper>(new QuicEpollConnectionHelper(
161 &epoll_server_, QuicAllocator::BUFFER_POOL)),
nharper5f23a2d2020-02-20 10:44:09 -0800162 std::unique_ptr<QuicCryptoServerStreamBase::Helper>(
wub662a3d62019-08-16 14:10:50 -0700163 new QuicSimpleCryptoServerStreamHelper()),
QUICHE teama6ef0a62019-03-07 20:34:33 -0500164 std::unique_ptr<QuicEpollAlarmFactory>(
165 new QuicEpollAlarmFactory(&epoll_server_)),
dschinazi8ff74822019-05-28 16:37:20 -0700166 quic_simple_server_backend_, expected_server_connection_id_length_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500167}
168
rch034c98c2019-05-17 15:46:09 -0700169void QuicServer::HandleEventsForever() {
170 while (true) {
171 WaitForEvents();
172 }
173}
174
QUICHE teama6ef0a62019-03-07 20:34:33 -0500175void QuicServer::WaitForEvents() {
176 epoll_server_.WaitForEventsAndExecuteCallbacks();
177}
178
179void QuicServer::Shutdown() {
180 if (!silent_close_) {
181 // Before we shut down the epoll server, give all active sessions a chance
182 // to notify clients that they're closing.
183 dispatcher_->Shutdown();
184 }
185
186 epoll_server_.Shutdown();
187
188 close(fd_);
189 fd_ = -1;
190}
191
192void QuicServer::OnEvent(int fd, QuicEpollEvent* event) {
vasilvvf8035162021-02-01 14:49:14 -0800193 QUICHE_DCHECK_EQ(fd, fd_);
QUICHE teama6ef0a62019-03-07 20:34:33 -0500194 event->out_ready_mask = 0;
195
196 if (event->in_events & EPOLLIN) {
197 QUIC_DVLOG(1) << "EPOLLIN";
198
199 dispatcher_->ProcessBufferedChlos(kNumSessionsToCreatePerSocketEvent);
200
201 bool more_to_read = true;
202 while (more_to_read) {
203 more_to_read = packet_reader_->ReadAndDispatchPackets(
204 fd_, port_, QuicEpollClock(&epoll_server_), dispatcher_.get(),
205 overflow_supported_ ? &packets_dropped_ : nullptr);
206 }
207
208 if (dispatcher_->HasChlosBuffered()) {
209 // Register EPOLLIN event to consume buffered CHLO(s).
210 event->out_ready_mask |= EPOLLIN;
211 }
212 }
213 if (event->in_events & EPOLLOUT) {
214 dispatcher_->OnCanWrite();
215 if (dispatcher_->HasPendingWrites()) {
216 event->out_ready_mask |= EPOLLOUT;
217 }
218 }
QUICHE teama6ef0a62019-03-07 20:34:33 -0500219}
220
221} // namespace quic