| // 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 <map> |
| #include <memory> |
| #include <string> |
| |
| #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> 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<std::string>& 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<std::string> urls_; |
| ReceiverObserver* observer_ = nullptr; |
| Controller* controller_ = nullptr; |
| }; |
| |
| class ConnectRequest { |
| public: |
| ConnectRequest(); |
| ConnectRequest(Controller* controller, |
| const std::string& service_id, |
| bool is_reconnect, |
| absl::optional<uint64_t> 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<uint64_t> 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<std::string>& 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<std::string>& 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> 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<ProtocolConnection> stream); |
| |
| private: |
| class TerminationListener; |
| class MessageGroupStreams; |
| |
| struct ControlledPresentation { |
| std::string service_id; |
| std::string url; |
| std::vector<Connection*> 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>&& connection, |
| std::unique_ptr<ProtocolConnection>&& stream); |
| |
| void TerminatePresentationById(const std::string& presentation_id); |
| |
| // Cancels compatible receiver monitoring for the given |urls|, |observer| |
| // pair. |
| void CancelReceiverWatch(const std::vector<std::string>& 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<std::string, uint64_t> next_connection_id_; |
| |
| std::map<std::string, ControlledPresentation> presentations_; |
| |
| std::unique_ptr<ConnectionManager> connection_manager_; |
| |
| std::unique_ptr<UrlAvailabilityRequester> availability_requester_; |
| std::map<std::string, IPEndpoint> receiver_endpoints_; |
| |
| std::map<std::string, std::unique_ptr<MessageGroupStreams>> group_streams_; |
| std::map<std::string, std::unique_ptr<TerminationListener>> |
| termination_listener_by_id_; |
| }; |
| |
| } // namespace osp |
| } // namespace openscreen |
| |
| #endif // OSP_PUBLIC_PRESENTATION_PRESENTATION_CONTROLLER_H_ |