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_IMPL_PRESENTATION_URL_AVAILABILITY_REQUESTER_H_ 6 #define OSP_IMPL_PRESENTATION_URL_AVAILABILITY_REQUESTER_H_ 7 8 #include <map> 9 #include <memory> 10 #include <set> 11 #include <string> 12 #include <vector> 13 14 #include "osp/msgs/osp_messages.h" 15 #include "osp/public/message_demuxer.h" 16 #include "osp/public/presentation/presentation_controller.h" 17 #include "osp/public/protocol_connection_client.h" 18 #include "osp/public/service_info.h" 19 #include "platform/api/time.h" 20 #include "platform/base/error.h" 21 22 namespace openscreen { 23 namespace osp { 24 25 // Handles Presentation API URL availability requests and persistent watches. 26 // It keeps track of the set of currently known receivers as well as all 27 // registered URLs and observers in order to query each receiver with all URLs. 28 // It uses the availability protocol message watch mechanism to stay informed of 29 // any availability changes as long as at least one observer is registered for a 30 // given URL. 31 class UrlAvailabilityRequester { 32 public: 33 explicit UrlAvailabilityRequester(ClockNowFunctionPtr now_function); 34 ~UrlAvailabilityRequester(); 35 36 // Adds a persistent availability request for |urls| to all known receivers. 37 // These URLs will also be queried for any receivers discovered in the future. 38 // |observer| will be called back once for the first known availability (which 39 // may be cached from previous requests) and when the availability of any of 40 // these URLs changes on any receiver. 41 void AddObserver(const std::vector<std::string>& urls, 42 ReceiverObserver* observer); 43 44 // Disassociates |observer| from all the URLs in |urls| so it will no longer 45 // receive availability updates for these URLs. Additionally, if |urls| is 46 // only a subset of the URL list it was originally added with, it will still 47 // be observing the URLs not included here. 48 void RemoveObserverUrls(const std::vector<std::string>& urls, 49 ReceiverObserver* observer); 50 51 // Disassociates |observer| from all the URLs it is observing. This 52 // guarantees that it is safe to delete |observer| after this call. 53 void RemoveObserver(ReceiverObserver* observer); 54 55 // Informs the UrlAvailabilityRequester of changes to the set of known 56 // receivers. New receivers are immediately queried for all currently 57 // observed URLs and removed receivers cause any URLs that were available on 58 // that receiver to become unavailable. 59 void AddReceiver(const ServiceInfo& info); 60 void ChangeReceiver(const ServiceInfo& info); 61 void RemoveReceiver(const ServiceInfo& info); 62 void RemoveAllReceivers(); 63 64 // Ensures that all open availability watches (to all receivers) that are 65 // about to expire are refreshed by sending a new request with the same URLs. 66 // Returns the time point at which this should next be scheduled to run. 67 Clock::time_point RefreshWatches(); 68 69 private: 70 // Handles Presentation API URL availability requests and watches for one 71 // particular receiver. When first constructed, it attempts to open a 72 // ProtocolConnection to the receiver, then it makes an availability request 73 // for all the observed URLs, then it continues to listen for update events 74 // during the following watch period. Before a watch will expire, it needs to 75 // send a new request to restart the watch, as long as there are active 76 // observers for a given URL. 77 struct ReceiverRequester final 78 : ProtocolConnectionClient::ConnectionRequestCallback, 79 MessageDemuxer::MessageCallback { 80 struct Request { 81 uint64_t watch_id; 82 std::vector<std::string> urls; 83 }; 84 85 struct Watch { 86 Clock::time_point deadline; 87 std::vector<std::string> urls; 88 }; 89 90 ReceiverRequester(UrlAvailabilityRequester* listener, 91 const std::string& service_id, 92 const IPEndpoint& endpoint); 93 ~ReceiverRequester() override; 94 95 void GetOrRequestAvailabilities( 96 const std::vector<std::string>& requested_urls, 97 ReceiverObserver* observer); 98 void RequestUrlAvailabilities(std::vector<std::string> urls); 99 ErrorOr<uint64_t> SendRequest(uint64_t request_id, 100 const std::vector<std::string>& urls); 101 Clock::time_point RefreshWatches(Clock::time_point now); 102 Error::Code UpdateAvailabilities( 103 const std::vector<std::string>& urls, 104 const std::vector<msgs::UrlAvailability>& availabilities); 105 void RemoveUnobservedRequests(const std::set<std::string>& unobserved_urls); 106 void RemoveUnobservedWatches(const std::set<std::string>& unobserved_urls); 107 void RemoveReceiver(); 108 109 // ProtocolConnectionClient::ConnectionRequestCallback overrides. 110 void OnConnectionOpened( 111 uint64_t request_id, 112 std::unique_ptr<ProtocolConnection> connection) override; 113 void OnConnectionFailed(uint64_t request_id) override; 114 115 // MessageDemuxer::MessageCallback overrides. 116 ErrorOr<size_t> OnStreamMessage(uint64_t endpoint_id, 117 uint64_t connection_id, 118 msgs::Type message_type, 119 const uint8_t* buffer, 120 size_t buffer_size, 121 Clock::time_point now) override; 122 123 UrlAvailabilityRequester* const listener; 124 125 uint64_t next_watch_id = 1; 126 127 const std::string service_id; 128 uint64_t endpoint_id{0}; 129 130 ProtocolConnectionClient::ConnectRequest connect_request; 131 // TODO(btolsch): Observe connection and restart all the things on close. 132 std::unique_ptr<ProtocolConnection> connection; 133 134 MessageDemuxer::MessageWatch response_watch; 135 std::map<uint64_t, Request> request_by_id; 136 MessageDemuxer::MessageWatch event_watch; 137 std::map<uint64_t, Watch> watch_by_id; 138 139 std::map<std::string, msgs::UrlAvailability> known_availability_by_url; 140 }; 141 142 const ClockNowFunctionPtr now_function_; 143 144 std::map<std::string, std::vector<ReceiverObserver*>> observers_by_url_; 145 146 std::map<std::string, std::unique_ptr<ReceiverRequester>> 147 receiver_by_service_id_; 148 }; 149 150 } // namespace osp 151 } // namespace openscreen 152 153 #endif // OSP_IMPL_PRESENTATION_URL_AVAILABILITY_REQUESTER_H_ 154