Home | History | Annotate | Download | only in wimax
      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;
     52 static string ObjectID(const WiMaxProvider* w) { return "(wimax_provider)"; }
     53 }
     54 
     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 
     64 WiMaxProvider::~WiMaxProvider() {}
     65 
     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 
     79 void WiMaxProvider::Stop() {
     80   SLOG(this, 2) << __func__;
     81   wimax_manager_proxy_.reset();
     82   DisconnectFromWiMaxManager();
     83   DestroyAllServices();
     84 }
     85 
     86 void WiMaxProvider::ConnectToWiMaxManager() {
     87   LOG(INFO) << "Connected to WiMaxManager.";
     88   Error error;
     89   OnDevicesChanged(wimax_manager_proxy_->Devices(&error));
     90 }
     91 
     92 void WiMaxProvider::DisconnectFromWiMaxManager() {
     93   SLOG(this, 2) << __func__;
     94   LOG(INFO) << "Disconnected from WiMaxManager.";
     95   OnDevicesChanged(RpcIdentifiers());
     96 }
     97 
     98 void WiMaxProvider::OnWiMaxManagerAppeared() {
     99   SLOG(this, 2) << __func__;
    100   DisconnectFromWiMaxManager();
    101   ConnectToWiMaxManager();
    102 }
    103 
    104 void WiMaxProvider::OnWiMaxManagerVanished() {
    105   SLOG(this, 2) << __func__;
    106   DisconnectFromWiMaxManager();
    107 }
    108 
    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 
    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 
    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
    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
    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 
    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 
    228 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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    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 
    418 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 
    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 
    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 
    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 
    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 
    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