blob: a12c8828abd070e34570c8cb9c479716c4248f52 [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>
8
Darin Petkovb72b62e2012-05-15 16:55:36 +02009#include <base/bind.h>
Darin Petkove4b27022012-05-16 13:28:50 +020010#include <base/string_util.h>
Ben Chanb879d142012-05-15 11:10:32 -070011#include <chromeos/dbus/service_constants.h>
Darin Petkovb72b62e2012-05-15 16:55:36 +020012
Darin Petkovb72b62e2012-05-15 16:55:36 +020013#include "shill/error.h"
Darin Petkove4b27022012-05-16 13:28:50 +020014#include "shill/manager.h"
Darin Petkovb72b62e2012-05-15 16:55:36 +020015#include "shill/proxy_factory.h"
16#include "shill/scope_logger.h"
Darin Petkove4b27022012-05-16 13:28:50 +020017#include "shill/wimax.h"
Darin Petkovb72b62e2012-05-15 16:55:36 +020018#include "shill/wimax_manager_proxy_interface.h"
19
20using base::Bind;
21using base::Unretained;
Darin Petkove4b27022012-05-16 13:28:50 +020022using std::find;
23using std::map;
Darin Petkovb72b62e2012-05-15 16:55:36 +020024using std::string;
25using std::vector;
26
27namespace shill {
28
Darin Petkovb72b62e2012-05-15 16:55:36 +020029WiMaxProvider::WiMaxProvider(ControlInterface *control,
30 EventDispatcher *dispatcher,
31 Metrics *metrics,
32 Manager *manager)
33 : control_(control),
34 dispatcher_(dispatcher),
35 metrics_(metrics),
36 manager_(manager),
37 proxy_factory_(ProxyFactory::GetInstance()) {}
38
39WiMaxProvider::~WiMaxProvider() {
40 Stop();
41}
42
43void WiMaxProvider::Start() {
44 SLOG(WiMax, 2) << __func__;
45 if (manager_proxy_.get()) {
46 return;
47 }
Darin Petkovb72b62e2012-05-15 16:55:36 +020048 manager_proxy_.reset(proxy_factory_->CreateWiMaxManagerProxy());
Darin Petkov9893d9c2012-05-17 15:27:31 -070049 manager_proxy_->set_devices_changed_callback(
50 Bind(&WiMaxProvider::OnDevicesChanged, Unretained(this)));
Darin Petkovb72b62e2012-05-15 16:55:36 +020051 Error error;
Darin Petkov9893d9c2012-05-17 15:27:31 -070052 OnDevicesChanged(manager_proxy_->Devices(&error));
Darin Petkovb72b62e2012-05-15 16:55:36 +020053}
54
55void WiMaxProvider::Stop() {
56 SLOG(WiMax, 2) << __func__;
Darin Petkovb72b62e2012-05-15 16:55:36 +020057 manager_proxy_.reset();
Darin Petkove4b27022012-05-16 13:28:50 +020058 DestroyDeadDevices(RpcIdentifiers());
Darin Petkovb72b62e2012-05-15 16:55:36 +020059}
60
Darin Petkov9893d9c2012-05-17 15:27:31 -070061void WiMaxProvider::OnDevicesChanged(const RpcIdentifiers &devices) {
Darin Petkovb72b62e2012-05-15 16:55:36 +020062 SLOG(WiMax, 2) << __func__;
Darin Petkove4b27022012-05-16 13:28:50 +020063 DestroyDeadDevices(devices);
64 for (RpcIdentifiers::const_iterator it = devices.begin();
65 it != devices.end(); ++it) {
66 string link_name = GetLinkName(*it);
67 if (!link_name.empty()) {
68 CreateDevice(link_name, *it);
69 }
70 }
Darin Petkovb72b62e2012-05-15 16:55:36 +020071}
72
Darin Petkove4b27022012-05-16 13:28:50 +020073void WiMaxProvider::OnDeviceInfoAvailable(const string &link_name) {
74 SLOG(WiMax, 2) << __func__ << "(" << link_name << ")";
75 map<string, string>::iterator find_it = pending_devices_.find(link_name);
76 if (find_it != pending_devices_.end()) {
77 RpcIdentifier path = find_it->second;
78 CreateDevice(link_name, path);
79 }
80}
81
82void WiMaxProvider::CreateDevice(const string &link_name,
83 const RpcIdentifier &path) {
84 SLOG(WiMax, 2) << __func__ << "(" << link_name << ", " << path << ")";
Darin Petkov0fcd3462012-05-17 11:25:11 +020085 if (ContainsKey(devices_, link_name)) {
86 SLOG(WiMax, 2) << "Device already exists.";
87 CHECK_EQ(path, devices_[link_name]->path());
88 return;
89 }
Darin Petkove4b27022012-05-16 13:28:50 +020090 pending_devices_.erase(link_name);
91 DeviceInfo *device_info = manager_->device_info();
92 if (device_info->IsDeviceBlackListed(link_name)) {
93 LOG(INFO) << "Do not create WiMax device for blacklisted interface "
94 << link_name;
95 return;
96 }
97 int index = device_info->GetIndex(link_name);
98 if (index < 0) {
99 SLOG(WiMax, 2) << link_name << " pending device info.";
100 // Adds the link to the pending device map, waiting for a notification from
101 // DeviceInfo that it's received information about the device from RTNL.
102 pending_devices_[link_name] = path;
103 return;
104 }
105 ByteString address_bytes;
106 if (!device_info->GetMACAddress(index, &address_bytes)) {
Darin Petkov0fcd3462012-05-17 11:25:11 +0200107 LOG(ERROR) << "Unable to create a WiMax device with no MAC address: "
Darin Petkove4b27022012-05-16 13:28:50 +0200108 << link_name;
109 return;
110 }
111 string address = address_bytes.HexEncode();
112 WiMaxRefPtr device(new WiMax(control_, dispatcher_, metrics_, manager_,
113 link_name, address, index, path));
Darin Petkov0fcd3462012-05-17 11:25:11 +0200114 devices_[link_name] = device;
Darin Petkove4b27022012-05-16 13:28:50 +0200115 device_info->RegisterDevice(device);
116}
117
118void WiMaxProvider::DestroyDeadDevices(const RpcIdentifiers &live_devices) {
119 SLOG(WiMax, 2) << __func__ << "(" << live_devices.size() << ")";
120 for (map<string, string>::iterator it = pending_devices_.begin();
121 it != pending_devices_.end(); ) {
122 if (find(live_devices.begin(), live_devices.end(), it->second) ==
123 live_devices.end()) {
124 SLOG(WiMax, 2) << "Forgetting pending device: " << it->second;
125 pending_devices_.erase(it++);
126 } else {
127 ++it;
128 }
129 }
Darin Petkov0fcd3462012-05-17 11:25:11 +0200130 for (map<string, WiMaxRefPtr>::iterator it = devices_.begin();
Darin Petkove4b27022012-05-16 13:28:50 +0200131 it != devices_.end(); ) {
Darin Petkov0fcd3462012-05-17 11:25:11 +0200132 if (find(live_devices.begin(), live_devices.end(), it->second->path()) ==
Darin Petkove4b27022012-05-16 13:28:50 +0200133 live_devices.end()) {
Darin Petkov0fcd3462012-05-17 11:25:11 +0200134 SLOG(WiMax, 2) << "Destroying device: " << it->first;
135 manager_->device_info()->DeregisterDevice(it->second);
136 devices_.erase(it++);
Darin Petkove4b27022012-05-16 13:28:50 +0200137 } else {
138 ++it;
139 }
140 }
141}
142
143string WiMaxProvider::GetLinkName(const RpcIdentifier &path) {
Darin Petkov9893d9c2012-05-17 15:27:31 -0700144 if (StartsWithASCII(path, wimax_manager::kDeviceObjectPathPrefix, true)) {
145 return path.substr(strlen(wimax_manager::kDeviceObjectPathPrefix));
Darin Petkove4b27022012-05-16 13:28:50 +0200146 }
147 LOG(ERROR) << "Unable to determine link name from RPC path: " << path;
148 return string();
Darin Petkovb72b62e2012-05-15 16:55:36 +0200149}
150
151} // namespace shill