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