blob: b0d0af597920f13b3578b0c708fe73df9aa46bce [file] [log] [blame]
Darin Petkovb72b62e2012-05-15 16:55:36 +02001// Copyright (c) 2012 The Chromium OS 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 "shill/wimax_provider.h"
6
Darin Petkove4b27022012-05-16 13:28:50 +02007#include <algorithm>
Darin Petkovfc00fd42012-05-30 11:30:06 +02008#include <set>
Darin Petkove4b27022012-05-16 13:28:50 +02009
Darin Petkovb72b62e2012-05-15 16:55:36 +020010#include <base/bind.h>
Darin Petkove4b27022012-05-16 13:28:50 +020011#include <base/string_util.h>
Ben Chanb879d142012-05-15 11:10:32 -070012#include <chromeos/dbus/service_constants.h>
Darin Petkovb72b62e2012-05-15 16:55:36 +020013
Darin Petkovb72b62e2012-05-15 16:55:36 +020014#include "shill/error.h"
Darin Petkovd1cd7972012-05-22 15:26:15 +020015#include "shill/key_value_store.h"
Christopher Wileyb691efd2012-08-09 13:51:51 -070016#include "shill/logging.h"
Darin Petkove4b27022012-05-16 13:28:50 +020017#include "shill/manager.h"
Darin Petkovc63dcf02012-05-24 11:51:43 +020018#include "shill/profile.h"
Darin Petkovb72b62e2012-05-15 16:55:36 +020019#include "shill/proxy_factory.h"
Darin Petkovc63dcf02012-05-24 11:51:43 +020020#include "shill/store_interface.h"
Darin Petkove4b27022012-05-16 13:28:50 +020021#include "shill/wimax.h"
Darin Petkovb72b62e2012-05-15 16:55:36 +020022#include "shill/wimax_manager_proxy_interface.h"
Darin Petkovd1cd7972012-05-22 15:26:15 +020023#include "shill/wimax_service.h"
Darin Petkovb72b62e2012-05-15 16:55:36 +020024
25using base::Bind;
26using base::Unretained;
Darin Petkove4b27022012-05-16 13:28:50 +020027using std::find;
28using std::map;
Darin Petkovc63dcf02012-05-24 11:51:43 +020029using std::set;
Darin Petkovb72b62e2012-05-15 16:55:36 +020030using std::string;
Darin Petkovb72b62e2012-05-15 16:55:36 +020031
32namespace shill {
33
Darin Petkovb72b62e2012-05-15 16:55:36 +020034WiMaxProvider::WiMaxProvider(ControlInterface *control,
35 EventDispatcher *dispatcher,
36 Metrics *metrics,
37 Manager *manager)
38 : control_(control),
39 dispatcher_(dispatcher),
40 metrics_(metrics),
41 manager_(manager),
42 proxy_factory_(ProxyFactory::GetInstance()) {}
43
Darin Petkovc63dcf02012-05-24 11:51:43 +020044WiMaxProvider::~WiMaxProvider() {}
Darin Petkovb72b62e2012-05-15 16:55:36 +020045
46void WiMaxProvider::Start() {
47 SLOG(WiMax, 2) << __func__;
Darin Petkovb501ad22012-07-03 12:50:52 +020048 if (!on_wimax_manager_appear_.IsCancelled()) {
Darin Petkovb72b62e2012-05-15 16:55:36 +020049 return;
50 }
Darin Petkovb501ad22012-07-03 12:50:52 +020051 // Registers a watcher for the WiMaxManager service. This provider will
52 // connect to it if/when the OnWiMaxManagerAppear callback is invoked.
53 on_wimax_manager_appear_.Reset(
54 Bind(&WiMaxProvider::OnWiMaxManagerAppear, Unretained(this)));
55 on_wimax_manager_vanish_.Reset(
56 Bind(&WiMaxProvider::DisconnectFromWiMaxManager, Unretained(this)));
57 manager_->dbus_manager()->WatchName(
58 wimax_manager::kWiMaxManagerServiceName,
59 on_wimax_manager_appear_.callback(),
60 on_wimax_manager_vanish_.callback());
Darin Petkovb72b62e2012-05-15 16:55:36 +020061}
62
63void WiMaxProvider::Stop() {
64 SLOG(WiMax, 2) << __func__;
Darin Petkovb501ad22012-07-03 12:50:52 +020065 // TODO(petkov): Deregister the watcher from DBusManager to avoid potential
Paul Stewartee6b3d72013-07-12 16:07:51 -070066 // memory leaks (crbug.com/214476).
Darin Petkovb501ad22012-07-03 12:50:52 +020067 on_wimax_manager_appear_.Cancel();
68 on_wimax_manager_vanish_.Cancel();
69 DisconnectFromWiMaxManager();
Darin Petkovc63dcf02012-05-24 11:51:43 +020070 DestroyAllServices();
Darin Petkovb72b62e2012-05-15 16:55:36 +020071}
72
Darin Petkovb501ad22012-07-03 12:50:52 +020073void WiMaxProvider::ConnectToWiMaxManager() {
74 DCHECK(!wimax_manager_proxy_.get());
75 LOG(INFO) << "Connecting to WiMaxManager.";
76 wimax_manager_proxy_.reset(proxy_factory_->CreateWiMaxManagerProxy());
77 wimax_manager_proxy_->set_devices_changed_callback(
78 Bind(&WiMaxProvider::OnDevicesChanged, Unretained(this)));
79 Error error;
80 OnDevicesChanged(wimax_manager_proxy_->Devices(&error));
81}
82
83void WiMaxProvider::DisconnectFromWiMaxManager() {
84 SLOG(WiMax, 2) << __func__;
85 if (!wimax_manager_proxy_.get()) {
86 return;
87 }
88 LOG(INFO) << "Disconnecting from WiMaxManager.";
89 wimax_manager_proxy_.reset();
90 OnDevicesChanged(RpcIdentifiers());
91}
92
93void WiMaxProvider::OnWiMaxManagerAppear(const string &owner) {
94 SLOG(WiMax, 2) << __func__ << "(" << owner << ")";
95 DisconnectFromWiMaxManager();
96 ConnectToWiMaxManager();
97}
98
Darin Petkove4b27022012-05-16 13:28:50 +020099void WiMaxProvider::OnDeviceInfoAvailable(const string &link_name) {
100 SLOG(WiMax, 2) << __func__ << "(" << link_name << ")";
Darin Petkovfc00fd42012-05-30 11:30:06 +0200101 map<string, RpcIdentifier>::const_iterator find_it =
Darin Petkovc1e52732012-05-25 15:23:45 +0200102 pending_devices_.find(link_name);
Darin Petkove4b27022012-05-16 13:28:50 +0200103 if (find_it != pending_devices_.end()) {
104 RpcIdentifier path = find_it->second;
105 CreateDevice(link_name, path);
106 }
107}
108
Darin Petkovc63dcf02012-05-24 11:51:43 +0200109void WiMaxProvider::OnNetworksChanged() {
110 SLOG(WiMax, 2) << __func__;
Darin Petkovfc00fd42012-05-30 11:30:06 +0200111 // Collects a set of live networks from all devices.
112 set<RpcIdentifier> live_networks;
113 for (map<string, WiMaxRefPtr>::const_iterator it = devices_.begin();
Darin Petkovc63dcf02012-05-24 11:51:43 +0200114 it != devices_.end(); ++it) {
115 const set<RpcIdentifier> &networks = it->second->networks();
Darin Petkovfc00fd42012-05-30 11:30:06 +0200116 live_networks.insert(networks.begin(), networks.end());
Darin Petkovc63dcf02012-05-24 11:51:43 +0200117 }
Darin Petkovfc00fd42012-05-30 11:30:06 +0200118 // Removes dead networks from |networks_|.
119 for (map<RpcIdentifier, NetworkInfo>::iterator it = networks_.begin();
120 it != networks_.end(); ) {
Darin Petkovb96a4512012-06-04 11:02:49 +0200121 const RpcIdentifier &path = it->first;
122 if (ContainsKey(live_networks, path)) {
Darin Petkovfc00fd42012-05-30 11:30:06 +0200123 ++it;
124 } else {
Darin Petkovb96a4512012-06-04 11:02:49 +0200125 LOG(INFO) << "WiMAX network disappeared: " << path;
Darin Petkovfc00fd42012-05-30 11:30:06 +0200126 networks_.erase(it++);
127 }
128 }
129 // Retrieves network info into |networks_| for the live networks.
130 for (set<RpcIdentifier>::const_iterator it = live_networks.begin();
131 it != live_networks.end(); ++it) {
132 RetrieveNetworkInfo(*it);
133 }
134 // Stops dead and starts live services based on the current |networks_|.
Darin Petkovc63dcf02012-05-24 11:51:43 +0200135 StopDeadServices();
136 StartLiveServices();
137}
138
Darin Petkovc1e52732012-05-25 15:23:45 +0200139bool WiMaxProvider::OnServiceUnloaded(const WiMaxServiceRefPtr &service) {
140 SLOG(WiMax, 2) << __func__ << "(" << service->GetStorageIdentifier() << ")";
141 if (service->is_default()) {
142 return false;
143 }
144 // Removes the service from the managed service set. The service will be
145 // deregistered from Manager when we release ownership by returning true.
146 services_.erase(service->GetStorageIdentifier());
147 return true;
148}
149
Paul Stewartbc14fb72013-07-30 08:21:58 -0700150// static
151bool WiMaxProvider::GetServiceParametersFromArgs(const KeyValueStore &args,
152 WiMaxNetworkId *id_ptr,
153 string *name_ptr,
154 Error *error) {
Darin Petkovd1cd7972012-05-22 15:26:15 +0200155 WiMaxNetworkId id = args.LookupString(WiMaxService::kNetworkIdProperty, "");
156 if (id.empty()) {
157 Error::PopulateAndLog(
158 error, Error::kInvalidArguments, "Missing WiMAX network id.");
Paul Stewartbc14fb72013-07-30 08:21:58 -0700159 return false;
Darin Petkovd1cd7972012-05-22 15:26:15 +0200160 }
161 string name = args.LookupString(flimflam::kNameProperty, "");
162 if (name.empty()) {
163 Error::PopulateAndLog(
164 error, Error::kInvalidArguments, "Missing WiMAX service name.");
Paul Stewartbc14fb72013-07-30 08:21:58 -0700165 return false;
166 }
167
168 *id_ptr = id;
169 *name_ptr = name;
170
171 return true;
172}
173
174ServiceRefPtr WiMaxProvider::GetService(const KeyValueStore &args,
175 Error *error) {
176 SLOG(WiMax, 2) << __func__;
177 CHECK_EQ(flimflam::kTypeWimax, args.GetString(flimflam::kTypeProperty));
178 WiMaxNetworkId id;
179 string name;
180 if (!GetServiceParametersFromArgs(args, &id, &name, error)) {
Darin Petkovd1cd7972012-05-22 15:26:15 +0200181 return NULL;
182 }
Darin Petkovc63dcf02012-05-24 11:51:43 +0200183 WiMaxServiceRefPtr service = GetUniqueService(id, name);
Darin Petkovd1cd7972012-05-22 15:26:15 +0200184 CHECK(service);
Darin Petkovfc00fd42012-05-30 11:30:06 +0200185 // Starts the service if there's a matching live network.
Darin Petkovc63dcf02012-05-24 11:51:43 +0200186 StartLiveServices();
Darin Petkovd1cd7972012-05-22 15:26:15 +0200187 return service;
188}
189
Paul Stewartbc14fb72013-07-30 08:21:58 -0700190ServiceRefPtr WiMaxProvider::FindSimilarService(const KeyValueStore &args,
191 Error *error) const {
192 SLOG(WiMax, 2) << __func__;
193 CHECK_EQ(flimflam::kTypeWimax, args.GetString(flimflam::kTypeProperty));
194 WiMaxNetworkId id;
195 string name;
196 if (!GetServiceParametersFromArgs(args, &id, &name, error)) {
197 return NULL;
198 }
199 string storage_id = WiMaxService::CreateStorageIdentifier(id, name);
200 WiMaxServiceRefPtr service = FindService(storage_id);
201 if (!service) {
202 error->Populate(Error::kNotFound, "Matching service was not found");
203 }
204 return service;
205}
206
207ServiceRefPtr WiMaxProvider::CreateTemporaryService(const KeyValueStore &args,
208 Error *error) {
209 SLOG(WiMax, 2) << __func__;
210 CHECK_EQ(flimflam::kTypeWimax, args.GetString(flimflam::kTypeProperty));
211 WiMaxNetworkId id;
212 string name;
213 if (!GetServiceParametersFromArgs(args, &id, &name, error)) {
214 return NULL;
215 }
216 return CreateService(id, name);
217}
218
Darin Petkovc63dcf02012-05-24 11:51:43 +0200219void WiMaxProvider::CreateServicesFromProfile(const ProfileRefPtr &profile) {
220 SLOG(WiMax, 2) << __func__;
221 bool created = false;
222 const StoreInterface *storage = profile->GetConstStorage();
223 set<string> groups = storage->GetGroupsWithKey(Service::kStorageType);
Darin Petkovfc00fd42012-05-30 11:30:06 +0200224 for (set<string>::const_iterator it = groups.begin();
225 it != groups.end(); ++it) {
Darin Petkovc63dcf02012-05-24 11:51:43 +0200226 const string &storage_id = *it;
227 string type;
228 if (!storage->GetString(storage_id, Service::kStorageType, &type) ||
229 type != Technology::NameFromIdentifier(Technology::kWiMax)) {
230 continue;
231 }
232 if (FindService(storage_id)) {
233 continue;
234 }
235 WiMaxNetworkId id;
236 if (!storage->GetString(storage_id, WiMaxService::kStorageNetworkId, &id) ||
237 id.empty()) {
238 LOG(ERROR) << "Unable to load network id: " << storage_id;
239 continue;
240 }
241 string name;
242 if (!storage->GetString(storage_id, Service::kStorageName, &name) ||
243 name.empty()) {
244 LOG(ERROR) << "Unable to load service name: " << storage_id;
245 continue;
246 }
247 WiMaxServiceRefPtr service = GetUniqueService(id, name);
248 CHECK(service);
249 if (!profile->ConfigureService(service)) {
250 LOG(ERROR) << "Could not configure service: " << storage_id;
251 }
252 created = true;
253 }
254 if (created) {
255 StartLiveServices();
256 }
257}
258
Darin Petkov6b9b2e12012-07-10 15:51:42 +0200259WiMaxRefPtr WiMaxProvider::SelectCarrier(
260 const WiMaxServiceConstRefPtr &service) {
Darin Petkovc63dcf02012-05-24 11:51:43 +0200261 SLOG(WiMax, 2) << __func__ << "(" << service->GetStorageIdentifier() << ")";
262 if (devices_.empty()) {
263 LOG(ERROR) << "No WiMAX devices available.";
264 return NULL;
265 }
266 // TODO(petkov): For now, just return the first available device. We need to
267 // be smarter here and select a device that sees |service|'s network.
268 return devices_.begin()->second;
269}
270
271void WiMaxProvider::OnDevicesChanged(const RpcIdentifiers &devices) {
272 SLOG(WiMax, 2) << __func__;
273 DestroyDeadDevices(devices);
274 for (RpcIdentifiers::const_iterator it = devices.begin();
275 it != devices.end(); ++it) {
276 const RpcIdentifier &path = *it;
277 string link_name = GetLinkName(path);
278 if (!link_name.empty()) {
279 CreateDevice(link_name, path);
280 }
281 }
282}
283
Darin Petkove4b27022012-05-16 13:28:50 +0200284void WiMaxProvider::CreateDevice(const string &link_name,
285 const RpcIdentifier &path) {
286 SLOG(WiMax, 2) << __func__ << "(" << link_name << ", " << path << ")";
Darin Petkov0fcd3462012-05-17 11:25:11 +0200287 if (ContainsKey(devices_, link_name)) {
288 SLOG(WiMax, 2) << "Device already exists.";
289 CHECK_EQ(path, devices_[link_name]->path());
290 return;
291 }
Darin Petkove4b27022012-05-16 13:28:50 +0200292 pending_devices_.erase(link_name);
293 DeviceInfo *device_info = manager_->device_info();
294 if (device_info->IsDeviceBlackListed(link_name)) {
Darin Petkovc63dcf02012-05-24 11:51:43 +0200295 LOG(INFO) << "WiMAX device not created, interface blacklisted: "
Darin Petkove4b27022012-05-16 13:28:50 +0200296 << link_name;
297 return;
298 }
299 int index = device_info->GetIndex(link_name);
300 if (index < 0) {
301 SLOG(WiMax, 2) << link_name << " pending device info.";
302 // Adds the link to the pending device map, waiting for a notification from
303 // DeviceInfo that it's received information about the device from RTNL.
304 pending_devices_[link_name] = path;
305 return;
306 }
307 ByteString address_bytes;
308 if (!device_info->GetMACAddress(index, &address_bytes)) {
Darin Petkovc63dcf02012-05-24 11:51:43 +0200309 LOG(ERROR) << "Unable to create a WiMAX device with no MAC address: "
Darin Petkove4b27022012-05-16 13:28:50 +0200310 << link_name;
311 return;
312 }
313 string address = address_bytes.HexEncode();
314 WiMaxRefPtr device(new WiMax(control_, dispatcher_, metrics_, manager_,
315 link_name, address, index, path));
Darin Petkov0fcd3462012-05-17 11:25:11 +0200316 devices_[link_name] = device;
Darin Petkove4b27022012-05-16 13:28:50 +0200317 device_info->RegisterDevice(device);
Darin Petkovc63dcf02012-05-24 11:51:43 +0200318 LOG(INFO) << "Created WiMAX device: " << link_name << " @ " << path;
Darin Petkove4b27022012-05-16 13:28:50 +0200319}
320
321void WiMaxProvider::DestroyDeadDevices(const RpcIdentifiers &live_devices) {
322 SLOG(WiMax, 2) << __func__ << "(" << live_devices.size() << ")";
Darin Petkovc1e52732012-05-25 15:23:45 +0200323 for (map<string, RpcIdentifier>::iterator it = pending_devices_.begin();
Darin Petkove4b27022012-05-16 13:28:50 +0200324 it != pending_devices_.end(); ) {
325 if (find(live_devices.begin(), live_devices.end(), it->second) ==
326 live_devices.end()) {
Darin Petkovc63dcf02012-05-24 11:51:43 +0200327 LOG(INFO) << "Forgetting pending device: " << it->second;
Darin Petkove4b27022012-05-16 13:28:50 +0200328 pending_devices_.erase(it++);
329 } else {
330 ++it;
331 }
332 }
Darin Petkov0fcd3462012-05-17 11:25:11 +0200333 for (map<string, WiMaxRefPtr>::iterator it = devices_.begin();
Darin Petkove4b27022012-05-16 13:28:50 +0200334 it != devices_.end(); ) {
Darin Petkov0fcd3462012-05-17 11:25:11 +0200335 if (find(live_devices.begin(), live_devices.end(), it->second->path()) ==
Darin Petkove4b27022012-05-16 13:28:50 +0200336 live_devices.end()) {
Darin Petkovc63dcf02012-05-24 11:51:43 +0200337 LOG(INFO) << "Destroying device: " << it->first;
Darin Petkovb96a4512012-06-04 11:02:49 +0200338 const WiMaxRefPtr &device = it->second;
339 device->OnDeviceVanished();
340 manager_->device_info()->DeregisterDevice(device);
Darin Petkov0fcd3462012-05-17 11:25:11 +0200341 devices_.erase(it++);
Darin Petkove4b27022012-05-16 13:28:50 +0200342 } else {
343 ++it;
344 }
345 }
346}
347
348string WiMaxProvider::GetLinkName(const RpcIdentifier &path) {
Darin Petkov9893d9c2012-05-17 15:27:31 -0700349 if (StartsWithASCII(path, wimax_manager::kDeviceObjectPathPrefix, true)) {
350 return path.substr(strlen(wimax_manager::kDeviceObjectPathPrefix));
Darin Petkove4b27022012-05-16 13:28:50 +0200351 }
352 LOG(ERROR) << "Unable to determine link name from RPC path: " << path;
353 return string();
Darin Petkovb72b62e2012-05-15 16:55:36 +0200354}
355
Darin Petkovfc00fd42012-05-30 11:30:06 +0200356void WiMaxProvider::RetrieveNetworkInfo(const RpcIdentifier &path) {
357 if (ContainsKey(networks_, path)) {
358 // Nothing to do, the network info is already available.
359 return;
360 }
Darin Petkovb96a4512012-06-04 11:02:49 +0200361 LOG(INFO) << "WiMAX network appeared: " << path;
Darin Petkovfc00fd42012-05-30 11:30:06 +0200362 scoped_ptr<WiMaxNetworkProxyInterface> proxy(
363 proxy_factory_->CreateWiMaxNetworkProxy(path));
364 Error error;
365 NetworkInfo info;
366 info.name = proxy->Name(&error);
367 if (error.IsFailure()) {
368 return;
369 }
370 uint32 identifier = proxy->Identifier(&error);
371 if (error.IsFailure()) {
372 return;
373 }
374 info.id = WiMaxService::ConvertIdentifierToNetworkId(identifier);
375 networks_[path] = info;
376}
377
Paul Stewartbc14fb72013-07-30 08:21:58 -0700378WiMaxServiceRefPtr WiMaxProvider::FindService(const string &storage_id) const {
Darin Petkovc63dcf02012-05-24 11:51:43 +0200379 SLOG(WiMax, 2) << __func__ << "(" << storage_id << ")";
Darin Petkovc1e52732012-05-25 15:23:45 +0200380 map<string, WiMaxServiceRefPtr>::const_iterator find_it =
381 services_.find(storage_id);
382 if (find_it == services_.end()) {
383 return NULL;
Darin Petkovc63dcf02012-05-24 11:51:43 +0200384 }
Darin Petkovc1e52732012-05-25 15:23:45 +0200385 const WiMaxServiceRefPtr &service = find_it->second;
386 LOG_IF(ERROR, storage_id != service->GetStorageIdentifier());
387 return service;
Darin Petkovc63dcf02012-05-24 11:51:43 +0200388}
389
390WiMaxServiceRefPtr WiMaxProvider::GetUniqueService(const WiMaxNetworkId &id,
391 const string &name) {
392 SLOG(WiMax, 2) << __func__ << "(" << id << ", " << name << ")";
393 string storage_id = WiMaxService::CreateStorageIdentifier(id, name);
394 WiMaxServiceRefPtr service = FindService(storage_id);
395 if (service) {
396 SLOG(WiMax, 2) << "Service already exists.";
397 return service;
398 }
Paul Stewartbc14fb72013-07-30 08:21:58 -0700399 service = CreateService(id, name);
Darin Petkovc1e52732012-05-25 15:23:45 +0200400 services_[service->GetStorageIdentifier()] = service;
Darin Petkovc63dcf02012-05-24 11:51:43 +0200401 manager_->RegisterService(service);
402 LOG(INFO) << "Registered WiMAX service: " << service->GetStorageIdentifier();
403 return service;
404}
405
Paul Stewartbc14fb72013-07-30 08:21:58 -0700406WiMaxServiceRefPtr WiMaxProvider::CreateService(const WiMaxNetworkId &id,
407 const string &name) {
408 WiMaxServiceRefPtr service =
409 new WiMaxService(control_, dispatcher_, metrics_, manager_);
410 service->set_network_id(id);
411 service->set_friendly_name(name);
412 service->InitStorageIdentifier();
413 return service;
414}
415
Darin Petkovc63dcf02012-05-24 11:51:43 +0200416void WiMaxProvider::StartLiveServices() {
Darin Petkovfc00fd42012-05-30 11:30:06 +0200417 SLOG(WiMax, 2) << __func__ << "(" << networks_.size() << ")";
418 for (map<RpcIdentifier, NetworkInfo>::const_iterator nit = networks_.begin();
419 nit != networks_.end(); ++nit) {
420 const RpcIdentifier &path = nit->first;
421 const NetworkInfo &info = nit->second;
Darin Petkovc63dcf02012-05-24 11:51:43 +0200422
Darin Petkovfc00fd42012-05-30 11:30:06 +0200423 // Creates the default service for the network, if not already created.
424 GetUniqueService(info.id, info.name)->set_is_default(true);
425
426 // Starts services for this live network.
427 for (map<string, WiMaxServiceRefPtr>::const_iterator it = services_.begin();
428 it != services_.end(); ++it) {
429 const WiMaxServiceRefPtr &service = it->second;
430 if (service->network_id() != info.id || service->IsStarted()) {
431 continue;
432 }
433 if (!service->Start(proxy_factory_->CreateWiMaxNetworkProxy(path))) {
434 LOG(ERROR) << "Unable to start service: "
435 << service->GetStorageIdentifier();
436 }
Darin Petkovc63dcf02012-05-24 11:51:43 +0200437 }
438 }
439}
440
441void WiMaxProvider::StopDeadServices() {
442 SLOG(WiMax, 2) << __func__ << "(" << networks_.size() << ")";
Darin Petkovc1e52732012-05-25 15:23:45 +0200443 for (map<string, WiMaxServiceRefPtr>::iterator it = services_.begin();
444 it != services_.end(); ) {
Darin Petkovc33eba82012-06-28 10:51:16 +0200445 // Keeps a local reference until we're done with this service.
446 WiMaxServiceRefPtr service = it->second;
Darin Petkovc1e52732012-05-25 15:23:45 +0200447 if (service->IsStarted() &&
448 !ContainsKey(networks_, service->GetNetworkObjectPath())) {
449 service->Stop();
450 // Default services are created and registered when a network becomes
451 // live. They need to be deregistered and destroyed when the network
452 // disappears.
453 if (service->is_default()) {
Darin Petkovc33eba82012-06-28 10:51:16 +0200454 // Removes |service| from the managed service set before deregistering
455 // it from Manager to ensure correct iterator increment (consider
456 // Manager::DeregisterService -> WiMaxService::Unload ->
457 // WiMaxProvider::OnServiceUnloaded -> services_.erase).
Darin Petkovc1e52732012-05-25 15:23:45 +0200458 services_.erase(it++);
Darin Petkovc33eba82012-06-28 10:51:16 +0200459 manager_->DeregisterService(service);
Darin Petkovc1e52732012-05-25 15:23:45 +0200460 continue;
461 }
Darin Petkovc63dcf02012-05-24 11:51:43 +0200462 }
Darin Petkovc1e52732012-05-25 15:23:45 +0200463 ++it;
Darin Petkovc63dcf02012-05-24 11:51:43 +0200464 }
465}
466
467void WiMaxProvider::DestroyAllServices() {
468 SLOG(WiMax, 2) << __func__;
Darin Petkovc33eba82012-06-28 10:51:16 +0200469 while (!services_.empty()) {
470 // Keeps a local reference until we're done with this service.
471 WiMaxServiceRefPtr service = services_.begin()->second;
472 services_.erase(services_.begin());
473 // Stops the service so that it can notify its carrier device, if any.
Darin Petkovc63dcf02012-05-24 11:51:43 +0200474 service->Stop();
475 manager_->DeregisterService(service);
476 LOG(INFO) << "Deregistered WiMAX service: "
477 << service->GetStorageIdentifier();
Darin Petkovc63dcf02012-05-24 11:51:43 +0200478 }
479}
480
Darin Petkovb72b62e2012-05-15 16:55:36 +0200481} // namespace shill