1 // Copyright 2018 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 #ifndef OSP_PUBLIC_PRESENTATION_PRESENTATION_CONTROLLER_H_
6 #define OSP_PUBLIC_PRESENTATION_PRESENTATION_CONTROLLER_H_
7 
8 #include <map>
9 #include <memory>
10 #include <string>
11 
12 #include "absl/strings/string_view.h"
13 #include "absl/types/optional.h"
14 #include "osp/public/presentation/presentation_connection.h"
15 #include "osp/public/protocol_connection.h"
16 #include "osp/public/service_listener.h"
17 #include "platform/api/time.h"
18 #include "platform/base/error.h"
19 
20 namespace openscreen {
21 namespace osp {
22 
23 class UrlAvailabilityRequester;
24 
25 class RequestDelegate {
26  public:
27   virtual ~RequestDelegate() = default;
28 
29   virtual void OnConnection(std::unique_ptr<Connection> connection) = 0;
30   virtual void OnError(const Error& error) = 0;
31 };
32 
33 class ReceiverObserver {
34  public:
35   virtual ~ReceiverObserver() = default;
36 
37   // Called when there is an unrecoverable error in requesting availability.
38   // This means the availability is unknown and there is no further response to
39   // wait for.
40   virtual void OnRequestFailed(const std::string& presentation_url,
41                                const std::string& service_id) = 0;
42 
43   // Called when receivers compatible with |presentation_url| are known to be
44   // available.
45   virtual void OnReceiverAvailable(const std::string& presentation_url,
46                                    const std::string& service_id) = 0;
47   // Only called for |service_id| values previously advertised as available.
48   virtual void OnReceiverUnavailable(const std::string& presentation_url,
49                                      const std::string& service_id) = 0;
50 };
51 
52 class Controller final : public ServiceListener::Observer,
53                          public Connection::ParentDelegate {
54  public:
55   class ReceiverWatch {
56    public:
57     ReceiverWatch();
58     ReceiverWatch(Controller* controller,
59                   const std::vector<std::string>& urls,
60                   ReceiverObserver* observer);
61     ReceiverWatch(ReceiverWatch&&) noexcept;
62     ~ReceiverWatch();
63 
64     ReceiverWatch& operator=(ReceiverWatch);
65 
66     explicit operator bool() const { return observer_; }
67 
68     friend void swap(ReceiverWatch& a, ReceiverWatch& b);
69 
70    private:
71     std::vector<std::string> urls_;
72     ReceiverObserver* observer_ = nullptr;
73     Controller* controller_ = nullptr;
74   };
75 
76   class ConnectRequest {
77    public:
78     ConnectRequest();
79     ConnectRequest(Controller* controller,
80                    const std::string& service_id,
81                    bool is_reconnect,
82                    absl::optional<uint64_t> request_id);
83     ConnectRequest(ConnectRequest&&) noexcept;
84     ~ConnectRequest();
85 
86     ConnectRequest& operator=(ConnectRequest);
87 
88     explicit operator bool() const { return request_id_.has_value(); }
89 
90     friend void swap(ConnectRequest& a, ConnectRequest& b);
91 
92    private:
93     std::string service_id_;
94     bool is_reconnect_;
95     absl::optional<uint64_t> request_id_;
96     Controller* controller_;
97   };
98 
99   explicit Controller(ClockNowFunctionPtr now_function);
100   ~Controller();
101 
102   // Requests receivers compatible with all urls in |urls| and registers
103   // |observer| for availability changes.  The screens will be a subset of the
104   // screen list maintained by the ServiceListener.  Returns an RAII object that
105   // tracks the registration.
106   ReceiverWatch RegisterReceiverWatch(const std::vector<std::string>& urls,
107                                       ReceiverObserver* observer);
108 
109   // Requests that a new presentation be created on |service_id| using
110   // |presentation_url|, with the result passed to |delegate|.
111   // |conn_delegate| is passed to the resulting connection.  The returned
112   // ConnectRequest object may be destroyed before any |delegate| methods are
113   // called to cancel the request.
114   ConnectRequest StartPresentation(const std::string& url,
115                                    const std::string& service_id,
116                                    RequestDelegate* delegate,
117                                    Connection::Delegate* conn_delegate);
118 
119   // Requests reconnection to the presentation with the given id and URL running
120   // on |service_id|, with the result passed to |delegate|.  |conn_delegate| is
121   // passed to the resulting connection.  The returned ConnectRequest object may
122   // be destroyed before any |delegate| methods are called to cancel the
123   // request.
124   ConnectRequest ReconnectPresentation(const std::vector<std::string>& urls,
125                                        const std::string& presentation_id,
126                                        const std::string& service_id,
127                                        RequestDelegate* delegate,
128                                        Connection::Delegate* conn_delegate);
129 
130   // Requests reconnection with a previously-connected connection.  This both
131   // avoids having to respecify the parameters and connection delegate but also
132   // simplifies the implementation of the Presentation API requirement to return
133   // the same connection object where possible.
134   ConnectRequest ReconnectConnection(std::unique_ptr<Connection> connection,
135                                      RequestDelegate* delegate);
136 
137   // Connection::ParentDelegate overrides.
138   Error CloseConnection(Connection* connection,
139                         Connection::CloseReason reason) override;
140 
141   // Also called by the embedder to report that a presentation has been
142   // terminated.
143   Error OnPresentationTerminated(const std::string& presentation_id,
144                                  TerminationReason reason) override;
145 
146   void OnConnectionDestroyed(Connection* connection) override;
147 
148   // Returns an empty string if no such presentation ID is found.
149   std::string GetServiceIdForPresentationId(
150       const std::string& presentation_id) const;
151 
152   ProtocolConnection* GetConnectionRequestGroupStream(
153       const std::string& service_id);
154 
155   // TODO(btolsch): still used?
156   void SetConnectionRequestGroupStreamForTest(
157       const std::string& service_id,
158       std::unique_ptr<ProtocolConnection> stream);
159 
160  private:
161   class TerminationListener;
162   class MessageGroupStreams;
163 
164   struct ControlledPresentation {
165     std::string service_id;
166     std::string url;
167     std::vector<Connection*> connections;
168   };
169 
170   static std::string MakePresentationId(const std::string& url,
171                                         const std::string& service_id);
172 
173   void AddConnection(Connection* connection);
174   void OpenConnection(uint64_t connection_id,
175                       uint64_t endpoint_id,
176                       const std::string& service_id,
177                       RequestDelegate* request_delegate,
178                       std::unique_ptr<Connection>&& connection,
179                       std::unique_ptr<ProtocolConnection>&& stream);
180 
181   void TerminatePresentationById(const std::string& presentation_id);
182 
183   // Cancels compatible receiver monitoring for the given |urls|, |observer|
184   // pair.
185   void CancelReceiverWatch(const std::vector<std::string>& urls,
186                            ReceiverObserver* observer);
187 
188   // Cancels a presentation connect request for the given |request_id| if one is
189   // pending.
190   void CancelConnectRequest(const std::string& service_id,
191                             bool is_reconnect,
192                             uint64_t request_id);
193 
194   // ServiceListener::Observer overrides.
195   void OnStarted() override;
196   void OnStopped() override;
197   void OnSuspended() override;
198   void OnSearching() override;
199   void OnReceiverAdded(const ServiceInfo& info) override;
200   void OnReceiverChanged(const ServiceInfo& info) override;
201   void OnReceiverRemoved(const ServiceInfo& info) override;
202   void OnAllReceiversRemoved() override;
203   void OnError(ServiceListenerError) override;
204   void OnMetrics(ServiceListener::Metrics) override;
205 
206   std::map<std::string, uint64_t> next_connection_id_;
207 
208   std::map<std::string, ControlledPresentation> presentations_;
209 
210   std::unique_ptr<ConnectionManager> connection_manager_;
211 
212   std::unique_ptr<UrlAvailabilityRequester> availability_requester_;
213   std::map<std::string, IPEndpoint> receiver_endpoints_;
214 
215   std::map<std::string, std::unique_ptr<MessageGroupStreams>> group_streams_;
216   std::map<std::string, std::unique_ptr<TerminationListener>>
217       termination_listener_by_id_;
218 };
219 
220 }  // namespace osp
221 }  // namespace openscreen
222 
223 #endif  // OSP_PUBLIC_PRESENTATION_PRESENTATION_CONTROLLER_H_
224