// Copyright 2018 The Chromium Authors. All rights reserved. // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #ifndef OSP_PUBLIC_PRESENTATION_PRESENTATION_CONTROLLER_H_ #define OSP_PUBLIC_PRESENTATION_PRESENTATION_CONTROLLER_H_ #include #include #include #include "absl/strings/string_view.h" #include "absl/types/optional.h" #include "osp/public/presentation/presentation_connection.h" #include "osp/public/protocol_connection.h" #include "osp/public/service_listener.h" #include "platform/api/time.h" #include "platform/base/error.h" namespace openscreen { namespace osp { class UrlAvailabilityRequester; class RequestDelegate { public: virtual ~RequestDelegate() = default; virtual void OnConnection(std::unique_ptr connection) = 0; virtual void OnError(const Error& error) = 0; }; class ReceiverObserver { public: virtual ~ReceiverObserver() = default; // Called when there is an unrecoverable error in requesting availability. // This means the availability is unknown and there is no further response to // wait for. virtual void OnRequestFailed(const std::string& presentation_url, const std::string& service_id) = 0; // Called when receivers compatible with |presentation_url| are known to be // available. virtual void OnReceiverAvailable(const std::string& presentation_url, const std::string& service_id) = 0; // Only called for |service_id| values previously advertised as available. virtual void OnReceiverUnavailable(const std::string& presentation_url, const std::string& service_id) = 0; }; class Controller final : public ServiceListener::Observer, public Connection::ParentDelegate { public: class ReceiverWatch { public: ReceiverWatch(); ReceiverWatch(Controller* controller, const std::vector& urls, ReceiverObserver* observer); ReceiverWatch(ReceiverWatch&&) noexcept; ~ReceiverWatch(); ReceiverWatch& operator=(ReceiverWatch); explicit operator bool() const { return observer_; } friend void swap(ReceiverWatch& a, ReceiverWatch& b); private: std::vector urls_; ReceiverObserver* observer_ = nullptr; Controller* controller_ = nullptr; }; class ConnectRequest { public: ConnectRequest(); ConnectRequest(Controller* controller, const std::string& service_id, bool is_reconnect, absl::optional request_id); ConnectRequest(ConnectRequest&&) noexcept; ~ConnectRequest(); ConnectRequest& operator=(ConnectRequest); explicit operator bool() const { return request_id_.has_value(); } friend void swap(ConnectRequest& a, ConnectRequest& b); private: std::string service_id_; bool is_reconnect_; absl::optional request_id_; Controller* controller_; }; explicit Controller(ClockNowFunctionPtr now_function); ~Controller(); // Requests receivers compatible with all urls in |urls| and registers // |observer| for availability changes. The screens will be a subset of the // screen list maintained by the ServiceListener. Returns an RAII object that // tracks the registration. ReceiverWatch RegisterReceiverWatch(const std::vector& urls, ReceiverObserver* observer); // Requests that a new presentation be created on |service_id| using // |presentation_url|, with the result passed to |delegate|. // |conn_delegate| is passed to the resulting connection. The returned // ConnectRequest object may be destroyed before any |delegate| methods are // called to cancel the request. ConnectRequest StartPresentation(const std::string& url, const std::string& service_id, RequestDelegate* delegate, Connection::Delegate* conn_delegate); // Requests reconnection to the presentation with the given id and URL running // on |service_id|, with the result passed to |delegate|. |conn_delegate| is // passed to the resulting connection. The returned ConnectRequest object may // be destroyed before any |delegate| methods are called to cancel the // request. ConnectRequest ReconnectPresentation(const std::vector& urls, const std::string& presentation_id, const std::string& service_id, RequestDelegate* delegate, Connection::Delegate* conn_delegate); // Requests reconnection with a previously-connected connection. This both // avoids having to respecify the parameters and connection delegate but also // simplifies the implementation of the Presentation API requirement to return // the same connection object where possible. ConnectRequest ReconnectConnection(std::unique_ptr connection, RequestDelegate* delegate); // Connection::ParentDelegate overrides. Error CloseConnection(Connection* connection, Connection::CloseReason reason) override; // Also called by the embedder to report that a presentation has been // terminated. Error OnPresentationTerminated(const std::string& presentation_id, TerminationReason reason) override; void OnConnectionDestroyed(Connection* connection) override; // Returns an empty string if no such presentation ID is found. std::string GetServiceIdForPresentationId( const std::string& presentation_id) const; ProtocolConnection* GetConnectionRequestGroupStream( const std::string& service_id); // TODO(btolsch): still used? void SetConnectionRequestGroupStreamForTest( const std::string& service_id, std::unique_ptr stream); private: class TerminationListener; class MessageGroupStreams; struct ControlledPresentation { std::string service_id; std::string url; std::vector connections; }; static std::string MakePresentationId(const std::string& url, const std::string& service_id); void AddConnection(Connection* connection); void OpenConnection(uint64_t connection_id, uint64_t endpoint_id, const std::string& service_id, RequestDelegate* request_delegate, std::unique_ptr&& connection, std::unique_ptr&& stream); void TerminatePresentationById(const std::string& presentation_id); // Cancels compatible receiver monitoring for the given |urls|, |observer| // pair. void CancelReceiverWatch(const std::vector& urls, ReceiverObserver* observer); // Cancels a presentation connect request for the given |request_id| if one is // pending. void CancelConnectRequest(const std::string& service_id, bool is_reconnect, uint64_t request_id); // ServiceListener::Observer overrides. void OnStarted() override; void OnStopped() override; void OnSuspended() override; void OnSearching() override; void OnReceiverAdded(const ServiceInfo& info) override; void OnReceiverChanged(const ServiceInfo& info) override; void OnReceiverRemoved(const ServiceInfo& info) override; void OnAllReceiversRemoved() override; void OnError(ServiceListenerError) override; void OnMetrics(ServiceListener::Metrics) override; std::map next_connection_id_; std::map presentations_; std::unique_ptr connection_manager_; std::unique_ptr availability_requester_; std::map receiver_endpoints_; std::map> group_streams_; std::map> termination_listener_by_id_; }; } // namespace osp } // namespace openscreen #endif // OSP_PUBLIC_PRESENTATION_PRESENTATION_CONTROLLER_H_