1*3f982cf4SFabien Sanglard // Copyright 2018 The Chromium Authors. All rights reserved.
2*3f982cf4SFabien Sanglard // Use of this source code is governed by a BSD-style license that can be
3*3f982cf4SFabien Sanglard // found in the LICENSE file.
4*3f982cf4SFabien Sanglard
5*3f982cf4SFabien Sanglard #include "osp/impl/quic/quic_server.h"
6*3f982cf4SFabien Sanglard
7*3f982cf4SFabien Sanglard #include <functional>
8*3f982cf4SFabien Sanglard #include <memory>
9*3f982cf4SFabien Sanglard
10*3f982cf4SFabien Sanglard #include "platform/api/task_runner.h"
11*3f982cf4SFabien Sanglard #include "platform/api/time.h"
12*3f982cf4SFabien Sanglard #include "util/osp_logging.h"
13*3f982cf4SFabien Sanglard
14*3f982cf4SFabien Sanglard namespace openscreen {
15*3f982cf4SFabien Sanglard namespace osp {
16*3f982cf4SFabien Sanglard
QuicServer(const ServerConfig & config,MessageDemuxer * demuxer,std::unique_ptr<QuicConnectionFactory> connection_factory,ProtocolConnectionServer::Observer * observer,ClockNowFunctionPtr now_function,TaskRunner * task_runner)17*3f982cf4SFabien Sanglard QuicServer::QuicServer(
18*3f982cf4SFabien Sanglard const ServerConfig& config,
19*3f982cf4SFabien Sanglard MessageDemuxer* demuxer,
20*3f982cf4SFabien Sanglard std::unique_ptr<QuicConnectionFactory> connection_factory,
21*3f982cf4SFabien Sanglard ProtocolConnectionServer::Observer* observer,
22*3f982cf4SFabien Sanglard ClockNowFunctionPtr now_function,
23*3f982cf4SFabien Sanglard TaskRunner* task_runner)
24*3f982cf4SFabien Sanglard : ProtocolConnectionServer(demuxer, observer),
25*3f982cf4SFabien Sanglard connection_endpoints_(config.connection_endpoints),
26*3f982cf4SFabien Sanglard connection_factory_(std::move(connection_factory)),
27*3f982cf4SFabien Sanglard cleanup_alarm_(now_function, task_runner) {}
28*3f982cf4SFabien Sanglard
~QuicServer()29*3f982cf4SFabien Sanglard QuicServer::~QuicServer() {
30*3f982cf4SFabien Sanglard CloseAllConnections();
31*3f982cf4SFabien Sanglard }
32*3f982cf4SFabien Sanglard
Start()33*3f982cf4SFabien Sanglard bool QuicServer::Start() {
34*3f982cf4SFabien Sanglard if (state_ != State::kStopped)
35*3f982cf4SFabien Sanglard return false;
36*3f982cf4SFabien Sanglard state_ = State::kRunning;
37*3f982cf4SFabien Sanglard connection_factory_->SetServerDelegate(this, connection_endpoints_);
38*3f982cf4SFabien Sanglard Cleanup(); // Start periodic clean-ups.
39*3f982cf4SFabien Sanglard observer_->OnRunning();
40*3f982cf4SFabien Sanglard return true;
41*3f982cf4SFabien Sanglard }
42*3f982cf4SFabien Sanglard
Stop()43*3f982cf4SFabien Sanglard bool QuicServer::Stop() {
44*3f982cf4SFabien Sanglard if (state_ != State::kRunning && state_ != State::kSuspended)
45*3f982cf4SFabien Sanglard return false;
46*3f982cf4SFabien Sanglard connection_factory_->SetServerDelegate(nullptr, {});
47*3f982cf4SFabien Sanglard CloseAllConnections();
48*3f982cf4SFabien Sanglard state_ = State::kStopped;
49*3f982cf4SFabien Sanglard Cleanup(); // Final clean-up.
50*3f982cf4SFabien Sanglard observer_->OnStopped();
51*3f982cf4SFabien Sanglard return true;
52*3f982cf4SFabien Sanglard }
53*3f982cf4SFabien Sanglard
Suspend()54*3f982cf4SFabien Sanglard bool QuicServer::Suspend() {
55*3f982cf4SFabien Sanglard // TODO(btolsch): QuicStreams should either buffer or reject writes.
56*3f982cf4SFabien Sanglard if (state_ != State::kRunning)
57*3f982cf4SFabien Sanglard return false;
58*3f982cf4SFabien Sanglard state_ = State::kSuspended;
59*3f982cf4SFabien Sanglard observer_->OnSuspended();
60*3f982cf4SFabien Sanglard return true;
61*3f982cf4SFabien Sanglard }
62*3f982cf4SFabien Sanglard
Resume()63*3f982cf4SFabien Sanglard bool QuicServer::Resume() {
64*3f982cf4SFabien Sanglard if (state_ != State::kSuspended)
65*3f982cf4SFabien Sanglard return false;
66*3f982cf4SFabien Sanglard state_ = State::kRunning;
67*3f982cf4SFabien Sanglard observer_->OnRunning();
68*3f982cf4SFabien Sanglard return true;
69*3f982cf4SFabien Sanglard }
70*3f982cf4SFabien Sanglard
Cleanup()71*3f982cf4SFabien Sanglard void QuicServer::Cleanup() {
72*3f982cf4SFabien Sanglard for (auto& entry : connections_)
73*3f982cf4SFabien Sanglard entry.second.delegate->DestroyClosedStreams();
74*3f982cf4SFabien Sanglard
75*3f982cf4SFabien Sanglard for (uint64_t endpoint_id : delete_connections_) {
76*3f982cf4SFabien Sanglard auto it = connections_.find(endpoint_id);
77*3f982cf4SFabien Sanglard if (it != connections_.end()) {
78*3f982cf4SFabien Sanglard connections_.erase(it);
79*3f982cf4SFabien Sanglard }
80*3f982cf4SFabien Sanglard }
81*3f982cf4SFabien Sanglard delete_connections_.clear();
82*3f982cf4SFabien Sanglard
83*3f982cf4SFabien Sanglard constexpr Clock::duration kQuicCleanupPeriod = std::chrono::milliseconds(500);
84*3f982cf4SFabien Sanglard if (state_ != State::kStopped) {
85*3f982cf4SFabien Sanglard cleanup_alarm_.ScheduleFromNow([this] { Cleanup(); }, kQuicCleanupPeriod);
86*3f982cf4SFabien Sanglard }
87*3f982cf4SFabien Sanglard }
88*3f982cf4SFabien Sanglard
CreateProtocolConnection(uint64_t endpoint_id)89*3f982cf4SFabien Sanglard std::unique_ptr<ProtocolConnection> QuicServer::CreateProtocolConnection(
90*3f982cf4SFabien Sanglard uint64_t endpoint_id) {
91*3f982cf4SFabien Sanglard if (state_ != State::kRunning) {
92*3f982cf4SFabien Sanglard return nullptr;
93*3f982cf4SFabien Sanglard }
94*3f982cf4SFabien Sanglard auto connection_entry = connections_.find(endpoint_id);
95*3f982cf4SFabien Sanglard if (connection_entry == connections_.end()) {
96*3f982cf4SFabien Sanglard return nullptr;
97*3f982cf4SFabien Sanglard }
98*3f982cf4SFabien Sanglard return QuicProtocolConnection::FromExisting(
99*3f982cf4SFabien Sanglard this, connection_entry->second.connection.get(),
100*3f982cf4SFabien Sanglard connection_entry->second.delegate.get(), endpoint_id);
101*3f982cf4SFabien Sanglard }
102*3f982cf4SFabien Sanglard
OnConnectionDestroyed(QuicProtocolConnection * connection)103*3f982cf4SFabien Sanglard void QuicServer::OnConnectionDestroyed(QuicProtocolConnection* connection) {
104*3f982cf4SFabien Sanglard if (!connection->stream())
105*3f982cf4SFabien Sanglard return;
106*3f982cf4SFabien Sanglard
107*3f982cf4SFabien Sanglard auto connection_entry = connections_.find(connection->endpoint_id());
108*3f982cf4SFabien Sanglard if (connection_entry == connections_.end())
109*3f982cf4SFabien Sanglard return;
110*3f982cf4SFabien Sanglard
111*3f982cf4SFabien Sanglard connection_entry->second.delegate->DropProtocolConnection(connection);
112*3f982cf4SFabien Sanglard }
113*3f982cf4SFabien Sanglard
OnCryptoHandshakeComplete(ServiceConnectionDelegate * delegate,uint64_t connection_id)114*3f982cf4SFabien Sanglard uint64_t QuicServer::OnCryptoHandshakeComplete(
115*3f982cf4SFabien Sanglard ServiceConnectionDelegate* delegate,
116*3f982cf4SFabien Sanglard uint64_t connection_id) {
117*3f982cf4SFabien Sanglard OSP_DCHECK_EQ(state_, State::kRunning);
118*3f982cf4SFabien Sanglard const IPEndpoint& endpoint = delegate->endpoint();
119*3f982cf4SFabien Sanglard auto pending_entry = pending_connections_.find(endpoint);
120*3f982cf4SFabien Sanglard if (pending_entry == pending_connections_.end())
121*3f982cf4SFabien Sanglard return 0;
122*3f982cf4SFabien Sanglard ServiceConnectionData connection_data = std::move(pending_entry->second);
123*3f982cf4SFabien Sanglard pending_connections_.erase(pending_entry);
124*3f982cf4SFabien Sanglard uint64_t endpoint_id = next_endpoint_id_++;
125*3f982cf4SFabien Sanglard endpoint_map_[endpoint] = endpoint_id;
126*3f982cf4SFabien Sanglard connections_.emplace(endpoint_id, std::move(connection_data));
127*3f982cf4SFabien Sanglard return endpoint_id;
128*3f982cf4SFabien Sanglard }
129*3f982cf4SFabien Sanglard
OnIncomingStream(std::unique_ptr<QuicProtocolConnection> connection)130*3f982cf4SFabien Sanglard void QuicServer::OnIncomingStream(
131*3f982cf4SFabien Sanglard std::unique_ptr<QuicProtocolConnection> connection) {
132*3f982cf4SFabien Sanglard OSP_DCHECK_EQ(state_, State::kRunning);
133*3f982cf4SFabien Sanglard observer_->OnIncomingConnection(std::move(connection));
134*3f982cf4SFabien Sanglard }
135*3f982cf4SFabien Sanglard
OnConnectionClosed(uint64_t endpoint_id,uint64_t connection_id)136*3f982cf4SFabien Sanglard void QuicServer::OnConnectionClosed(uint64_t endpoint_id,
137*3f982cf4SFabien Sanglard uint64_t connection_id) {
138*3f982cf4SFabien Sanglard OSP_DCHECK_EQ(state_, State::kRunning);
139*3f982cf4SFabien Sanglard auto connection_entry = connections_.find(endpoint_id);
140*3f982cf4SFabien Sanglard if (connection_entry == connections_.end())
141*3f982cf4SFabien Sanglard return;
142*3f982cf4SFabien Sanglard delete_connections_.push_back(endpoint_id);
143*3f982cf4SFabien Sanglard
144*3f982cf4SFabien Sanglard // TODO(crbug.com/openscreen/42): If we reset request IDs when a connection is
145*3f982cf4SFabien Sanglard // closed, we might end up re-using request IDs when a new connection is
146*3f982cf4SFabien Sanglard // created to the same endpoint.
147*3f982cf4SFabien Sanglard endpoint_request_ids_.ResetRequestId(endpoint_id);
148*3f982cf4SFabien Sanglard }
149*3f982cf4SFabien Sanglard
OnDataReceived(uint64_t endpoint_id,uint64_t connection_id,const uint8_t * data,size_t data_size)150*3f982cf4SFabien Sanglard void QuicServer::OnDataReceived(uint64_t endpoint_id,
151*3f982cf4SFabien Sanglard uint64_t connection_id,
152*3f982cf4SFabien Sanglard const uint8_t* data,
153*3f982cf4SFabien Sanglard size_t data_size) {
154*3f982cf4SFabien Sanglard OSP_DCHECK_EQ(state_, State::kRunning);
155*3f982cf4SFabien Sanglard demuxer_->OnStreamData(endpoint_id, connection_id, data, data_size);
156*3f982cf4SFabien Sanglard }
157*3f982cf4SFabien Sanglard
CloseAllConnections()158*3f982cf4SFabien Sanglard void QuicServer::CloseAllConnections() {
159*3f982cf4SFabien Sanglard for (auto& conn : pending_connections_)
160*3f982cf4SFabien Sanglard conn.second.connection->Close();
161*3f982cf4SFabien Sanglard
162*3f982cf4SFabien Sanglard pending_connections_.clear();
163*3f982cf4SFabien Sanglard
164*3f982cf4SFabien Sanglard for (auto& conn : connections_)
165*3f982cf4SFabien Sanglard conn.second.connection->Close();
166*3f982cf4SFabien Sanglard
167*3f982cf4SFabien Sanglard connections_.clear();
168*3f982cf4SFabien Sanglard endpoint_map_.clear();
169*3f982cf4SFabien Sanglard next_endpoint_id_ = 0;
170*3f982cf4SFabien Sanglard endpoint_request_ids_.Reset();
171*3f982cf4SFabien Sanglard }
172*3f982cf4SFabien Sanglard
NextConnectionDelegate(const IPEndpoint & source)173*3f982cf4SFabien Sanglard QuicConnection::Delegate* QuicServer::NextConnectionDelegate(
174*3f982cf4SFabien Sanglard const IPEndpoint& source) {
175*3f982cf4SFabien Sanglard OSP_DCHECK_EQ(state_, State::kRunning);
176*3f982cf4SFabien Sanglard OSP_DCHECK(!pending_connection_delegate_);
177*3f982cf4SFabien Sanglard pending_connection_delegate_ =
178*3f982cf4SFabien Sanglard std::make_unique<ServiceConnectionDelegate>(this, source);
179*3f982cf4SFabien Sanglard return pending_connection_delegate_.get();
180*3f982cf4SFabien Sanglard }
181*3f982cf4SFabien Sanglard
OnIncomingConnection(std::unique_ptr<QuicConnection> connection)182*3f982cf4SFabien Sanglard void QuicServer::OnIncomingConnection(
183*3f982cf4SFabien Sanglard std::unique_ptr<QuicConnection> connection) {
184*3f982cf4SFabien Sanglard OSP_DCHECK_EQ(state_, State::kRunning);
185*3f982cf4SFabien Sanglard const IPEndpoint& endpoint = pending_connection_delegate_->endpoint();
186*3f982cf4SFabien Sanglard pending_connections_.emplace(
187*3f982cf4SFabien Sanglard endpoint, ServiceConnectionData(std::move(connection),
188*3f982cf4SFabien Sanglard std::move(pending_connection_delegate_)));
189*3f982cf4SFabien Sanglard }
190*3f982cf4SFabien Sanglard
191*3f982cf4SFabien Sanglard } // namespace osp
192*3f982cf4SFabien Sanglard } // namespace openscreen
193