• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright (C) 2012 The Android Open Source Project
3 //
4 // Licensed under the Apache License, Version 2.0 (the "License");
5 // you may not use this file except in compliance with the License.
6 // You may obtain a copy of the License at
7 //
8 //      http://www.apache.org/licenses/LICENSE-2.0
9 //
10 // Unless required by applicable law or agreed to in writing, software
11 // distributed under the License is distributed on an "AS IS" BASIS,
12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 // See the License for the specific language governing permissions and
14 // limitations under the License.
15 //
16 
17 #include "shill/wimax/wimax_provider.h"
18 
19 #include <algorithm>
20 #include <set>
21 
22 #include <base/bind.h>
23 #include <base/strings/string_util.h>
24 #if defined(__ANDROID__)
25 #include <dbus/service_constants.h>
26 #else
27 #include <chromeos/dbus/service_constants.h>
28 #endif  // __ANDROID__
29 
30 #include "shill/control_interface.h"
31 #include "shill/error.h"
32 #include "shill/key_value_store.h"
33 #include "shill/logging.h"
34 #include "shill/manager.h"
35 #include "shill/profile.h"
36 #include "shill/store_interface.h"
37 #include "shill/wimax/wimax.h"
38 #include "shill/wimax/wimax_manager_proxy_interface.h"
39 #include "shill/wimax/wimax_service.h"
40 
41 using base::Bind;
42 using base::Unretained;
43 using std::find;
44 using std::map;
45 using std::set;
46 using std::string;
47 
48 namespace shill {
49 
50 namespace Logging {
51 static auto kModuleLogScope = ScopeLogger::kWiMax;
ObjectID(const WiMaxProvider * w)52 static string ObjectID(const WiMaxProvider* w) { return "(wimax_provider)"; }
53 }
54 
WiMaxProvider(ControlInterface * control,EventDispatcher * dispatcher,Metrics * metrics,Manager * manager)55 WiMaxProvider::WiMaxProvider(ControlInterface* control,
56                              EventDispatcher* dispatcher,
57                              Metrics* metrics,
58                              Manager* manager)
59     : control_(control),
60       dispatcher_(dispatcher),
61       metrics_(metrics),
62       manager_(manager) {}
63 
~WiMaxProvider()64 WiMaxProvider::~WiMaxProvider() {}
65 
Start()66 void WiMaxProvider::Start() {
67   SLOG(this, 2) << __func__;
68 
69   // Create a proxy for WiMaxManager service. This provider will connect to it
70   // if/when the OnWiMaxManagerAppear callback is invoked.
71   wimax_manager_proxy_.reset(
72       control_->CreateWiMaxManagerProxy(
73           Bind(&WiMaxProvider::OnWiMaxManagerAppeared, Unretained(this)),
74           Bind(&WiMaxProvider::OnWiMaxManagerVanished, Unretained(this))));
75   wimax_manager_proxy_->set_devices_changed_callback(
76       Bind(&WiMaxProvider::OnDevicesChanged, Unretained(this)));
77 }
78 
Stop()79 void WiMaxProvider::Stop() {
80   SLOG(this, 2) << __func__;
81   wimax_manager_proxy_.reset();
82   DisconnectFromWiMaxManager();
83   DestroyAllServices();
84 }
85 
ConnectToWiMaxManager()86 void WiMaxProvider::ConnectToWiMaxManager() {
87   LOG(INFO) << "Connected to WiMaxManager.";
88   Error error;
89   OnDevicesChanged(wimax_manager_proxy_->Devices(&error));
90 }
91 
DisconnectFromWiMaxManager()92 void WiMaxProvider::DisconnectFromWiMaxManager() {
93   SLOG(this, 2) << __func__;
94   LOG(INFO) << "Disconnected from WiMaxManager.";
95   OnDevicesChanged(RpcIdentifiers());
96 }
97 
OnWiMaxManagerAppeared()98 void WiMaxProvider::OnWiMaxManagerAppeared() {
99   SLOG(this, 2) << __func__;
100   DisconnectFromWiMaxManager();
101   ConnectToWiMaxManager();
102 }
103 
OnWiMaxManagerVanished()104 void WiMaxProvider::OnWiMaxManagerVanished() {
105   SLOG(this, 2) << __func__;
106   DisconnectFromWiMaxManager();
107 }
108 
OnDeviceInfoAvailable(const string & link_name)109 void WiMaxProvider::OnDeviceInfoAvailable(const string& link_name) {
110   SLOG(this, 2) << __func__ << "(" << link_name << ")";
111   map<string, RpcIdentifier>::const_iterator find_it =
112       pending_devices_.find(link_name);
113   if (find_it != pending_devices_.end()) {
114     RpcIdentifier path = find_it->second;
115     CreateDevice(link_name, path);
116   }
117 }
118 
OnNetworksChanged()119 void WiMaxProvider::OnNetworksChanged() {
120   SLOG(this, 2) << __func__;
121   // Collects a set of live networks from all devices.
122   set<RpcIdentifier> live_networks;
123   for (const auto& device : devices_) {
124     const set<RpcIdentifier>& networks = device.second->networks();
125     live_networks.insert(networks.begin(), networks.end());
126   }
127   // Removes dead networks from |networks_|.
128   for (auto it = networks_.begin(); it != networks_.end(); ) {
129     const RpcIdentifier& path = it->first;
130     if (ContainsKey(live_networks, path)) {
131       ++it;
132     } else {
133       LOG(INFO) << "WiMAX network disappeared: " << path;
134       it = networks_.erase(it);
135     }
136   }
137   // Retrieves network info into |networks_| for the live networks.
138   for (const auto& network : live_networks) {
139     RetrieveNetworkInfo(network);
140   }
141   // Stops dead and starts live services based on the current |networks_|.
142   StopDeadServices();
143   StartLiveServices();
144 }
145 
OnServiceUnloaded(const WiMaxServiceRefPtr & service)146 bool WiMaxProvider::OnServiceUnloaded(const WiMaxServiceRefPtr& service) {
147   SLOG(this, 2) << __func__ << "(" << service->GetStorageIdentifier() << ")";
148   if (service->is_default()) {
149     return false;
150   }
151   // Removes the service from the managed service set. The service will be
152   // deregistered from Manager when we release ownership by returning true.
153   services_.erase(service->GetStorageIdentifier());
154   return true;
155 }
156 
157 // static
GetServiceParametersFromArgs(const KeyValueStore & args,WiMaxNetworkId * id_ptr,string * name_ptr,Error * error)158 bool WiMaxProvider::GetServiceParametersFromArgs(const KeyValueStore& args,
159                                                  WiMaxNetworkId* id_ptr,
160                                                  string* name_ptr,
161                                                  Error* error) {
162   WiMaxNetworkId id = args.LookupString(WiMaxService::kNetworkIdProperty, "");
163   if (id.empty()) {
164     Error::PopulateAndLog(
165         FROM_HERE, error, Error::kInvalidArguments,
166         "Missing WiMAX network id.");
167     return false;
168   }
169   string name = args.LookupString(kNameProperty, "");
170   if (name.empty()) {
171     Error::PopulateAndLog(
172         FROM_HERE, error, Error::kInvalidArguments,
173         "Missing WiMAX service name.");
174     return false;
175   }
176 
177   *id_ptr = id;
178   *name_ptr = name;
179 
180   return true;
181 }
182 
183 // static
GetServiceParametersFromStorage(const StoreInterface * storage,const std::string & entry_name,WiMaxNetworkId * id_ptr,std::string * name_ptr,Error * error)184 bool WiMaxProvider::GetServiceParametersFromStorage(
185     const StoreInterface* storage,
186     const std::string& entry_name,
187     WiMaxNetworkId* id_ptr,
188     std::string* name_ptr,
189     Error* error) {
190   string type;
191   if (!storage->GetString(entry_name, Service::kStorageType, &type) ||
192       type != kTypeWimax) {
193     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
194                           "Unspecified or invalid network type");
195     return false;
196   }
197   if (!storage->GetString(entry_name, WiMaxService::kStorageNetworkId, id_ptr)
198       || id_ptr->empty()) {
199     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
200                           "Network ID not specified");
201     return false;
202   }
203   if (!storage->GetString(entry_name, Service::kStorageName, name_ptr) ||
204       name_ptr->empty()) {
205     Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
206                           "Network name not specified");
207     return false;
208   }
209   return true;
210 }
211 
GetService(const KeyValueStore & args,Error * error)212 ServiceRefPtr WiMaxProvider::GetService(const KeyValueStore& args,
213                                         Error* error) {
214   SLOG(this, 2) << __func__;
215   CHECK_EQ(kTypeWimax, args.GetString(kTypeProperty));
216   WiMaxNetworkId id;
217   string name;
218   if (!GetServiceParametersFromArgs(args, &id, &name, error)) {
219     return nullptr;
220   }
221   WiMaxServiceRefPtr service = GetUniqueService(id, name);
222   CHECK(service);
223   // Starts the service if there's a matching live network.
224   StartLiveServices();
225   return service;
226 }
227 
FindSimilarService(const KeyValueStore & args,Error * error) const228 ServiceRefPtr WiMaxProvider::FindSimilarService(const KeyValueStore& args,
229                                                 Error* error) const {
230   SLOG(this, 2) << __func__;
231   CHECK_EQ(kTypeWimax, args.GetString(kTypeProperty));
232   WiMaxNetworkId id;
233   string name;
234   if (!GetServiceParametersFromArgs(args, &id, &name, error)) {
235     return nullptr;
236   }
237   string storage_id = WiMaxService::CreateStorageIdentifier(id, name);
238   WiMaxServiceRefPtr service = FindService(storage_id);
239   if (!service) {
240     error->Populate(Error::kNotFound, "Matching service was not found");
241   }
242   return service;
243 }
244 
CreateTemporaryService(const KeyValueStore & args,Error * error)245 ServiceRefPtr WiMaxProvider::CreateTemporaryService(const KeyValueStore& args,
246                                                     Error* error) {
247   SLOG(this, 2) << __func__;
248   CHECK_EQ(kTypeWimax, args.GetString(kTypeProperty));
249   WiMaxNetworkId id;
250   string name;
251   if (!GetServiceParametersFromArgs(args, &id, &name, error)) {
252     return nullptr;
253   }
254   return CreateService(id, name);
255 }
256 
CreateTemporaryServiceFromProfile(const ProfileRefPtr & profile,const std::string & entry_name,Error * error)257 ServiceRefPtr WiMaxProvider::CreateTemporaryServiceFromProfile(
258     const ProfileRefPtr& profile, const std::string& entry_name, Error* error) {
259   WiMaxNetworkId id;
260   string name;
261   if (!GetServiceParametersFromStorage(profile->GetConstStorage(),
262                                        entry_name,
263                                        &id,
264                                        &name,
265                                        error)) {
266     return nullptr;
267   }
268   return CreateService(id, name);
269 }
270 
CreateServicesFromProfile(const ProfileRefPtr & profile)271 void WiMaxProvider::CreateServicesFromProfile(const ProfileRefPtr& profile) {
272   SLOG(this, 2) << __func__;
273   bool created = false;
274   const StoreInterface* storage = profile->GetConstStorage();
275   KeyValueStore args;
276   args.SetString(kTypeProperty, kTypeWimax);
277   for (const auto& storage_id : storage->GetGroupsWithProperties(args)) {
278     WiMaxNetworkId id;
279     string name;
280     if (!GetServiceParametersFromStorage(storage,
281                                          storage_id,
282                                          &id,
283                                          &name,
284                                          nullptr)) {
285       continue;
286     }
287     if (FindService(storage_id)) {
288       continue;
289     }
290     WiMaxServiceRefPtr service = GetUniqueService(id, name);
291     CHECK(service);
292     if (!profile->ConfigureService(service)) {
293       LOG(ERROR) << "Could not configure service: " << storage_id;
294     }
295     created = true;
296   }
297   if (created) {
298     StartLiveServices();
299   }
300 }
301 
SelectCarrier(const WiMaxServiceConstRefPtr & service)302 WiMaxRefPtr WiMaxProvider::SelectCarrier(
303     const WiMaxServiceConstRefPtr& service) {
304   SLOG(this, 2) << __func__ << "(" << service->GetStorageIdentifier() << ")";
305   if (devices_.empty()) {
306     LOG(ERROR) << "No WiMAX devices available.";
307     return nullptr;
308   }
309   // TODO(petkov): For now, just return the first available device. We need to
310   // be smarter here and select a device that sees |service|'s network.
311   return devices_.begin()->second;
312 }
313 
OnDevicesChanged(const RpcIdentifiers & devices)314 void WiMaxProvider::OnDevicesChanged(const RpcIdentifiers& devices) {
315   SLOG(this, 2) << __func__;
316   DestroyDeadDevices(devices);
317   for (const auto& path : devices) {
318     string link_name = GetLinkName(path);
319     if (!link_name.empty()) {
320       CreateDevice(link_name, path);
321     }
322   }
323 }
324 
CreateDevice(const string & link_name,const RpcIdentifier & path)325 void WiMaxProvider::CreateDevice(const string& link_name,
326                                  const RpcIdentifier& path) {
327   SLOG(this, 2) << __func__ << "(" << link_name << ", " << path << ")";
328   if (ContainsKey(devices_, link_name)) {
329     SLOG(this, 2) << "Device already exists.";
330     CHECK_EQ(path, devices_[link_name]->path());
331     return;
332   }
333   pending_devices_.erase(link_name);
334   DeviceInfo* device_info = manager_->device_info();
335   if (device_info->IsDeviceBlackListed(link_name)) {
336     LOG(INFO) << "WiMAX device not created, interface blacklisted: "
337               << link_name;
338     return;
339   }
340   int index = device_info->GetIndex(link_name);
341   if (index < 0) {
342     SLOG(this, 2) << link_name << " pending device info.";
343     // Adds the link to the pending device map, waiting for a notification from
344     // DeviceInfo that it's received information about the device from RTNL.
345     pending_devices_[link_name] = path;
346     return;
347   }
348   ByteString address_bytes;
349   if (!device_info->GetMACAddress(index, &address_bytes)) {
350     LOG(ERROR) << "Unable to create a WiMAX device with no MAC address: "
351                << link_name;
352     return;
353   }
354   string address = address_bytes.HexEncode();
355   WiMaxRefPtr device(new WiMax(control_, dispatcher_, metrics_, manager_,
356                                link_name, address, index, path));
357   devices_[link_name] = device;
358   device_info->RegisterDevice(device);
359   LOG(INFO) << "Created WiMAX device: " << link_name << " @ " << path;
360 }
361 
DestroyDeadDevices(const RpcIdentifiers & live_devices)362 void WiMaxProvider::DestroyDeadDevices(const RpcIdentifiers& live_devices) {
363   SLOG(this, 2) << __func__ << "(" << live_devices.size() << ")";
364   for (auto it = pending_devices_.begin(); it != pending_devices_.end(); ) {
365     if (find(live_devices.begin(), live_devices.end(), it->second) ==
366         live_devices.end()) {
367       LOG(INFO) << "Forgetting pending device: " << it->second;
368       it = pending_devices_.erase(it);
369     } else {
370       ++it;
371     }
372   }
373   for (auto it = devices_.begin(); it != devices_.end(); ) {
374     if (find(live_devices.begin(), live_devices.end(), it->second->path()) ==
375         live_devices.end()) {
376       LOG(INFO) << "Destroying device: " << it->first;
377       const WiMaxRefPtr& device = it->second;
378       device->OnDeviceVanished();
379       manager_->device_info()->DeregisterDevice(device);
380       it = devices_.erase(it);
381     } else {
382       ++it;
383     }
384   }
385 }
386 
GetLinkName(const RpcIdentifier & path)387 string WiMaxProvider::GetLinkName(const RpcIdentifier& path) {
388   if (base::StartsWith(path, wimax_manager::kDeviceObjectPathPrefix,
389                        base::CompareCase::SENSITIVE)) {
390     return path.substr(strlen(wimax_manager::kDeviceObjectPathPrefix));
391   }
392   LOG(ERROR) << "Unable to determine link name from RPC path: " << path;
393   return string();
394 }
395 
RetrieveNetworkInfo(const RpcIdentifier & path)396 void WiMaxProvider::RetrieveNetworkInfo(const RpcIdentifier& path) {
397   if (ContainsKey(networks_, path)) {
398     // Nothing to do, the network info is already available.
399     return;
400   }
401   LOG(INFO) << "WiMAX network appeared: " << path;
402   std::unique_ptr<WiMaxNetworkProxyInterface> proxy(
403       control_->CreateWiMaxNetworkProxy(path));
404   Error error;
405   NetworkInfo info;
406   info.name = proxy->Name(&error);
407   if (error.IsFailure()) {
408     return;
409   }
410   uint32_t identifier = proxy->Identifier(&error);
411   if (error.IsFailure()) {
412     return;
413   }
414   info.id = WiMaxService::ConvertIdentifierToNetworkId(identifier);
415   networks_[path] = info;
416 }
417 
FindService(const string & storage_id) const418 WiMaxServiceRefPtr WiMaxProvider::FindService(const string& storage_id) const {
419   SLOG(this, 2) << __func__ << "(" << storage_id << ")";
420   map<string, WiMaxServiceRefPtr>::const_iterator find_it =
421       services_.find(storage_id);
422   if (find_it == services_.end()) {
423     return nullptr;
424   }
425   const WiMaxServiceRefPtr& service = find_it->second;
426   LOG_IF(ERROR, storage_id != service->GetStorageIdentifier());
427   return service;
428 }
429 
GetUniqueService(const WiMaxNetworkId & id,const string & name)430 WiMaxServiceRefPtr WiMaxProvider::GetUniqueService(const WiMaxNetworkId& id,
431                                                    const string& name) {
432   SLOG(this, 2) << __func__ << "(" << id << ", " << name << ")";
433   string storage_id = WiMaxService::CreateStorageIdentifier(id, name);
434   WiMaxServiceRefPtr service = FindService(storage_id);
435   if (service) {
436     SLOG(this, 2) << "Service already exists.";
437     return service;
438   }
439   service = CreateService(id, name);
440   services_[service->GetStorageIdentifier()] = service;
441   manager_->RegisterService(service);
442   LOG(INFO) << "Registered WiMAX service: " << service->GetStorageIdentifier();
443   return service;
444 }
445 
CreateService(const WiMaxNetworkId & id,const string & name)446 WiMaxServiceRefPtr WiMaxProvider::CreateService(const WiMaxNetworkId& id,
447                                                 const string& name) {
448   WiMaxServiceRefPtr service =
449       new WiMaxService(control_, dispatcher_, metrics_, manager_);
450   service->set_network_id(id);
451   service->set_friendly_name(name);
452   service->InitStorageIdentifier();
453   return service;
454 }
455 
StartLiveServices()456 void WiMaxProvider::StartLiveServices() {
457   SLOG(this, 2) << __func__ << "(" << networks_.size() << ")";
458   for (const auto& nit : networks_) {
459     const RpcIdentifier& path = nit.first;
460     const NetworkInfo& info = nit.second;
461 
462     // Creates the default service for the network, if not already created.
463     GetUniqueService(info.id, info.name)->set_is_default(true);
464 
465     // Starts services for this live network.
466     for (const auto& entry : services_) {
467       const WiMaxServiceRefPtr& service = entry.second;
468       if (service->network_id() != info.id || service->IsStarted()) {
469         continue;
470       }
471       if (!service->Start(control_->CreateWiMaxNetworkProxy(path))) {
472         LOG(ERROR) << "Unable to start service: "
473                    << service->GetStorageIdentifier();
474       }
475     }
476   }
477 }
478 
StopDeadServices()479 void WiMaxProvider::StopDeadServices() {
480   SLOG(this, 2) << __func__ << "(" << networks_.size() << ")";
481   for (map<string, WiMaxServiceRefPtr>::iterator it = services_.begin();
482        it != services_.end(); ) {
483     // Keeps a local reference until we're done with this service.
484     WiMaxServiceRefPtr service = it->second;
485     if (service->IsStarted() &&
486         !ContainsKey(networks_, service->GetNetworkObjectPath())) {
487       service->Stop();
488       // Default services are created and registered when a network becomes
489       // live. They need to be deregistered and destroyed when the network
490       // disappears.
491       if (service->is_default()) {
492         // Removes |service| from the managed service set before deregistering
493         // it from Manager to ensure correct iterator increment (consider
494         // Manager::DeregisterService -> WiMaxService::Unload ->
495         // WiMaxProvider::OnServiceUnloaded -> services_.erase).
496         services_.erase(it++);
497         manager_->DeregisterService(service);
498         continue;
499       }
500     }
501     ++it;
502   }
503 }
504 
DestroyAllServices()505 void WiMaxProvider::DestroyAllServices() {
506   SLOG(this, 2) << __func__;
507   while (!services_.empty()) {
508     // Keeps a local reference until we're done with this service.
509     WiMaxServiceRefPtr service = services_.begin()->second;
510     services_.erase(services_.begin());
511     // Stops the service so that it can notify its carrier device, if any.
512     service->Stop();
513     manager_->DeregisterService(service);
514     LOG(INFO) << "Deregistered WiMAX service: "
515               << service->GetStorageIdentifier();
516   }
517 }
518 
519 }  // namespace shill
520