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_PUBLIC_SERVICE_LISTENER_H_
6 #define OSP_PUBLIC_SERVICE_LISTENER_H_
7 
8 #include <cstdint>
9 #include <string>
10 #include <vector>
11 
12 #include "osp/public/service_info.h"
13 #include "osp/public/timestamp.h"
14 #include "platform/base/macros.h"
15 
16 namespace openscreen {
17 namespace osp {
18 
19 // Used to report an error from a ServiceListener implementation.
20 struct ServiceListenerError {
21  public:
22   // TODO(mfoltz): Add additional error types, as implementations progress.
23   enum class Code {
24     kNone = 0,
25   };
26 
27   ServiceListenerError();
28   ServiceListenerError(Code error, const std::string& message);
29   ServiceListenerError(const ServiceListenerError& other);
30   ~ServiceListenerError();
31 
32   ServiceListenerError& operator=(const ServiceListenerError& other);
33 
34   Code error;
35   std::string message;
36 };
37 
38 class ServiceListener {
39  public:
40   enum class State {
41     kStopped = 0,
42     kStarting,
43     kRunning,
44     kStopping,
45     kSearching,
46     kSuspended,
47   };
48 
49   // Holds a set of metrics, captured over a specific range of time, about the
50   // behavior of a ServiceListener instance.
51   struct Metrics {
52     Metrics();
53     ~Metrics();
54 
55     // The range of time over which the metrics were collected; end_timestamp >
56     // start_timestamp
57     timestamp_t start_timestamp = 0;
58     timestamp_t end_timestamp = 0;
59 
60     // The number of packets and bytes sent over the timestamp range.
61     uint64_t num_packets_sent = 0;
62     uint64_t num_bytes_sent = 0;
63 
64     // The number of packets and bytes received over the timestamp range.
65     uint64_t num_packets_received = 0;
66     uint64_t num_bytes_received = 0;
67 
68     // The maximum number of receivers discovered over the timestamp range.  The
69     // latter two fields break this down by receivers advertising ipv4 and ipv6
70     // endpoints.
71     size_t num_receivers = 0;
72     size_t num_ipv4_receivers = 0;
73     size_t num_ipv6_receivers = 0;
74   };
75 
76   class Observer {
77    public:
78     virtual ~Observer() = default;
79 
80     // Called when the state becomes kRunning.
81     virtual void OnStarted() = 0;
82     // Called when the state becomes kStopped.
83     virtual void OnStopped() = 0;
84     // Called when the state becomes kSuspended.
85     virtual void OnSuspended() = 0;
86     // Called when the state becomes kSearching.
87     virtual void OnSearching() = 0;
88 
89     // Notifications to changes to the listener's receiver list.
90     virtual void OnReceiverAdded(const ServiceInfo&) = 0;
91     virtual void OnReceiverChanged(const ServiceInfo&) = 0;
92     virtual void OnReceiverRemoved(const ServiceInfo&) = 0;
93     // Called if all receivers are no longer available, e.g. all network
94     // interfaces have been disabled.
95     virtual void OnAllReceiversRemoved() = 0;
96 
97     // Reports an error.
98     virtual void OnError(ServiceListenerError) = 0;
99 
100     // Reports metrics.
101     virtual void OnMetrics(Metrics) = 0;
102   };
103 
104   virtual ~ServiceListener();
105 
106   // Starts listening for receivers using the config object.
107   // Returns true if state() == kStopped and the service will be started, false
108   // otherwise.
109   virtual bool Start() = 0;
110 
111   // Starts the listener in kSuspended mode.  This could be used to enable
112   // immediate search via SearchNow() in the future.
113   // Returns true if state() == kStopped and the service will be started, false
114   // otherwise.
115   virtual bool StartAndSuspend() = 0;
116 
117   // Stops listening and cancels any search in progress.
118   // Returns true if state() != (kStopped|kStopping).
119   virtual bool Stop() = 0;
120 
121   // Suspends background listening. For example, the tab wanting receiver
122   // availability might go in the background, meaning we can suspend listening
123   // to save power.
124   // Returns true if state() == (kRunning|kSearching|kStarting), meaning the
125   // suspension will take effect.
126   virtual bool Suspend() = 0;
127 
128   // Resumes listening.  Returns true if state() == (kSuspended|kSearching).
129   virtual bool Resume() = 0;
130 
131   // Asks the listener to search for receivers now, even if the listener is
132   // is currently suspended.  If a background search is already in
133   // progress, this has no effect.  Returns true if state() ==
134   // (kRunning|kSuspended).
135   virtual bool SearchNow() = 0;
136 
137   virtual void AddObserver(Observer* observer) = 0;
138   virtual void RemoveObserver(Observer* observer) = 0;
139 
140   // Returns the current state of the listener.
state()141   State state() const { return state_; }
142 
143   // Returns the last error reported by this listener.
last_error()144   const ServiceListenerError& last_error() const { return last_error_; }
145 
146   // Returns the current list of receivers known to the ServiceListener.
147   virtual const std::vector<ServiceInfo>& GetReceivers() const = 0;
148 
149  protected:
150   ServiceListener();
151 
152   State state_;
153   ServiceListenerError last_error_;
154   std::vector<Observer*> observers_;
155 
156   OSP_DISALLOW_COPY_AND_ASSIGN(ServiceListener);
157 };
158 
159 }  // namespace osp
160 }  // namespace openscreen
161 
162 #endif  // OSP_PUBLIC_SERVICE_LISTENER_H_
163