blob: 86d5eb730c20259c71fca0877d77e07d97eb7acd [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
13#include "shill/dbus_properties_proxy_interface.h"
14#include "shill/error.h"
Darin Petkove4b27022012-05-16 13:28:50 +020015#include "shill/manager.h"
Darin Petkovb72b62e2012-05-15 16:55:36 +020016#include "shill/proxy_factory.h"
17#include "shill/scope_logger.h"
Darin Petkove4b27022012-05-16 13:28:50 +020018#include "shill/wimax.h"
Darin Petkovb72b62e2012-05-15 16:55:36 +020019#include "shill/wimax_manager_proxy_interface.h"
20
21using base::Bind;
22using base::Unretained;
Darin Petkove4b27022012-05-16 13:28:50 +020023using std::find;
24using std::map;
Darin Petkovb72b62e2012-05-15 16:55:36 +020025using std::string;
26using std::vector;
27
28namespace shill {
29
Darin Petkove4b27022012-05-16 13:28:50 +020030namespace {
31// TODO(petkov): Add these to chromeos/dbus/service_constants.h.
32const char kWiMaxDevicePathPrefix[] = "/org/chromium/WiMaxManager/Device/";
33const char kWiMaxManagerDevicesProperty[] = "Devices";
34} // namespace
35
Darin Petkovb72b62e2012-05-15 16:55:36 +020036WiMaxProvider::WiMaxProvider(ControlInterface *control,
37 EventDispatcher *dispatcher,
38 Metrics *metrics,
39 Manager *manager)
40 : control_(control),
41 dispatcher_(dispatcher),
42 metrics_(metrics),
43 manager_(manager),
44 proxy_factory_(ProxyFactory::GetInstance()) {}
45
46WiMaxProvider::~WiMaxProvider() {
47 Stop();
48}
49
50void WiMaxProvider::Start() {
51 SLOG(WiMax, 2) << __func__;
52 if (manager_proxy_.get()) {
53 return;
54 }
55 properties_proxy_.reset(
56 proxy_factory_->CreateDBusPropertiesProxy(
Ben Chanb879d142012-05-15 11:10:32 -070057 wimax_manager::kWiMaxManagerServicePath,
58 wimax_manager::kWiMaxManagerServiceName));
Darin Petkovb72b62e2012-05-15 16:55:36 +020059 properties_proxy_->set_properties_changed_callback(
60 Bind(&WiMaxProvider::OnPropertiesChanged, Unretained(this)));
61 manager_proxy_.reset(proxy_factory_->CreateWiMaxManagerProxy());
62 Error error;
63 UpdateDevices(manager_proxy_->Devices(&error));
64}
65
66void WiMaxProvider::Stop() {
67 SLOG(WiMax, 2) << __func__;
68 properties_proxy_.reset();
69 manager_proxy_.reset();
Darin Petkove4b27022012-05-16 13:28:50 +020070 DestroyDeadDevices(RpcIdentifiers());
Darin Petkovb72b62e2012-05-15 16:55:36 +020071}
72
Darin Petkove4b27022012-05-16 13:28:50 +020073void WiMaxProvider::UpdateDevices(const RpcIdentifiers &devices) {
Darin Petkovb72b62e2012-05-15 16:55:36 +020074 SLOG(WiMax, 2) << __func__;
Darin Petkove4b27022012-05-16 13:28:50 +020075 DestroyDeadDevices(devices);
76 for (RpcIdentifiers::const_iterator it = devices.begin();
77 it != devices.end(); ++it) {
78 string link_name = GetLinkName(*it);
79 if (!link_name.empty()) {
80 CreateDevice(link_name, *it);
81 }
82 }
Darin Petkovb72b62e2012-05-15 16:55:36 +020083}
84
85void WiMaxProvider::OnPropertiesChanged(
86 const string &/*interface*/,
Darin Petkove4b27022012-05-16 13:28:50 +020087 const DBusPropertiesMap &changed_properties,
Darin Petkovb72b62e2012-05-15 16:55:36 +020088 const vector<string> &/*invalidated_properties*/) {
89 SLOG(WiMax, 2) << __func__;
Darin Petkove4b27022012-05-16 13:28:50 +020090 RpcIdentifiers devices;
91 if (DBusProperties::GetRpcIdentifiers(
92 changed_properties, kWiMaxManagerDevicesProperty, &devices)) {
93 UpdateDevices(devices);
94 }
95}
96
97void WiMaxProvider::OnDeviceInfoAvailable(const string &link_name) {
98 SLOG(WiMax, 2) << __func__ << "(" << link_name << ")";
99 map<string, string>::iterator find_it = pending_devices_.find(link_name);
100 if (find_it != pending_devices_.end()) {
101 RpcIdentifier path = find_it->second;
102 CreateDevice(link_name, path);
103 }
104}
105
106void WiMaxProvider::CreateDevice(const string &link_name,
107 const RpcIdentifier &path) {
108 SLOG(WiMax, 2) << __func__ << "(" << link_name << ", " << path << ")";
109 pending_devices_.erase(link_name);
110 DeviceInfo *device_info = manager_->device_info();
111 if (device_info->IsDeviceBlackListed(link_name)) {
112 LOG(INFO) << "Do not create WiMax device for blacklisted interface "
113 << link_name;
114 return;
115 }
116 int index = device_info->GetIndex(link_name);
117 if (index < 0) {
118 SLOG(WiMax, 2) << link_name << " pending device info.";
119 // Adds the link to the pending device map, waiting for a notification from
120 // DeviceInfo that it's received information about the device from RTNL.
121 pending_devices_[link_name] = path;
122 return;
123 }
124 ByteString address_bytes;
125 if (!device_info->GetMACAddress(index, &address_bytes)) {
126 LOG(ERROR) << "Unable to create a WiMax device with not MAC address: "
127 << link_name;
128 return;
129 }
130 string address = address_bytes.HexEncode();
131 WiMaxRefPtr device(new WiMax(control_, dispatcher_, metrics_, manager_,
132 link_name, address, index, path));
133 devices_.push_back(device);
134 device_info->RegisterDevice(device);
135}
136
137void WiMaxProvider::DestroyDeadDevices(const RpcIdentifiers &live_devices) {
138 SLOG(WiMax, 2) << __func__ << "(" << live_devices.size() << ")";
139 for (map<string, string>::iterator it = pending_devices_.begin();
140 it != pending_devices_.end(); ) {
141 if (find(live_devices.begin(), live_devices.end(), it->second) ==
142 live_devices.end()) {
143 SLOG(WiMax, 2) << "Forgetting pending device: " << it->second;
144 pending_devices_.erase(it++);
145 } else {
146 ++it;
147 }
148 }
149 for (vector<WiMaxRefPtr>::iterator it = devices_.begin();
150 it != devices_.end(); ) {
151 if (find(live_devices.begin(), live_devices.end(), (*it)->path()) ==
152 live_devices.end()) {
153 SLOG(WiMax, 2) << "Destroying device: " << (*it)->link_name();
154 manager_->device_info()->DeregisterDevice(*it);
155 it = devices_.erase(it);
156 } else {
157 ++it;
158 }
159 }
160}
161
162string WiMaxProvider::GetLinkName(const RpcIdentifier &path) {
163 if (StartsWithASCII(path, kWiMaxDevicePathPrefix, true)) {
164 return path.substr(strlen(kWiMaxDevicePathPrefix));
165 }
166 LOG(ERROR) << "Unable to determine link name from RPC path: " << path;
167 return string();
Darin Petkovb72b62e2012-05-15 16:55:36 +0200168}
169
170} // namespace shill