| // 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_RECEIVER_H_ |
| #define OSP_PUBLIC_PRESENTATION_PRESENTATION_RECEIVER_H_ |
| |
| #include <map> |
| #include <memory> |
| #include <string> |
| #include <vector> |
| |
| #include "osp/msgs/osp_messages.h" |
| #include "osp/public/message_demuxer.h" |
| #include "osp/public/presentation/presentation_connection.h" |
| |
| namespace openscreen { |
| namespace osp { |
| |
| enum class ResponseResult { |
| kSuccess = 0, |
| kInvalidUrl, |
| kRequestTimedOut, |
| kRequestFailedTransient, |
| kRequestFailedPermanent, |
| kHttpError, |
| kUnknown, |
| }; |
| |
| class ReceiverDelegate { |
| public: |
| virtual ~ReceiverDelegate() = default; |
| |
| // Called when the availability (compatible, not compatible, or invalid) |
| // for specific URLs is needed to be supplied by the delegate. |
| // See "#presentation-protocol" spec section. |
| // Returns a list of url availabilities. |
| virtual std::vector<msgs::UrlAvailability> OnUrlAvailabilityRequest( |
| uint64_t watch_id, |
| uint64_t watch_duration, |
| std::vector<std::string> urls) = 0; |
| |
| // Called when a new presentation is requested by a controller. This should |
| // return true if the presentation was accepted, false otherwise. |
| virtual bool StartPresentation( |
| const Connection::PresentationInfo& info, |
| uint64_t source_id, |
| const std::vector<msgs::HttpHeader>& http_headers) = 0; |
| |
| // Called when the receiver wants to actually connection to the presentation. |
| // Should return true if the connection was successful, false otherwise. |
| virtual bool ConnectToPresentation(uint64_t request_id, |
| const std::string& id, |
| uint64_t source_id) = 0; |
| |
| // Called when a presentation is requested to be terminated by a controller. |
| virtual void TerminatePresentation(const std::string& id, |
| TerminationReason reason) = 0; |
| }; |
| |
| class Receiver final : public MessageDemuxer::MessageCallback, |
| public Connection::ParentDelegate { |
| public: |
| // TODO(crbug.com/openscreen/31): Remove singletons in the embedder API and |
| // protocol implementation layers. |
| static Receiver* Get(); |
| void Init(); |
| void Deinit(); |
| |
| // Sets the object to call when a new receiver connection is available. |
| // |delegate| must either outlive PresentationReceiver or live until a new |
| // delegate (possibly nullptr) is set. Setting the delegate to nullptr will |
| // automatically ignore all future receiver requests. |
| void SetReceiverDelegate(ReceiverDelegate* delegate); |
| |
| // Called by the embedder to report its response to StartPresentation. |
| Error OnPresentationStarted(const std::string& presentation_id, |
| Connection* connection, |
| ResponseResult result); |
| |
| Error OnConnectionCreated(uint64_t request_id, |
| Connection* connection, |
| ResponseResult result); |
| |
| // 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; |
| |
| // MessageDemuxer::MessageCallback overrides. |
| ErrorOr<size_t> 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) override; |
| |
| private: |
| struct QueuedResponse { |
| enum class Type { kInitiation, kConnection }; |
| |
| Type type; |
| uint64_t request_id; |
| uint64_t connection_id; |
| uint64_t endpoint_id; |
| }; |
| |
| struct Presentation { |
| uint64_t endpoint_id; |
| MessageDemuxer::MessageWatch terminate_watch; |
| uint64_t terminate_request_id; |
| std::vector<Connection*> connections; |
| }; |
| |
| Receiver(); |
| ~Receiver() override; |
| |
| using QueuedResponseIterator = std::vector<QueuedResponse>::const_iterator; |
| |
| void DeleteQueuedResponse(const std::string& presentation_id, |
| QueuedResponseIterator response); |
| ErrorOr<QueuedResponseIterator> GetQueuedResponse( |
| const std::string& presentation_id, |
| uint64_t request_id) const; |
| |
| ReceiverDelegate* delegate_ = nullptr; |
| |
| // TODO(jophba): scope requests by endpoint, not presentation. This doesn't |
| // work properly for multiple controllers. |
| std::map<std::string, std::vector<QueuedResponse>> queued_responses_; |
| |
| // Presentations are added when the embedder starts the presentation, |
| // and ended when a new receiver delegate is set or when |
| // a presentation is called to be terminated (OnPresentationTerminated). |
| std::map<std::string, Presentation> started_presentations_; |
| |
| std::unique_ptr<ConnectionManager> connection_manager_; |
| |
| MessageDemuxer::MessageWatch availability_watch_; |
| MessageDemuxer::MessageWatch initiation_watch_; |
| MessageDemuxer::MessageWatch connection_watch_; |
| |
| uint64_t GetNextConnectionId(); |
| }; |
| |
| } // namespace osp |
| } // namespace openscreen |
| |
| #endif // OSP_PUBLIC_PRESENTATION_PRESENTATION_RECEIVER_H_ |