• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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