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