// 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_IMPL_PRESENTATION_URL_AVAILABILITY_REQUESTER_H_ #define OSP_IMPL_PRESENTATION_URL_AVAILABILITY_REQUESTER_H_ #include #include #include #include #include #include "osp/msgs/osp_messages.h" #include "osp/public/message_demuxer.h" #include "osp/public/presentation/presentation_controller.h" #include "osp/public/protocol_connection_client.h" #include "osp/public/service_info.h" #include "platform/api/time.h" #include "platform/base/error.h" namespace openscreen { namespace osp { // Handles Presentation API URL availability requests and persistent watches. // It keeps track of the set of currently known receivers as well as all // registered URLs and observers in order to query each receiver with all URLs. // It uses the availability protocol message watch mechanism to stay informed of // any availability changes as long as at least one observer is registered for a // given URL. class UrlAvailabilityRequester { public: explicit UrlAvailabilityRequester(ClockNowFunctionPtr now_function); ~UrlAvailabilityRequester(); // Adds a persistent availability request for |urls| to all known receivers. // These URLs will also be queried for any receivers discovered in the future. // |observer| will be called back once for the first known availability (which // may be cached from previous requests) and when the availability of any of // these URLs changes on any receiver. void AddObserver(const std::vector& urls, ReceiverObserver* observer); // Disassociates |observer| from all the URLs in |urls| so it will no longer // receive availability updates for these URLs. Additionally, if |urls| is // only a subset of the URL list it was originally added with, it will still // be observing the URLs not included here. void RemoveObserverUrls(const std::vector& urls, ReceiverObserver* observer); // Disassociates |observer| from all the URLs it is observing. This // guarantees that it is safe to delete |observer| after this call. void RemoveObserver(ReceiverObserver* observer); // Informs the UrlAvailabilityRequester of changes to the set of known // receivers. New receivers are immediately queried for all currently // observed URLs and removed receivers cause any URLs that were available on // that receiver to become unavailable. void AddReceiver(const ServiceInfo& info); void ChangeReceiver(const ServiceInfo& info); void RemoveReceiver(const ServiceInfo& info); void RemoveAllReceivers(); // Ensures that all open availability watches (to all receivers) that are // about to expire are refreshed by sending a new request with the same URLs. // Returns the time point at which this should next be scheduled to run. Clock::time_point RefreshWatches(); private: // Handles Presentation API URL availability requests and watches for one // particular receiver. When first constructed, it attempts to open a // ProtocolConnection to the receiver, then it makes an availability request // for all the observed URLs, then it continues to listen for update events // during the following watch period. Before a watch will expire, it needs to // send a new request to restart the watch, as long as there are active // observers for a given URL. struct ReceiverRequester final : ProtocolConnectionClient::ConnectionRequestCallback, MessageDemuxer::MessageCallback { struct Request { uint64_t watch_id; std::vector urls; }; struct Watch { Clock::time_point deadline; std::vector urls; }; ReceiverRequester(UrlAvailabilityRequester* listener, const std::string& service_id, const IPEndpoint& endpoint); ~ReceiverRequester() override; void GetOrRequestAvailabilities( const std::vector& requested_urls, ReceiverObserver* observer); void RequestUrlAvailabilities(std::vector urls); ErrorOr SendRequest(uint64_t request_id, const std::vector& urls); Clock::time_point RefreshWatches(Clock::time_point now); Error::Code UpdateAvailabilities( const std::vector& urls, const std::vector& availabilities); void RemoveUnobservedRequests(const std::set& unobserved_urls); void RemoveUnobservedWatches(const std::set& unobserved_urls); void RemoveReceiver(); // ProtocolConnectionClient::ConnectionRequestCallback overrides. void OnConnectionOpened( uint64_t request_id, std::unique_ptr connection) override; void OnConnectionFailed(uint64_t request_id) override; // MessageDemuxer::MessageCallback overrides. ErrorOr 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; UrlAvailabilityRequester* const listener; uint64_t next_watch_id = 1; const std::string service_id; uint64_t endpoint_id{0}; ProtocolConnectionClient::ConnectRequest connect_request; // TODO(btolsch): Observe connection and restart all the things on close. std::unique_ptr connection; MessageDemuxer::MessageWatch response_watch; std::map request_by_id; MessageDemuxer::MessageWatch event_watch; std::map watch_by_id; std::map known_availability_by_url; }; const ClockNowFunctionPtr now_function_; std::map> observers_by_url_; std::map> receiver_by_service_id_; }; } // namespace osp } // namespace openscreen #endif // OSP_IMPL_PRESENTATION_URL_AVAILABILITY_REQUESTER_H_