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