1*3f982cf4SFabien Sanglard // Copyright 2019 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/public/presentation/presentation_controller.h"
6*3f982cf4SFabien Sanglard
7*3f982cf4SFabien Sanglard #include <algorithm>
8*3f982cf4SFabien Sanglard #include <sstream>
9*3f982cf4SFabien Sanglard #include <type_traits>
10*3f982cf4SFabien Sanglard
11*3f982cf4SFabien Sanglard #include "absl/types/optional.h"
12*3f982cf4SFabien Sanglard #include "osp/impl/presentation/url_availability_requester.h"
13*3f982cf4SFabien Sanglard #include "osp/msgs/osp_messages.h"
14*3f982cf4SFabien Sanglard #include "osp/public/message_demuxer.h"
15*3f982cf4SFabien Sanglard #include "osp/public/network_service_manager.h"
16*3f982cf4SFabien Sanglard #include "osp/public/protocol_connection_client.h"
17*3f982cf4SFabien Sanglard #include "osp/public/request_response_handler.h"
18*3f982cf4SFabien Sanglard #include "util/osp_logging.h"
19*3f982cf4SFabien Sanglard
20*3f982cf4SFabien Sanglard namespace openscreen {
21*3f982cf4SFabien Sanglard namespace osp {
22*3f982cf4SFabien Sanglard
23*3f982cf4SFabien Sanglard #define DECLARE_MSG_REQUEST_RESPONSE(base_name) \
24*3f982cf4SFabien Sanglard using RequestMsgType = msgs::Presentation##base_name##Request; \
25*3f982cf4SFabien Sanglard using ResponseMsgType = msgs::Presentation##base_name##Response; \
26*3f982cf4SFabien Sanglard \
27*3f982cf4SFabien Sanglard static constexpr MessageEncodingFunction<RequestMsgType> kEncoder = \
28*3f982cf4SFabien Sanglard &msgs::EncodePresentation##base_name##Request; \
29*3f982cf4SFabien Sanglard static constexpr MessageDecodingFunction<ResponseMsgType> kDecoder = \
30*3f982cf4SFabien Sanglard &msgs::DecodePresentation##base_name##Response; \
31*3f982cf4SFabien Sanglard static constexpr msgs::Type kResponseType = \
32*3f982cf4SFabien Sanglard msgs::Type::kPresentation##base_name##Response
33*3f982cf4SFabien Sanglard
34*3f982cf4SFabien Sanglard struct StartRequest {
35*3f982cf4SFabien Sanglard DECLARE_MSG_REQUEST_RESPONSE(Start);
36*3f982cf4SFabien Sanglard
37*3f982cf4SFabien Sanglard msgs::PresentationStartRequest request;
38*3f982cf4SFabien Sanglard RequestDelegate* delegate;
39*3f982cf4SFabien Sanglard Connection::Delegate* presentation_connection_delegate;
40*3f982cf4SFabien Sanglard };
41*3f982cf4SFabien Sanglard
42*3f982cf4SFabien Sanglard struct ConnectionOpenRequest {
43*3f982cf4SFabien Sanglard DECLARE_MSG_REQUEST_RESPONSE(ConnectionOpen);
44*3f982cf4SFabien Sanglard
45*3f982cf4SFabien Sanglard msgs::PresentationConnectionOpenRequest request;
46*3f982cf4SFabien Sanglard RequestDelegate* delegate;
47*3f982cf4SFabien Sanglard Connection::Delegate* presentation_connection_delegate;
48*3f982cf4SFabien Sanglard std::unique_ptr<Connection> connection;
49*3f982cf4SFabien Sanglard };
50*3f982cf4SFabien Sanglard
51*3f982cf4SFabien Sanglard struct ConnectionCloseRequest {
52*3f982cf4SFabien Sanglard DECLARE_MSG_REQUEST_RESPONSE(ConnectionClose);
53*3f982cf4SFabien Sanglard
54*3f982cf4SFabien Sanglard msgs::PresentationConnectionCloseRequest request;
55*3f982cf4SFabien Sanglard };
56*3f982cf4SFabien Sanglard
57*3f982cf4SFabien Sanglard struct TerminationRequest {
58*3f982cf4SFabien Sanglard DECLARE_MSG_REQUEST_RESPONSE(Termination);
59*3f982cf4SFabien Sanglard
60*3f982cf4SFabien Sanglard msgs::PresentationTerminationRequest request;
61*3f982cf4SFabien Sanglard };
62*3f982cf4SFabien Sanglard
63*3f982cf4SFabien Sanglard class Controller::MessageGroupStreams final
64*3f982cf4SFabien Sanglard : public ProtocolConnectionClient::ConnectionRequestCallback,
65*3f982cf4SFabien Sanglard public ProtocolConnection::Observer,
66*3f982cf4SFabien Sanglard public RequestResponseHandler<StartRequest>::Delegate,
67*3f982cf4SFabien Sanglard public RequestResponseHandler<ConnectionOpenRequest>::Delegate,
68*3f982cf4SFabien Sanglard public RequestResponseHandler<ConnectionCloseRequest>::Delegate,
69*3f982cf4SFabien Sanglard public RequestResponseHandler<TerminationRequest>::Delegate {
70*3f982cf4SFabien Sanglard public:
71*3f982cf4SFabien Sanglard MessageGroupStreams(Controller* controller, const std::string& service_id);
72*3f982cf4SFabien Sanglard ~MessageGroupStreams();
73*3f982cf4SFabien Sanglard
74*3f982cf4SFabien Sanglard uint64_t SendStartRequest(StartRequest request);
75*3f982cf4SFabien Sanglard void CancelStartRequest(uint64_t request_id);
76*3f982cf4SFabien Sanglard void OnMatchedResponse(StartRequest* request,
77*3f982cf4SFabien Sanglard msgs::PresentationStartResponse* response,
78*3f982cf4SFabien Sanglard uint64_t endpoint_id) override;
79*3f982cf4SFabien Sanglard void OnError(StartRequest* request, Error error) override;
80*3f982cf4SFabien Sanglard
81*3f982cf4SFabien Sanglard uint64_t SendConnectionOpenRequest(ConnectionOpenRequest request);
82*3f982cf4SFabien Sanglard void CancelConnectionOpenRequest(uint64_t request_id);
83*3f982cf4SFabien Sanglard void OnMatchedResponse(ConnectionOpenRequest* request,
84*3f982cf4SFabien Sanglard msgs::PresentationConnectionOpenResponse* response,
85*3f982cf4SFabien Sanglard uint64_t endpoint_id) override;
86*3f982cf4SFabien Sanglard void OnError(ConnectionOpenRequest* request, Error error) override;
87*3f982cf4SFabien Sanglard
88*3f982cf4SFabien Sanglard void SendConnectionCloseRequest(ConnectionCloseRequest request);
89*3f982cf4SFabien Sanglard void OnMatchedResponse(ConnectionCloseRequest* request,
90*3f982cf4SFabien Sanglard msgs::PresentationConnectionCloseResponse* response,
91*3f982cf4SFabien Sanglard uint64_t endpoint_id) override;
92*3f982cf4SFabien Sanglard void OnError(ConnectionCloseRequest* request, Error error) override;
93*3f982cf4SFabien Sanglard
94*3f982cf4SFabien Sanglard void SendTerminationRequest(TerminationRequest request);
95*3f982cf4SFabien Sanglard void OnMatchedResponse(TerminationRequest* request,
96*3f982cf4SFabien Sanglard msgs::PresentationTerminationResponse* response,
97*3f982cf4SFabien Sanglard uint64_t endpoint_id) override;
98*3f982cf4SFabien Sanglard void OnError(TerminationRequest* request, Error error) override;
99*3f982cf4SFabien Sanglard
100*3f982cf4SFabien Sanglard // ProtocolConnectionClient::ConnectionRequestCallback overrides.
101*3f982cf4SFabien Sanglard void OnConnectionOpened(
102*3f982cf4SFabien Sanglard uint64_t request_id,
103*3f982cf4SFabien Sanglard std::unique_ptr<ProtocolConnection> connection) override;
104*3f982cf4SFabien Sanglard void OnConnectionFailed(uint64_t request_id) override;
105*3f982cf4SFabien Sanglard
106*3f982cf4SFabien Sanglard // ProtocolConnection::Observer overrides.
107*3f982cf4SFabien Sanglard void OnConnectionClosed(const ProtocolConnection& connection) override;
108*3f982cf4SFabien Sanglard
109*3f982cf4SFabien Sanglard private:
110*3f982cf4SFabien Sanglard uint64_t GetNextInternalRequestId();
111*3f982cf4SFabien Sanglard
112*3f982cf4SFabien Sanglard Controller* const controller_;
113*3f982cf4SFabien Sanglard const std::string service_id_;
114*3f982cf4SFabien Sanglard
115*3f982cf4SFabien Sanglard uint64_t next_internal_request_id_ = 1;
116*3f982cf4SFabien Sanglard ProtocolConnectionClient::ConnectRequest initiation_connect_request_;
117*3f982cf4SFabien Sanglard std::unique_ptr<ProtocolConnection> initiation_protocol_connection_;
118*3f982cf4SFabien Sanglard ProtocolConnectionClient::ConnectRequest connection_connect_request_;
119*3f982cf4SFabien Sanglard std::unique_ptr<ProtocolConnection> connection_protocol_connection_;
120*3f982cf4SFabien Sanglard
121*3f982cf4SFabien Sanglard // TODO(btolsch): Improve the ergo of QuicClient::Connect because this is bad.
122*3f982cf4SFabien Sanglard bool initiation_connect_request_stack_{false};
123*3f982cf4SFabien Sanglard bool connection_connect_request_stack_{false};
124*3f982cf4SFabien Sanglard
125*3f982cf4SFabien Sanglard RequestResponseHandler<StartRequest> initiation_handler_;
126*3f982cf4SFabien Sanglard RequestResponseHandler<ConnectionOpenRequest> connection_open_handler_;
127*3f982cf4SFabien Sanglard RequestResponseHandler<ConnectionCloseRequest> connection_close_handler_;
128*3f982cf4SFabien Sanglard RequestResponseHandler<TerminationRequest> termination_handler_;
129*3f982cf4SFabien Sanglard };
130*3f982cf4SFabien Sanglard
MessageGroupStreams(Controller * controller,const std::string & service_id)131*3f982cf4SFabien Sanglard Controller::MessageGroupStreams::MessageGroupStreams(
132*3f982cf4SFabien Sanglard Controller* controller,
133*3f982cf4SFabien Sanglard const std::string& service_id)
134*3f982cf4SFabien Sanglard : controller_(controller),
135*3f982cf4SFabien Sanglard service_id_(service_id),
136*3f982cf4SFabien Sanglard initiation_handler_(this),
137*3f982cf4SFabien Sanglard connection_open_handler_(this),
138*3f982cf4SFabien Sanglard connection_close_handler_(this),
139*3f982cf4SFabien Sanglard termination_handler_(this) {}
140*3f982cf4SFabien Sanglard
141*3f982cf4SFabien Sanglard Controller::MessageGroupStreams::~MessageGroupStreams() = default;
142*3f982cf4SFabien Sanglard
SendStartRequest(StartRequest request)143*3f982cf4SFabien Sanglard uint64_t Controller::MessageGroupStreams::SendStartRequest(
144*3f982cf4SFabien Sanglard StartRequest request) {
145*3f982cf4SFabien Sanglard uint64_t request_id = GetNextInternalRequestId();
146*3f982cf4SFabien Sanglard if (!initiation_protocol_connection_ && !initiation_connect_request_) {
147*3f982cf4SFabien Sanglard initiation_connect_request_stack_ = true;
148*3f982cf4SFabien Sanglard initiation_connect_request_ =
149*3f982cf4SFabien Sanglard NetworkServiceManager::Get()->GetProtocolConnectionClient()->Connect(
150*3f982cf4SFabien Sanglard controller_->receiver_endpoints_[service_id_], this);
151*3f982cf4SFabien Sanglard initiation_connect_request_stack_ = false;
152*3f982cf4SFabien Sanglard }
153*3f982cf4SFabien Sanglard initiation_handler_.WriteMessage(request_id, std::move(request));
154*3f982cf4SFabien Sanglard return request_id;
155*3f982cf4SFabien Sanglard }
156*3f982cf4SFabien Sanglard
CancelStartRequest(uint64_t request_id)157*3f982cf4SFabien Sanglard void Controller::MessageGroupStreams::CancelStartRequest(uint64_t request_id) {
158*3f982cf4SFabien Sanglard // TODO(btolsch): Instead, mark the |request_id| for immediate termination if
159*3f982cf4SFabien Sanglard // we get a successful response.
160*3f982cf4SFabien Sanglard initiation_handler_.CancelMessage(request_id);
161*3f982cf4SFabien Sanglard }
162*3f982cf4SFabien Sanglard
OnMatchedResponse(StartRequest * request,msgs::PresentationStartResponse * response,uint64_t endpoint_id)163*3f982cf4SFabien Sanglard void Controller::MessageGroupStreams::OnMatchedResponse(
164*3f982cf4SFabien Sanglard StartRequest* request,
165*3f982cf4SFabien Sanglard msgs::PresentationStartResponse* response,
166*3f982cf4SFabien Sanglard uint64_t endpoint_id) {
167*3f982cf4SFabien Sanglard if (response->result != msgs::PresentationStartResponse_result::kSuccess) {
168*3f982cf4SFabien Sanglard std::stringstream ss;
169*3f982cf4SFabien Sanglard ss << "presentation-start-response for " << request->request.url
170*3f982cf4SFabien Sanglard << " failed: " << static_cast<int>(response->result);
171*3f982cf4SFabien Sanglard Error error(Error::Code::kUnknownStartError, ss.str());
172*3f982cf4SFabien Sanglard OSP_LOG_INFO << error.message();
173*3f982cf4SFabien Sanglard request->delegate->OnError(std::move(error));
174*3f982cf4SFabien Sanglard return;
175*3f982cf4SFabien Sanglard }
176*3f982cf4SFabien Sanglard OSP_LOG_INFO << "presentation started for " << request->request.url;
177*3f982cf4SFabien Sanglard Controller::ControlledPresentation& presentation =
178*3f982cf4SFabien Sanglard controller_->presentations_[request->request.presentation_id];
179*3f982cf4SFabien Sanglard presentation.service_id = service_id_;
180*3f982cf4SFabien Sanglard presentation.url = request->request.url;
181*3f982cf4SFabien Sanglard auto connection = std::make_unique<Connection>(
182*3f982cf4SFabien Sanglard Connection::PresentationInfo{request->request.presentation_id,
183*3f982cf4SFabien Sanglard request->request.url},
184*3f982cf4SFabien Sanglard request->presentation_connection_delegate, controller_);
185*3f982cf4SFabien Sanglard controller_->OpenConnection(response->connection_id, endpoint_id, service_id_,
186*3f982cf4SFabien Sanglard request->delegate, std::move(connection),
187*3f982cf4SFabien Sanglard NetworkServiceManager::Get()
188*3f982cf4SFabien Sanglard ->GetProtocolConnectionClient()
189*3f982cf4SFabien Sanglard ->CreateProtocolConnection(endpoint_id));
190*3f982cf4SFabien Sanglard }
191*3f982cf4SFabien Sanglard
OnError(StartRequest * request,Error error)192*3f982cf4SFabien Sanglard void Controller::MessageGroupStreams::OnError(StartRequest* request,
193*3f982cf4SFabien Sanglard Error error) {
194*3f982cf4SFabien Sanglard request->delegate->OnError(std::move(error));
195*3f982cf4SFabien Sanglard }
196*3f982cf4SFabien Sanglard
SendConnectionOpenRequest(ConnectionOpenRequest request)197*3f982cf4SFabien Sanglard uint64_t Controller::MessageGroupStreams::SendConnectionOpenRequest(
198*3f982cf4SFabien Sanglard ConnectionOpenRequest request) {
199*3f982cf4SFabien Sanglard uint64_t request_id = GetNextInternalRequestId();
200*3f982cf4SFabien Sanglard if (!connection_protocol_connection_ && !connection_connect_request_) {
201*3f982cf4SFabien Sanglard connection_connect_request_stack_ = true;
202*3f982cf4SFabien Sanglard connection_connect_request_ =
203*3f982cf4SFabien Sanglard NetworkServiceManager::Get()->GetProtocolConnectionClient()->Connect(
204*3f982cf4SFabien Sanglard controller_->receiver_endpoints_[service_id_], this);
205*3f982cf4SFabien Sanglard connection_connect_request_stack_ = false;
206*3f982cf4SFabien Sanglard }
207*3f982cf4SFabien Sanglard connection_open_handler_.WriteMessage(request_id, std::move(request));
208*3f982cf4SFabien Sanglard return request_id;
209*3f982cf4SFabien Sanglard }
210*3f982cf4SFabien Sanglard
CancelConnectionOpenRequest(uint64_t request_id)211*3f982cf4SFabien Sanglard void Controller::MessageGroupStreams::CancelConnectionOpenRequest(
212*3f982cf4SFabien Sanglard uint64_t request_id) {
213*3f982cf4SFabien Sanglard connection_open_handler_.CancelMessage(request_id);
214*3f982cf4SFabien Sanglard }
215*3f982cf4SFabien Sanglard
OnMatchedResponse(ConnectionOpenRequest * request,msgs::PresentationConnectionOpenResponse * response,uint64_t endpoint_id)216*3f982cf4SFabien Sanglard void Controller::MessageGroupStreams::OnMatchedResponse(
217*3f982cf4SFabien Sanglard ConnectionOpenRequest* request,
218*3f982cf4SFabien Sanglard msgs::PresentationConnectionOpenResponse* response,
219*3f982cf4SFabien Sanglard uint64_t endpoint_id) {
220*3f982cf4SFabien Sanglard if (response->result !=
221*3f982cf4SFabien Sanglard msgs::PresentationConnectionOpenResponse_result::kSuccess) {
222*3f982cf4SFabien Sanglard std::stringstream ss;
223*3f982cf4SFabien Sanglard ss << "presentation-connection-open-response for " << request->request.url
224*3f982cf4SFabien Sanglard << " failed: " << static_cast<int>(response->result);
225*3f982cf4SFabien Sanglard Error error(Error::Code::kUnknownStartError, ss.str());
226*3f982cf4SFabien Sanglard OSP_LOG_INFO << error.message();
227*3f982cf4SFabien Sanglard request->delegate->OnError(std::move(error));
228*3f982cf4SFabien Sanglard return;
229*3f982cf4SFabien Sanglard }
230*3f982cf4SFabien Sanglard OSP_LOG_INFO << "presentation connection opened to "
231*3f982cf4SFabien Sanglard << request->request.presentation_id;
232*3f982cf4SFabien Sanglard if (request->presentation_connection_delegate) {
233*3f982cf4SFabien Sanglard request->connection = std::make_unique<Connection>(
234*3f982cf4SFabien Sanglard Connection::PresentationInfo{request->request.presentation_id,
235*3f982cf4SFabien Sanglard request->request.url},
236*3f982cf4SFabien Sanglard request->presentation_connection_delegate, controller_);
237*3f982cf4SFabien Sanglard }
238*3f982cf4SFabien Sanglard std::unique_ptr<ProtocolConnection> protocol_connection =
239*3f982cf4SFabien Sanglard NetworkServiceManager::Get()
240*3f982cf4SFabien Sanglard ->GetProtocolConnectionClient()
241*3f982cf4SFabien Sanglard ->CreateProtocolConnection(endpoint_id);
242*3f982cf4SFabien Sanglard request->connection->OnConnected(response->connection_id, endpoint_id,
243*3f982cf4SFabien Sanglard std::move(protocol_connection));
244*3f982cf4SFabien Sanglard controller_->AddConnection(request->connection.get());
245*3f982cf4SFabien Sanglard request->delegate->OnConnection(std::move(request->connection));
246*3f982cf4SFabien Sanglard }
247*3f982cf4SFabien Sanglard
OnError(ConnectionOpenRequest * request,Error error)248*3f982cf4SFabien Sanglard void Controller::MessageGroupStreams::OnError(ConnectionOpenRequest* request,
249*3f982cf4SFabien Sanglard Error error) {
250*3f982cf4SFabien Sanglard request->delegate->OnError(std::move(error));
251*3f982cf4SFabien Sanglard }
252*3f982cf4SFabien Sanglard
SendConnectionCloseRequest(ConnectionCloseRequest request)253*3f982cf4SFabien Sanglard void Controller::MessageGroupStreams::SendConnectionCloseRequest(
254*3f982cf4SFabien Sanglard ConnectionCloseRequest request) {
255*3f982cf4SFabien Sanglard if (!connection_protocol_connection_ && !connection_connect_request_) {
256*3f982cf4SFabien Sanglard connection_connect_request_stack_ = true;
257*3f982cf4SFabien Sanglard connection_connect_request_ =
258*3f982cf4SFabien Sanglard NetworkServiceManager::Get()->GetProtocolConnectionClient()->Connect(
259*3f982cf4SFabien Sanglard controller_->receiver_endpoints_[service_id_], this);
260*3f982cf4SFabien Sanglard connection_connect_request_stack_ = false;
261*3f982cf4SFabien Sanglard }
262*3f982cf4SFabien Sanglard connection_close_handler_.WriteMessage(std::move(request));
263*3f982cf4SFabien Sanglard }
264*3f982cf4SFabien Sanglard
OnMatchedResponse(ConnectionCloseRequest * request,msgs::PresentationConnectionCloseResponse * response,uint64_t endpoint_id)265*3f982cf4SFabien Sanglard void Controller::MessageGroupStreams::OnMatchedResponse(
266*3f982cf4SFabien Sanglard ConnectionCloseRequest* request,
267*3f982cf4SFabien Sanglard msgs::PresentationConnectionCloseResponse* response,
268*3f982cf4SFabien Sanglard uint64_t endpoint_id) {
269*3f982cf4SFabien Sanglard OSP_LOG_IF(INFO,
270*3f982cf4SFabien Sanglard response->result !=
271*3f982cf4SFabien Sanglard msgs::PresentationConnectionCloseResponse_result::kSuccess)
272*3f982cf4SFabien Sanglard << "error in presentation-connection-close-response: "
273*3f982cf4SFabien Sanglard << static_cast<int>(response->result);
274*3f982cf4SFabien Sanglard }
275*3f982cf4SFabien Sanglard
OnError(ConnectionCloseRequest * request,Error error)276*3f982cf4SFabien Sanglard void Controller::MessageGroupStreams::OnError(ConnectionCloseRequest* request,
277*3f982cf4SFabien Sanglard Error error) {
278*3f982cf4SFabien Sanglard OSP_LOG_INFO << "got error when closing connection "
279*3f982cf4SFabien Sanglard << request->request.connection_id << ": " << error;
280*3f982cf4SFabien Sanglard }
281*3f982cf4SFabien Sanglard
SendTerminationRequest(TerminationRequest request)282*3f982cf4SFabien Sanglard void Controller::MessageGroupStreams::SendTerminationRequest(
283*3f982cf4SFabien Sanglard TerminationRequest request) {
284*3f982cf4SFabien Sanglard if (!initiation_protocol_connection_ && !initiation_connect_request_) {
285*3f982cf4SFabien Sanglard initiation_connect_request_ =
286*3f982cf4SFabien Sanglard NetworkServiceManager::Get()->GetProtocolConnectionClient()->Connect(
287*3f982cf4SFabien Sanglard controller_->receiver_endpoints_[service_id_], this);
288*3f982cf4SFabien Sanglard }
289*3f982cf4SFabien Sanglard termination_handler_.WriteMessage(std::move(request));
290*3f982cf4SFabien Sanglard }
291*3f982cf4SFabien Sanglard
OnMatchedResponse(TerminationRequest * request,msgs::PresentationTerminationResponse * response,uint64_t endpoint_id)292*3f982cf4SFabien Sanglard void Controller::MessageGroupStreams::OnMatchedResponse(
293*3f982cf4SFabien Sanglard TerminationRequest* request,
294*3f982cf4SFabien Sanglard msgs::PresentationTerminationResponse* response,
295*3f982cf4SFabien Sanglard uint64_t endpoint_id) {
296*3f982cf4SFabien Sanglard OSP_VLOG << "got presentation-termination-response for "
297*3f982cf4SFabien Sanglard << request->request.presentation_id << " with result "
298*3f982cf4SFabien Sanglard << static_cast<int>(response->result);
299*3f982cf4SFabien Sanglard controller_->TerminatePresentationById(request->request.presentation_id);
300*3f982cf4SFabien Sanglard }
301*3f982cf4SFabien Sanglard
OnError(TerminationRequest * request,Error error)302*3f982cf4SFabien Sanglard void Controller::MessageGroupStreams::OnError(TerminationRequest* request,
303*3f982cf4SFabien Sanglard Error error) {}
304*3f982cf4SFabien Sanglard
OnConnectionOpened(uint64_t request_id,std::unique_ptr<ProtocolConnection> connection)305*3f982cf4SFabien Sanglard void Controller::MessageGroupStreams::OnConnectionOpened(
306*3f982cf4SFabien Sanglard uint64_t request_id,
307*3f982cf4SFabien Sanglard std::unique_ptr<ProtocolConnection> connection) {
308*3f982cf4SFabien Sanglard if ((initiation_connect_request_ &&
309*3f982cf4SFabien Sanglard initiation_connect_request_.request_id() == request_id) ||
310*3f982cf4SFabien Sanglard initiation_connect_request_stack_) {
311*3f982cf4SFabien Sanglard initiation_protocol_connection_ = std::move(connection);
312*3f982cf4SFabien Sanglard initiation_protocol_connection_->SetObserver(this);
313*3f982cf4SFabien Sanglard initiation_connect_request_.MarkComplete();
314*3f982cf4SFabien Sanglard initiation_handler_.SetConnection(initiation_protocol_connection_.get());
315*3f982cf4SFabien Sanglard termination_handler_.SetConnection(initiation_protocol_connection_.get());
316*3f982cf4SFabien Sanglard } else if ((connection_connect_request_ &&
317*3f982cf4SFabien Sanglard connection_connect_request_.request_id() == request_id) ||
318*3f982cf4SFabien Sanglard connection_connect_request_stack_) {
319*3f982cf4SFabien Sanglard connection_protocol_connection_ = std::move(connection);
320*3f982cf4SFabien Sanglard connection_protocol_connection_->SetObserver(this);
321*3f982cf4SFabien Sanglard connection_connect_request_.MarkComplete();
322*3f982cf4SFabien Sanglard connection_open_handler_.SetConnection(
323*3f982cf4SFabien Sanglard connection_protocol_connection_.get());
324*3f982cf4SFabien Sanglard connection_close_handler_.SetConnection(
325*3f982cf4SFabien Sanglard connection_protocol_connection_.get());
326*3f982cf4SFabien Sanglard }
327*3f982cf4SFabien Sanglard }
328*3f982cf4SFabien Sanglard
OnConnectionFailed(uint64_t request_id)329*3f982cf4SFabien Sanglard void Controller::MessageGroupStreams::OnConnectionFailed(uint64_t request_id) {
330*3f982cf4SFabien Sanglard if (initiation_connect_request_ &&
331*3f982cf4SFabien Sanglard initiation_connect_request_.request_id() == request_id) {
332*3f982cf4SFabien Sanglard initiation_connect_request_.MarkComplete();
333*3f982cf4SFabien Sanglard initiation_handler_.Reset();
334*3f982cf4SFabien Sanglard termination_handler_.Reset();
335*3f982cf4SFabien Sanglard } else if (connection_connect_request_ &&
336*3f982cf4SFabien Sanglard connection_connect_request_.request_id() == request_id) {
337*3f982cf4SFabien Sanglard connection_connect_request_.MarkComplete();
338*3f982cf4SFabien Sanglard connection_open_handler_.Reset();
339*3f982cf4SFabien Sanglard connection_close_handler_.Reset();
340*3f982cf4SFabien Sanglard }
341*3f982cf4SFabien Sanglard }
342*3f982cf4SFabien Sanglard
OnConnectionClosed(const ProtocolConnection & connection)343*3f982cf4SFabien Sanglard void Controller::MessageGroupStreams::OnConnectionClosed(
344*3f982cf4SFabien Sanglard const ProtocolConnection& connection) {
345*3f982cf4SFabien Sanglard if (&connection == initiation_protocol_connection_.get()) {
346*3f982cf4SFabien Sanglard initiation_handler_.Reset();
347*3f982cf4SFabien Sanglard termination_handler_.Reset();
348*3f982cf4SFabien Sanglard }
349*3f982cf4SFabien Sanglard }
350*3f982cf4SFabien Sanglard
GetNextInternalRequestId()351*3f982cf4SFabien Sanglard uint64_t Controller::MessageGroupStreams::GetNextInternalRequestId() {
352*3f982cf4SFabien Sanglard return ++next_internal_request_id_;
353*3f982cf4SFabien Sanglard }
354*3f982cf4SFabien Sanglard
355*3f982cf4SFabien Sanglard Controller::ReceiverWatch::ReceiverWatch() = default;
ReceiverWatch(Controller * controller,const std::vector<std::string> & urls,ReceiverObserver * observer)356*3f982cf4SFabien Sanglard Controller::ReceiverWatch::ReceiverWatch(Controller* controller,
357*3f982cf4SFabien Sanglard const std::vector<std::string>& urls,
358*3f982cf4SFabien Sanglard ReceiverObserver* observer)
359*3f982cf4SFabien Sanglard : urls_(urls), observer_(observer), controller_(controller) {}
360*3f982cf4SFabien Sanglard
ReceiverWatch(Controller::ReceiverWatch && other)361*3f982cf4SFabien Sanglard Controller::ReceiverWatch::ReceiverWatch(
362*3f982cf4SFabien Sanglard Controller::ReceiverWatch&& other) noexcept {
363*3f982cf4SFabien Sanglard swap(*this, other);
364*3f982cf4SFabien Sanglard }
365*3f982cf4SFabien Sanglard
~ReceiverWatch()366*3f982cf4SFabien Sanglard Controller::ReceiverWatch::~ReceiverWatch() {
367*3f982cf4SFabien Sanglard if (observer_) {
368*3f982cf4SFabien Sanglard controller_->CancelReceiverWatch(urls_, observer_);
369*3f982cf4SFabien Sanglard }
370*3f982cf4SFabien Sanglard observer_ = nullptr;
371*3f982cf4SFabien Sanglard }
372*3f982cf4SFabien Sanglard
operator =(Controller::ReceiverWatch other)373*3f982cf4SFabien Sanglard Controller::ReceiverWatch& Controller::ReceiverWatch::operator=(
374*3f982cf4SFabien Sanglard Controller::ReceiverWatch other) {
375*3f982cf4SFabien Sanglard swap(*this, other);
376*3f982cf4SFabien Sanglard return *this;
377*3f982cf4SFabien Sanglard }
378*3f982cf4SFabien Sanglard
swap(Controller::ReceiverWatch & a,Controller::ReceiverWatch & b)379*3f982cf4SFabien Sanglard void swap(Controller::ReceiverWatch& a, Controller::ReceiverWatch& b) {
380*3f982cf4SFabien Sanglard using std::swap;
381*3f982cf4SFabien Sanglard swap(a.urls_, b.urls_);
382*3f982cf4SFabien Sanglard swap(a.observer_, b.observer_);
383*3f982cf4SFabien Sanglard swap(a.controller_, b.controller_);
384*3f982cf4SFabien Sanglard }
385*3f982cf4SFabien Sanglard
386*3f982cf4SFabien Sanglard Controller::ConnectRequest::ConnectRequest() = default;
ConnectRequest(Controller * controller,const std::string & service_id,bool is_reconnect,absl::optional<uint64_t> request_id)387*3f982cf4SFabien Sanglard Controller::ConnectRequest::ConnectRequest(Controller* controller,
388*3f982cf4SFabien Sanglard const std::string& service_id,
389*3f982cf4SFabien Sanglard bool is_reconnect,
390*3f982cf4SFabien Sanglard absl::optional<uint64_t> request_id)
391*3f982cf4SFabien Sanglard : service_id_(service_id),
392*3f982cf4SFabien Sanglard is_reconnect_(is_reconnect),
393*3f982cf4SFabien Sanglard request_id_(request_id),
394*3f982cf4SFabien Sanglard controller_(controller) {}
395*3f982cf4SFabien Sanglard
ConnectRequest(ConnectRequest && other)396*3f982cf4SFabien Sanglard Controller::ConnectRequest::ConnectRequest(ConnectRequest&& other) noexcept {
397*3f982cf4SFabien Sanglard swap(*this, other);
398*3f982cf4SFabien Sanglard }
399*3f982cf4SFabien Sanglard
~ConnectRequest()400*3f982cf4SFabien Sanglard Controller::ConnectRequest::~ConnectRequest() {
401*3f982cf4SFabien Sanglard if (request_id_) {
402*3f982cf4SFabien Sanglard controller_->CancelConnectRequest(service_id_, is_reconnect_,
403*3f982cf4SFabien Sanglard request_id_.value());
404*3f982cf4SFabien Sanglard }
405*3f982cf4SFabien Sanglard request_id_ = 0;
406*3f982cf4SFabien Sanglard }
407*3f982cf4SFabien Sanglard
operator =(ConnectRequest other)408*3f982cf4SFabien Sanglard Controller::ConnectRequest& Controller::ConnectRequest::operator=(
409*3f982cf4SFabien Sanglard ConnectRequest other) {
410*3f982cf4SFabien Sanglard swap(*this, other);
411*3f982cf4SFabien Sanglard return *this;
412*3f982cf4SFabien Sanglard }
413*3f982cf4SFabien Sanglard
swap(Controller::ConnectRequest & a,Controller::ConnectRequest & b)414*3f982cf4SFabien Sanglard void swap(Controller::ConnectRequest& a, Controller::ConnectRequest& b) {
415*3f982cf4SFabien Sanglard using std::swap;
416*3f982cf4SFabien Sanglard swap(a.service_id_, b.service_id_);
417*3f982cf4SFabien Sanglard swap(a.is_reconnect_, b.is_reconnect_);
418*3f982cf4SFabien Sanglard swap(a.request_id_, b.request_id_);
419*3f982cf4SFabien Sanglard swap(a.controller_, b.controller_);
420*3f982cf4SFabien Sanglard }
421*3f982cf4SFabien Sanglard
Controller(ClockNowFunctionPtr now_function)422*3f982cf4SFabien Sanglard Controller::Controller(ClockNowFunctionPtr now_function) {
423*3f982cf4SFabien Sanglard availability_requester_ =
424*3f982cf4SFabien Sanglard std::make_unique<UrlAvailabilityRequester>(now_function);
425*3f982cf4SFabien Sanglard connection_manager_ =
426*3f982cf4SFabien Sanglard std::make_unique<ConnectionManager>(NetworkServiceManager::Get()
427*3f982cf4SFabien Sanglard ->GetProtocolConnectionClient()
428*3f982cf4SFabien Sanglard ->message_demuxer());
429*3f982cf4SFabien Sanglard const std::vector<ServiceInfo>& receivers =
430*3f982cf4SFabien Sanglard NetworkServiceManager::Get()->GetMdnsServiceListener()->GetReceivers();
431*3f982cf4SFabien Sanglard for (const auto& info : receivers) {
432*3f982cf4SFabien Sanglard // TODO(crbug.com/openscreen/33): Replace service_id with endpoint_id when
433*3f982cf4SFabien Sanglard // endpoint_id is more than just an IPEndpoint counter and actually relates
434*3f982cf4SFabien Sanglard // to a device's identity.
435*3f982cf4SFabien Sanglard receiver_endpoints_.emplace(info.service_id, info.v4_endpoint.port
436*3f982cf4SFabien Sanglard ? info.v4_endpoint
437*3f982cf4SFabien Sanglard : info.v6_endpoint);
438*3f982cf4SFabien Sanglard availability_requester_->AddReceiver(info);
439*3f982cf4SFabien Sanglard }
440*3f982cf4SFabien Sanglard // TODO(btolsch): This is for |receiver_endpoints_|, but this should really be
441*3f982cf4SFabien Sanglard // tracked elsewhere so it's available to other protocols as well.
442*3f982cf4SFabien Sanglard NetworkServiceManager::Get()->GetMdnsServiceListener()->AddObserver(this);
443*3f982cf4SFabien Sanglard }
444*3f982cf4SFabien Sanglard
~Controller()445*3f982cf4SFabien Sanglard Controller::~Controller() {
446*3f982cf4SFabien Sanglard connection_manager_.reset();
447*3f982cf4SFabien Sanglard NetworkServiceManager::Get()->GetMdnsServiceListener()->RemoveObserver(this);
448*3f982cf4SFabien Sanglard }
449*3f982cf4SFabien Sanglard
RegisterReceiverWatch(const std::vector<std::string> & urls,ReceiverObserver * observer)450*3f982cf4SFabien Sanglard Controller::ReceiverWatch Controller::RegisterReceiverWatch(
451*3f982cf4SFabien Sanglard const std::vector<std::string>& urls,
452*3f982cf4SFabien Sanglard ReceiverObserver* observer) {
453*3f982cf4SFabien Sanglard availability_requester_->AddObserver(urls, observer);
454*3f982cf4SFabien Sanglard return ReceiverWatch(this, urls, observer);
455*3f982cf4SFabien Sanglard }
456*3f982cf4SFabien Sanglard
StartPresentation(const std::string & url,const std::string & service_id,RequestDelegate * delegate,Connection::Delegate * conn_delegate)457*3f982cf4SFabien Sanglard Controller::ConnectRequest Controller::StartPresentation(
458*3f982cf4SFabien Sanglard const std::string& url,
459*3f982cf4SFabien Sanglard const std::string& service_id,
460*3f982cf4SFabien Sanglard RequestDelegate* delegate,
461*3f982cf4SFabien Sanglard Connection::Delegate* conn_delegate) {
462*3f982cf4SFabien Sanglard StartRequest request;
463*3f982cf4SFabien Sanglard request.request.url = url;
464*3f982cf4SFabien Sanglard request.request.presentation_id = MakePresentationId(url, service_id);
465*3f982cf4SFabien Sanglard request.delegate = delegate;
466*3f982cf4SFabien Sanglard request.presentation_connection_delegate = conn_delegate;
467*3f982cf4SFabien Sanglard uint64_t request_id =
468*3f982cf4SFabien Sanglard group_streams_[service_id]->SendStartRequest(std::move(request));
469*3f982cf4SFabien Sanglard constexpr bool is_reconnect = false;
470*3f982cf4SFabien Sanglard return ConnectRequest(this, service_id, is_reconnect, request_id);
471*3f982cf4SFabien Sanglard }
472*3f982cf4SFabien Sanglard
ReconnectPresentation(const std::vector<std::string> & urls,const std::string & presentation_id,const std::string & service_id,RequestDelegate * delegate,Connection::Delegate * conn_delegate)473*3f982cf4SFabien Sanglard Controller::ConnectRequest Controller::ReconnectPresentation(
474*3f982cf4SFabien Sanglard const std::vector<std::string>& urls,
475*3f982cf4SFabien Sanglard const std::string& presentation_id,
476*3f982cf4SFabien Sanglard const std::string& service_id,
477*3f982cf4SFabien Sanglard RequestDelegate* delegate,
478*3f982cf4SFabien Sanglard Connection::Delegate* conn_delegate) {
479*3f982cf4SFabien Sanglard auto presentation_entry = presentations_.find(presentation_id);
480*3f982cf4SFabien Sanglard if (presentation_entry == presentations_.end()) {
481*3f982cf4SFabien Sanglard delegate->OnError(Error::Code::kNoPresentationFound);
482*3f982cf4SFabien Sanglard return ConnectRequest();
483*3f982cf4SFabien Sanglard }
484*3f982cf4SFabien Sanglard auto matching_url_it =
485*3f982cf4SFabien Sanglard std::find(urls.begin(), urls.end(), presentation_entry->second.url);
486*3f982cf4SFabien Sanglard if (matching_url_it == urls.end()) {
487*3f982cf4SFabien Sanglard delegate->OnError(Error::Code::kNoPresentationFound);
488*3f982cf4SFabien Sanglard return ConnectRequest();
489*3f982cf4SFabien Sanglard }
490*3f982cf4SFabien Sanglard ConnectionOpenRequest request;
491*3f982cf4SFabien Sanglard request.request.url = presentation_entry->second.url;
492*3f982cf4SFabien Sanglard request.request.presentation_id = presentation_id;
493*3f982cf4SFabien Sanglard request.delegate = delegate;
494*3f982cf4SFabien Sanglard request.presentation_connection_delegate = conn_delegate;
495*3f982cf4SFabien Sanglard request.connection = nullptr;
496*3f982cf4SFabien Sanglard uint64_t request_id =
497*3f982cf4SFabien Sanglard group_streams_[service_id]->SendConnectionOpenRequest(std::move(request));
498*3f982cf4SFabien Sanglard constexpr bool is_reconnect = true;
499*3f982cf4SFabien Sanglard return ConnectRequest(this, service_id, is_reconnect, request_id);
500*3f982cf4SFabien Sanglard }
501*3f982cf4SFabien Sanglard
ReconnectConnection(std::unique_ptr<Connection> connection,RequestDelegate * delegate)502*3f982cf4SFabien Sanglard Controller::ConnectRequest Controller::ReconnectConnection(
503*3f982cf4SFabien Sanglard std::unique_ptr<Connection> connection,
504*3f982cf4SFabien Sanglard RequestDelegate* delegate) {
505*3f982cf4SFabien Sanglard if (connection->state() != Connection::State::kClosed) {
506*3f982cf4SFabien Sanglard delegate->OnError(Error::Code::kInvalidConnectionState);
507*3f982cf4SFabien Sanglard return ConnectRequest();
508*3f982cf4SFabien Sanglard }
509*3f982cf4SFabien Sanglard const Connection::PresentationInfo& info = connection->presentation_info();
510*3f982cf4SFabien Sanglard auto presentation_entry = presentations_.find(info.id);
511*3f982cf4SFabien Sanglard if (presentation_entry == presentations_.end() ||
512*3f982cf4SFabien Sanglard presentation_entry->second.url != info.url) {
513*3f982cf4SFabien Sanglard OSP_LOG_ERROR << "missing ControlledPresentation for non-terminated "
514*3f982cf4SFabien Sanglard "connection with info ("
515*3f982cf4SFabien Sanglard << info.id << ", " << info.url << ")";
516*3f982cf4SFabien Sanglard delegate->OnError(Error::Code::kNoPresentationFound);
517*3f982cf4SFabien Sanglard return ConnectRequest();
518*3f982cf4SFabien Sanglard }
519*3f982cf4SFabien Sanglard OSP_DCHECK(connection_manager_->GetConnection(connection->connection_id()))
520*3f982cf4SFabien Sanglard << "otherwise valid connection for reconnect is unknown to the "
521*3f982cf4SFabien Sanglard "connection manager";
522*3f982cf4SFabien Sanglard connection_manager_->RemoveConnection(connection.get());
523*3f982cf4SFabien Sanglard connection->OnConnecting();
524*3f982cf4SFabien Sanglard ConnectionOpenRequest request;
525*3f982cf4SFabien Sanglard request.request.url = info.url;
526*3f982cf4SFabien Sanglard request.request.presentation_id = info.id;
527*3f982cf4SFabien Sanglard request.delegate = delegate;
528*3f982cf4SFabien Sanglard request.presentation_connection_delegate = nullptr;
529*3f982cf4SFabien Sanglard request.connection = std::move(connection);
530*3f982cf4SFabien Sanglard const std::string& service_id = presentation_entry->second.service_id;
531*3f982cf4SFabien Sanglard uint64_t request_id =
532*3f982cf4SFabien Sanglard group_streams_[service_id]->SendConnectionOpenRequest(std::move(request));
533*3f982cf4SFabien Sanglard constexpr bool is_reconnect = true;
534*3f982cf4SFabien Sanglard return ConnectRequest(this, service_id, is_reconnect, request_id);
535*3f982cf4SFabien Sanglard }
536*3f982cf4SFabien Sanglard
CloseConnection(Connection * connection,Connection::CloseReason reason)537*3f982cf4SFabien Sanglard Error Controller::CloseConnection(Connection* connection,
538*3f982cf4SFabien Sanglard Connection::CloseReason reason) {
539*3f982cf4SFabien Sanglard auto presentation_entry =
540*3f982cf4SFabien Sanglard presentations_.find(connection->presentation_info().id);
541*3f982cf4SFabien Sanglard if (presentation_entry == presentations_.end()) {
542*3f982cf4SFabien Sanglard std::stringstream ss;
543*3f982cf4SFabien Sanglard ss << "no presentation found when trying to close connection "
544*3f982cf4SFabien Sanglard << connection->presentation_info().id << ":"
545*3f982cf4SFabien Sanglard << connection->connection_id();
546*3f982cf4SFabien Sanglard return Error(Error::Code::kNoPresentationFound, ss.str());
547*3f982cf4SFabien Sanglard }
548*3f982cf4SFabien Sanglard ConnectionCloseRequest request;
549*3f982cf4SFabien Sanglard request.request.connection_id = connection->connection_id();
550*3f982cf4SFabien Sanglard group_streams_[presentation_entry->second.service_id]
551*3f982cf4SFabien Sanglard ->SendConnectionCloseRequest(std::move(request));
552*3f982cf4SFabien Sanglard return Error::None();
553*3f982cf4SFabien Sanglard }
554*3f982cf4SFabien Sanglard
OnPresentationTerminated(const std::string & presentation_id,TerminationReason reason)555*3f982cf4SFabien Sanglard Error Controller::OnPresentationTerminated(const std::string& presentation_id,
556*3f982cf4SFabien Sanglard TerminationReason reason) {
557*3f982cf4SFabien Sanglard auto presentation_entry = presentations_.find(presentation_id);
558*3f982cf4SFabien Sanglard if (presentation_entry == presentations_.end()) {
559*3f982cf4SFabien Sanglard return Error::Code::kNoPresentationFound;
560*3f982cf4SFabien Sanglard }
561*3f982cf4SFabien Sanglard ControlledPresentation& presentation = presentation_entry->second;
562*3f982cf4SFabien Sanglard for (auto* connection : presentation.connections) {
563*3f982cf4SFabien Sanglard connection->OnTerminated();
564*3f982cf4SFabien Sanglard }
565*3f982cf4SFabien Sanglard TerminationRequest request;
566*3f982cf4SFabien Sanglard request.request.presentation_id = presentation_id;
567*3f982cf4SFabien Sanglard request.request.reason =
568*3f982cf4SFabien Sanglard msgs::PresentationTerminationRequest_reason::kUserTerminatedViaController;
569*3f982cf4SFabien Sanglard group_streams_[presentation.service_id]->SendTerminationRequest(
570*3f982cf4SFabien Sanglard std::move(request));
571*3f982cf4SFabien Sanglard presentations_.erase(presentation_entry);
572*3f982cf4SFabien Sanglard termination_listener_by_id_.erase(presentation_id);
573*3f982cf4SFabien Sanglard return Error::None();
574*3f982cf4SFabien Sanglard }
575*3f982cf4SFabien Sanglard
OnConnectionDestroyed(Connection * connection)576*3f982cf4SFabien Sanglard void Controller::OnConnectionDestroyed(Connection* connection) {
577*3f982cf4SFabien Sanglard auto presentation_entry =
578*3f982cf4SFabien Sanglard presentations_.find(connection->presentation_info().id);
579*3f982cf4SFabien Sanglard if (presentation_entry == presentations_.end()) {
580*3f982cf4SFabien Sanglard return;
581*3f982cf4SFabien Sanglard }
582*3f982cf4SFabien Sanglard
583*3f982cf4SFabien Sanglard std::vector<Connection*>& connections =
584*3f982cf4SFabien Sanglard presentation_entry->second.connections;
585*3f982cf4SFabien Sanglard
586*3f982cf4SFabien Sanglard connections.erase(
587*3f982cf4SFabien Sanglard std::remove(connections.begin(), connections.end(), connection),
588*3f982cf4SFabien Sanglard connections.end());
589*3f982cf4SFabien Sanglard
590*3f982cf4SFabien Sanglard connection_manager_->RemoveConnection(connection);
591*3f982cf4SFabien Sanglard }
592*3f982cf4SFabien Sanglard
GetServiceIdForPresentationId(const std::string & presentation_id) const593*3f982cf4SFabien Sanglard std::string Controller::GetServiceIdForPresentationId(
594*3f982cf4SFabien Sanglard const std::string& presentation_id) const {
595*3f982cf4SFabien Sanglard auto presentation_entry = presentations_.find(presentation_id);
596*3f982cf4SFabien Sanglard if (presentation_entry == presentations_.end()) {
597*3f982cf4SFabien Sanglard return "";
598*3f982cf4SFabien Sanglard }
599*3f982cf4SFabien Sanglard return presentation_entry->second.service_id;
600*3f982cf4SFabien Sanglard }
601*3f982cf4SFabien Sanglard
GetConnectionRequestGroupStream(const std::string & service_id)602*3f982cf4SFabien Sanglard ProtocolConnection* Controller::GetConnectionRequestGroupStream(
603*3f982cf4SFabien Sanglard const std::string& service_id) {
604*3f982cf4SFabien Sanglard OSP_UNIMPLEMENTED();
605*3f982cf4SFabien Sanglard return nullptr;
606*3f982cf4SFabien Sanglard }
607*3f982cf4SFabien Sanglard
OnError(ServiceListenerError)608*3f982cf4SFabien Sanglard void Controller::OnError(ServiceListenerError) {}
OnMetrics(ServiceListener::Metrics)609*3f982cf4SFabien Sanglard void Controller::OnMetrics(ServiceListener::Metrics) {}
610*3f982cf4SFabien Sanglard
611*3f982cf4SFabien Sanglard class Controller::TerminationListener final
612*3f982cf4SFabien Sanglard : public MessageDemuxer::MessageCallback {
613*3f982cf4SFabien Sanglard public:
614*3f982cf4SFabien Sanglard TerminationListener(Controller* controller,
615*3f982cf4SFabien Sanglard const std::string& presentation_id,
616*3f982cf4SFabien Sanglard uint64_t endpoint_id);
617*3f982cf4SFabien Sanglard ~TerminationListener() override;
618*3f982cf4SFabien Sanglard
619*3f982cf4SFabien Sanglard // MessageDemuxer::MessageCallback overrides.
620*3f982cf4SFabien Sanglard ErrorOr<size_t> OnStreamMessage(uint64_t endpoint_id,
621*3f982cf4SFabien Sanglard uint64_t connection_id,
622*3f982cf4SFabien Sanglard msgs::Type message_type,
623*3f982cf4SFabien Sanglard const uint8_t* buffer,
624*3f982cf4SFabien Sanglard size_t buffer_size,
625*3f982cf4SFabien Sanglard Clock::time_point now) override;
626*3f982cf4SFabien Sanglard
627*3f982cf4SFabien Sanglard private:
628*3f982cf4SFabien Sanglard Controller* const controller_;
629*3f982cf4SFabien Sanglard std::string presentation_id_;
630*3f982cf4SFabien Sanglard MessageDemuxer::MessageWatch event_watch_;
631*3f982cf4SFabien Sanglard };
632*3f982cf4SFabien Sanglard
TerminationListener(Controller * controller,const std::string & presentation_id,uint64_t endpoint_id)633*3f982cf4SFabien Sanglard Controller::TerminationListener::TerminationListener(
634*3f982cf4SFabien Sanglard Controller* controller,
635*3f982cf4SFabien Sanglard const std::string& presentation_id,
636*3f982cf4SFabien Sanglard uint64_t endpoint_id)
637*3f982cf4SFabien Sanglard : controller_(controller), presentation_id_(presentation_id) {
638*3f982cf4SFabien Sanglard event_watch_ =
639*3f982cf4SFabien Sanglard NetworkServiceManager::Get()
640*3f982cf4SFabien Sanglard ->GetProtocolConnectionClient()
641*3f982cf4SFabien Sanglard ->message_demuxer()
642*3f982cf4SFabien Sanglard ->WatchMessageType(endpoint_id,
643*3f982cf4SFabien Sanglard msgs::Type::kPresentationTerminationEvent, this);
644*3f982cf4SFabien Sanglard }
645*3f982cf4SFabien Sanglard
646*3f982cf4SFabien Sanglard Controller::TerminationListener::~TerminationListener() = default;
647*3f982cf4SFabien Sanglard
OnStreamMessage(uint64_t endpoint_id,uint64_t connection_id,msgs::Type message_type,const uint8_t * buffer,size_t buffer_size,Clock::time_point now)648*3f982cf4SFabien Sanglard ErrorOr<size_t> Controller::TerminationListener::OnStreamMessage(
649*3f982cf4SFabien Sanglard uint64_t endpoint_id,
650*3f982cf4SFabien Sanglard uint64_t connection_id,
651*3f982cf4SFabien Sanglard msgs::Type message_type,
652*3f982cf4SFabien Sanglard const uint8_t* buffer,
653*3f982cf4SFabien Sanglard size_t buffer_size,
654*3f982cf4SFabien Sanglard Clock::time_point now) {
655*3f982cf4SFabien Sanglard OSP_CHECK_EQ(static_cast<int>(msgs::Type::kPresentationTerminationEvent),
656*3f982cf4SFabien Sanglard static_cast<int>(message_type));
657*3f982cf4SFabien Sanglard msgs::PresentationTerminationEvent event;
658*3f982cf4SFabien Sanglard ssize_t result =
659*3f982cf4SFabien Sanglard msgs::DecodePresentationTerminationEvent(buffer, buffer_size, &event);
660*3f982cf4SFabien Sanglard if (result < 0) {
661*3f982cf4SFabien Sanglard OSP_LOG_WARN << "decode presentation-termination-event error: " << result;
662*3f982cf4SFabien Sanglard return Error::Code::kCborParsing;
663*3f982cf4SFabien Sanglard } else if (event.presentation_id != presentation_id_) {
664*3f982cf4SFabien Sanglard OSP_LOG_WARN << "got presentation-termination-event for wrong id: "
665*3f982cf4SFabien Sanglard << presentation_id_ << " vs. " << event.presentation_id;
666*3f982cf4SFabien Sanglard return result;
667*3f982cf4SFabien Sanglard }
668*3f982cf4SFabien Sanglard OSP_LOG_INFO << "termination event";
669*3f982cf4SFabien Sanglard auto presentation_entry =
670*3f982cf4SFabien Sanglard controller_->presentations_.find(event.presentation_id);
671*3f982cf4SFabien Sanglard if (presentation_entry != controller_->presentations_.end()) {
672*3f982cf4SFabien Sanglard for (auto* connection : presentation_entry->second.connections)
673*3f982cf4SFabien Sanglard connection->OnTerminated();
674*3f982cf4SFabien Sanglard controller_->presentations_.erase(presentation_entry);
675*3f982cf4SFabien Sanglard }
676*3f982cf4SFabien Sanglard controller_->termination_listener_by_id_.erase(event.presentation_id);
677*3f982cf4SFabien Sanglard return result;
678*3f982cf4SFabien Sanglard }
679*3f982cf4SFabien Sanglard
680*3f982cf4SFabien Sanglard // static
MakePresentationId(const std::string & url,const std::string & service_id)681*3f982cf4SFabien Sanglard std::string Controller::MakePresentationId(const std::string& url,
682*3f982cf4SFabien Sanglard const std::string& service_id) {
683*3f982cf4SFabien Sanglard // TODO(btolsch): This is just a placeholder for the demo. It should
684*3f982cf4SFabien Sanglard // eventually become a GUID/unguessable token routine.
685*3f982cf4SFabien Sanglard std::string safe_id = service_id;
686*3f982cf4SFabien Sanglard for (auto& c : safe_id)
687*3f982cf4SFabien Sanglard if (c < ' ' || c > '~')
688*3f982cf4SFabien Sanglard c = '.';
689*3f982cf4SFabien Sanglard return safe_id + ":" + url;
690*3f982cf4SFabien Sanglard }
691*3f982cf4SFabien Sanglard
AddConnection(Connection * connection)692*3f982cf4SFabien Sanglard void Controller::AddConnection(Connection* connection) {
693*3f982cf4SFabien Sanglard connection_manager_->AddConnection(connection);
694*3f982cf4SFabien Sanglard }
695*3f982cf4SFabien Sanglard
OpenConnection(uint64_t connection_id,uint64_t endpoint_id,const std::string & service_id,RequestDelegate * request_delegate,std::unique_ptr<Connection> && connection,std::unique_ptr<ProtocolConnection> && protocol_connection)696*3f982cf4SFabien Sanglard void Controller::OpenConnection(
697*3f982cf4SFabien Sanglard uint64_t connection_id,
698*3f982cf4SFabien Sanglard uint64_t endpoint_id,
699*3f982cf4SFabien Sanglard const std::string& service_id,
700*3f982cf4SFabien Sanglard RequestDelegate* request_delegate,
701*3f982cf4SFabien Sanglard std::unique_ptr<Connection>&& connection,
702*3f982cf4SFabien Sanglard std::unique_ptr<ProtocolConnection>&& protocol_connection) {
703*3f982cf4SFabien Sanglard connection->OnConnected(connection_id, endpoint_id,
704*3f982cf4SFabien Sanglard std::move(protocol_connection));
705*3f982cf4SFabien Sanglard const std::string& presentation_id = connection->presentation_info().id;
706*3f982cf4SFabien Sanglard auto presentation_entry = presentations_.find(presentation_id);
707*3f982cf4SFabien Sanglard if (presentation_entry == presentations_.end()) {
708*3f982cf4SFabien Sanglard auto emplace_entry = presentations_.emplace(
709*3f982cf4SFabien Sanglard presentation_id,
710*3f982cf4SFabien Sanglard ControlledPresentation{
711*3f982cf4SFabien Sanglard service_id, connection->presentation_info().url, {}});
712*3f982cf4SFabien Sanglard presentation_entry = emplace_entry.first;
713*3f982cf4SFabien Sanglard }
714*3f982cf4SFabien Sanglard ControlledPresentation& presentation = presentation_entry->second;
715*3f982cf4SFabien Sanglard presentation.connections.push_back(connection.get());
716*3f982cf4SFabien Sanglard AddConnection(connection.get());
717*3f982cf4SFabien Sanglard
718*3f982cf4SFabien Sanglard auto terminate_entry = termination_listener_by_id_.find(presentation_id);
719*3f982cf4SFabien Sanglard if (terminate_entry == termination_listener_by_id_.end()) {
720*3f982cf4SFabien Sanglard termination_listener_by_id_.emplace(
721*3f982cf4SFabien Sanglard presentation_id, std::make_unique<TerminationListener>(
722*3f982cf4SFabien Sanglard this, presentation_id, endpoint_id));
723*3f982cf4SFabien Sanglard }
724*3f982cf4SFabien Sanglard request_delegate->OnConnection(std::move(connection));
725*3f982cf4SFabien Sanglard }
726*3f982cf4SFabien Sanglard
TerminatePresentationById(const std::string & presentation_id)727*3f982cf4SFabien Sanglard void Controller::TerminatePresentationById(const std::string& presentation_id) {
728*3f982cf4SFabien Sanglard auto presentation_entry = presentations_.find(presentation_id);
729*3f982cf4SFabien Sanglard if (presentation_entry != presentations_.end()) {
730*3f982cf4SFabien Sanglard for (auto* connection : presentation_entry->second.connections) {
731*3f982cf4SFabien Sanglard connection->OnTerminated();
732*3f982cf4SFabien Sanglard }
733*3f982cf4SFabien Sanglard presentations_.erase(presentation_entry);
734*3f982cf4SFabien Sanglard }
735*3f982cf4SFabien Sanglard }
736*3f982cf4SFabien Sanglard
CancelReceiverWatch(const std::vector<std::string> & urls,ReceiverObserver * observer)737*3f982cf4SFabien Sanglard void Controller::CancelReceiverWatch(const std::vector<std::string>& urls,
738*3f982cf4SFabien Sanglard ReceiverObserver* observer) {
739*3f982cf4SFabien Sanglard availability_requester_->RemoveObserverUrls(urls, observer);
740*3f982cf4SFabien Sanglard }
741*3f982cf4SFabien Sanglard
CancelConnectRequest(const std::string & service_id,bool is_reconnect,uint64_t request_id)742*3f982cf4SFabien Sanglard void Controller::CancelConnectRequest(const std::string& service_id,
743*3f982cf4SFabien Sanglard bool is_reconnect,
744*3f982cf4SFabien Sanglard uint64_t request_id) {
745*3f982cf4SFabien Sanglard auto group_streams_entry = group_streams_.find(service_id);
746*3f982cf4SFabien Sanglard if (group_streams_entry == group_streams_.end())
747*3f982cf4SFabien Sanglard return;
748*3f982cf4SFabien Sanglard if (is_reconnect) {
749*3f982cf4SFabien Sanglard group_streams_entry->second->CancelConnectionOpenRequest(request_id);
750*3f982cf4SFabien Sanglard } else {
751*3f982cf4SFabien Sanglard group_streams_entry->second->CancelStartRequest(request_id);
752*3f982cf4SFabien Sanglard }
753*3f982cf4SFabien Sanglard }
754*3f982cf4SFabien Sanglard
OnStarted()755*3f982cf4SFabien Sanglard void Controller::OnStarted() {}
OnStopped()756*3f982cf4SFabien Sanglard void Controller::OnStopped() {}
OnSuspended()757*3f982cf4SFabien Sanglard void Controller::OnSuspended() {}
OnSearching()758*3f982cf4SFabien Sanglard void Controller::OnSearching() {}
759*3f982cf4SFabien Sanglard
OnReceiverAdded(const ServiceInfo & info)760*3f982cf4SFabien Sanglard void Controller::OnReceiverAdded(const ServiceInfo& info) {
761*3f982cf4SFabien Sanglard receiver_endpoints_.emplace(info.service_id, info.v4_endpoint.port
762*3f982cf4SFabien Sanglard ? info.v4_endpoint
763*3f982cf4SFabien Sanglard : info.v6_endpoint);
764*3f982cf4SFabien Sanglard auto group_streams =
765*3f982cf4SFabien Sanglard std::make_unique<MessageGroupStreams>(this, info.service_id);
766*3f982cf4SFabien Sanglard group_streams_[info.service_id] = std::move(group_streams);
767*3f982cf4SFabien Sanglard availability_requester_->AddReceiver(info);
768*3f982cf4SFabien Sanglard }
769*3f982cf4SFabien Sanglard
OnReceiverChanged(const ServiceInfo & info)770*3f982cf4SFabien Sanglard void Controller::OnReceiverChanged(const ServiceInfo& info) {
771*3f982cf4SFabien Sanglard receiver_endpoints_[info.service_id] =
772*3f982cf4SFabien Sanglard info.v4_endpoint.port ? info.v4_endpoint : info.v6_endpoint;
773*3f982cf4SFabien Sanglard availability_requester_->ChangeReceiver(info);
774*3f982cf4SFabien Sanglard }
775*3f982cf4SFabien Sanglard
OnReceiverRemoved(const ServiceInfo & info)776*3f982cf4SFabien Sanglard void Controller::OnReceiverRemoved(const ServiceInfo& info) {
777*3f982cf4SFabien Sanglard receiver_endpoints_.erase(info.service_id);
778*3f982cf4SFabien Sanglard group_streams_.erase(info.service_id);
779*3f982cf4SFabien Sanglard availability_requester_->RemoveReceiver(info);
780*3f982cf4SFabien Sanglard }
781*3f982cf4SFabien Sanglard
OnAllReceiversRemoved()782*3f982cf4SFabien Sanglard void Controller::OnAllReceiversRemoved() {
783*3f982cf4SFabien Sanglard receiver_endpoints_.clear();
784*3f982cf4SFabien Sanglard availability_requester_->RemoveAllReceivers();
785*3f982cf4SFabien Sanglard }
786*3f982cf4SFabien Sanglard
787*3f982cf4SFabien Sanglard } // namespace osp
788*3f982cf4SFabien Sanglard } // namespace openscreen
789