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 #include "osp/impl/service_listener_impl.h" 6 7 #include <algorithm> 8 9 #include "platform/base/error.h" 10 #include "util/osp_logging.h" 11 12 namespace openscreen { 13 namespace osp { 14 namespace { 15 IsTransitionValid(ServiceListener::State from,ServiceListener::State to)16bool IsTransitionValid(ServiceListener::State from, ServiceListener::State to) { 17 switch (from) { 18 case ServiceListener::State::kStopped: 19 return to == ServiceListener::State::kStarting || 20 to == ServiceListener::State::kStopping; 21 case ServiceListener::State::kStarting: 22 return to == ServiceListener::State::kRunning || 23 to == ServiceListener::State::kStopping || 24 to == ServiceListener::State::kSuspended; 25 case ServiceListener::State::kRunning: 26 return to == ServiceListener::State::kSuspended || 27 to == ServiceListener::State::kSearching || 28 to == ServiceListener::State::kStopping; 29 case ServiceListener::State::kStopping: 30 return to == ServiceListener::State::kStopped; 31 case ServiceListener::State::kSearching: 32 return to == ServiceListener::State::kRunning || 33 to == ServiceListener::State::kSuspended || 34 to == ServiceListener::State::kStopping; 35 case ServiceListener::State::kSuspended: 36 return to == ServiceListener::State::kRunning || 37 to == ServiceListener::State::kSearching || 38 to == ServiceListener::State::kStopping; 39 default: 40 OSP_DCHECK(false) << "unknown ServiceListener::State value: " 41 << static_cast<int>(from); 42 break; 43 } 44 return false; 45 } 46 47 } // namespace 48 49 ServiceListenerImpl::Delegate::Delegate() = default; 50 ServiceListenerImpl::Delegate::~Delegate() = default; 51 SetListenerImpl(ServiceListenerImpl * listener)52void ServiceListenerImpl::Delegate::SetListenerImpl( 53 ServiceListenerImpl* listener) { 54 OSP_DCHECK(!listener_); 55 listener_ = listener; 56 } 57 ServiceListenerImpl(Delegate * delegate)58ServiceListenerImpl::ServiceListenerImpl(Delegate* delegate) 59 : delegate_(delegate) { 60 delegate_->SetListenerImpl(this); 61 } 62 63 ServiceListenerImpl::~ServiceListenerImpl() = default; 64 OnReceiverAdded(const ServiceInfo & info)65void ServiceListenerImpl::OnReceiverAdded(const ServiceInfo& info) { 66 receiver_list_.OnReceiverAdded(info); 67 for (auto* observer : observers_) { 68 observer->OnReceiverAdded(info); 69 } 70 } 71 OnReceiverChanged(const ServiceInfo & info)72void ServiceListenerImpl::OnReceiverChanged(const ServiceInfo& info) { 73 const Error changed_error = receiver_list_.OnReceiverChanged(info); 74 if (changed_error.ok()) { 75 for (auto* observer : observers_) { 76 observer->OnReceiverChanged(info); 77 } 78 } 79 } 80 OnReceiverRemoved(const ServiceInfo & info)81void ServiceListenerImpl::OnReceiverRemoved(const ServiceInfo& info) { 82 const Error removed_error = receiver_list_.OnReceiverRemoved(info); 83 if (removed_error.ok()) { 84 for (auto* observer : observers_) { 85 observer->OnReceiverRemoved(info); 86 } 87 } 88 } 89 OnAllReceiversRemoved()90void ServiceListenerImpl::OnAllReceiversRemoved() { 91 const Error removed_all_error = receiver_list_.OnAllReceiversRemoved(); 92 if (removed_all_error.ok()) { 93 for (auto* observer : observers_) { 94 observer->OnAllReceiversRemoved(); 95 } 96 } 97 } 98 OnError(ServiceListenerError error)99void ServiceListenerImpl::OnError(ServiceListenerError error) { 100 last_error_ = error; 101 for (auto* observer : observers_) { 102 observer->OnError(error); 103 } 104 } 105 Start()106bool ServiceListenerImpl::Start() { 107 if (state_ != State::kStopped) 108 return false; 109 state_ = State::kStarting; 110 delegate_->StartListener(); 111 return true; 112 } 113 StartAndSuspend()114bool ServiceListenerImpl::StartAndSuspend() { 115 if (state_ != State::kStopped) 116 return false; 117 state_ = State::kStarting; 118 delegate_->StartAndSuspendListener(); 119 return true; 120 } 121 Stop()122bool ServiceListenerImpl::Stop() { 123 if (state_ == State::kStopped || state_ == State::kStopping) 124 return false; 125 126 state_ = State::kStopping; 127 delegate_->StopListener(); 128 return true; 129 } 130 Suspend()131bool ServiceListenerImpl::Suspend() { 132 if (state_ != State::kRunning && state_ != State::kSearching && 133 state_ != State::kStarting) { 134 return false; 135 } 136 delegate_->SuspendListener(); 137 return true; 138 } 139 Resume()140bool ServiceListenerImpl::Resume() { 141 if (state_ != State::kSuspended && state_ != State::kSearching) 142 return false; 143 144 delegate_->ResumeListener(); 145 return true; 146 } 147 SearchNow()148bool ServiceListenerImpl::SearchNow() { 149 if (state_ != State::kRunning && state_ != State::kSuspended) 150 return false; 151 152 delegate_->SearchNow(state_); 153 return true; 154 } 155 AddObserver(Observer * observer)156void ServiceListenerImpl::AddObserver(Observer* observer) { 157 OSP_DCHECK(observer); 158 observers_.push_back(observer); 159 } 160 RemoveObserver(Observer * observer)161void ServiceListenerImpl::RemoveObserver(Observer* observer) { 162 // TODO(btolsch): Consider writing an ObserverList in base/ for things like 163 // CHECK()ing that the list is empty on destruction. 164 observers_.erase(std::remove(observers_.begin(), observers_.end(), observer), 165 observers_.end()); 166 } 167 GetReceivers() const168const std::vector<ServiceInfo>& ServiceListenerImpl::GetReceivers() const { 169 return receiver_list_.receivers(); 170 } 171 SetState(State state)172void ServiceListenerImpl::SetState(State state) { 173 OSP_DCHECK(IsTransitionValid(state_, state)); 174 state_ = state; 175 if (!observers_.empty()) { 176 MaybeNotifyObservers(); 177 } 178 } 179 MaybeNotifyObservers()180void ServiceListenerImpl::MaybeNotifyObservers() { 181 OSP_DCHECK(!observers_.empty()); 182 switch (state_) { 183 case State::kRunning: 184 for (auto* observer : observers_) { 185 observer->OnStarted(); 186 } 187 break; 188 case State::kStopped: 189 for (auto* observer : observers_) { 190 observer->OnStopped(); 191 } 192 break; 193 case State::kSuspended: 194 for (auto* observer : observers_) { 195 observer->OnSuspended(); 196 } 197 break; 198 case State::kSearching: 199 for (auto* observer : observers_) { 200 observer->OnSearching(); 201 } 202 break; 203 default: 204 break; 205 } 206 } 207 208 } // namespace osp 209 } // namespace openscreen 210