blob: f96d6b2c0958fe07fdba9cb6147fe67419a943b5 [file] [log] [blame]
Ben Chan99c8a4d2012-05-01 08:11:53 -07001// 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.h"
6
Darin Petkov912f0de2012-05-16 14:12:14 +02007#include <base/bind.h>
Darin Petkov9893d9c2012-05-17 15:27:31 -07008#include <base/stringprintf.h>
Darin Petkov912f0de2012-05-16 14:12:14 +02009
10#include "shill/manager.h"
Darin Petkovb72b62e2012-05-15 16:55:36 +020011#include "shill/proxy_factory.h"
12#include "shill/scope_logger.h"
13#include "shill/wimax_device_proxy_interface.h"
Darin Petkov912f0de2012-05-16 14:12:14 +020014#include "shill/wimax_service.h"
Darin Petkovb72b62e2012-05-15 16:55:36 +020015
Darin Petkov912f0de2012-05-16 14:12:14 +020016using base::Bind;
Darin Petkov9893d9c2012-05-17 15:27:31 -070017using std::map;
Ben Chan99c8a4d2012-05-01 08:11:53 -070018using std::string;
19
20namespace shill {
21
Darin Petkov912f0de2012-05-16 14:12:14 +020022const int WiMax::kTimeoutDefault = 30000;
23
Ben Chan99c8a4d2012-05-01 08:11:53 -070024WiMax::WiMax(ControlInterface *control,
25 EventDispatcher *dispatcher,
26 Metrics *metrics,
27 Manager *manager,
28 const string &link_name,
Ben Chan4e64d2d2012-05-16 00:02:25 -070029 const string &address,
Darin Petkovb72b62e2012-05-15 16:55:36 +020030 int interface_index,
31 const RpcIdentifier &path)
Ben Chan4e64d2d2012-05-16 00:02:25 -070032 : Device(control, dispatcher, metrics, manager, link_name, address,
Darin Petkovb72b62e2012-05-15 16:55:36 +020033 interface_index, Technology::kWiMax),
34 path_(path),
Darin Petkov9893d9c2012-05-17 15:27:31 -070035 scanning_(false),
Darin Petkovb72b62e2012-05-15 16:55:36 +020036 proxy_factory_(ProxyFactory::GetInstance()) {
37 SLOG(WiMax, 2) << __func__ << "(" << link_name << ", " << path << ")";
Darin Petkov9893d9c2012-05-17 15:27:31 -070038 PropertyStore *store = mutable_store();
39 store->RegisterConstBool(flimflam::kScanningProperty, &scanning_);
Darin Petkovb72b62e2012-05-15 16:55:36 +020040}
Ben Chan99c8a4d2012-05-01 08:11:53 -070041
Darin Petkovb72b62e2012-05-15 16:55:36 +020042WiMax::~WiMax() {
43 SLOG(WiMax, 2) << __func__ << "(" << link_name() << ", " << path_ << ")";
44}
Ben Chan99c8a4d2012-05-01 08:11:53 -070045
46void WiMax::Start(Error *error, const EnabledStateChangedCallback &callback) {
Darin Petkovb72b62e2012-05-15 16:55:36 +020047 SLOG(WiMax, 2) << __func__;
Darin Petkov9893d9c2012-05-17 15:27:31 -070048 scanning_ = false;
Darin Petkovb72b62e2012-05-15 16:55:36 +020049 proxy_.reset(proxy_factory_->CreateWiMaxDeviceProxy(path_));
Darin Petkov9893d9c2012-05-17 15:27:31 -070050 proxy_->set_networks_changed_callback(
51 Bind(&WiMax::OnNetworksChanged, Unretained(this)));
Darin Petkov912f0de2012-05-16 14:12:14 +020052 proxy_->Enable(
53 error, Bind(&WiMax::OnEnableComplete, this, callback), kTimeoutDefault);
Ben Chan99c8a4d2012-05-01 08:11:53 -070054}
55
56void WiMax::Stop(Error *error, const EnabledStateChangedCallback &callback) {
Darin Petkovb72b62e2012-05-15 16:55:36 +020057 SLOG(WiMax, 2) << __func__;
Darin Petkov9893d9c2012-05-17 15:27:31 -070058 DestroyDeadServices(RpcIdentifiers());
Darin Petkov912f0de2012-05-16 14:12:14 +020059 proxy_->Disable(
60 error, Bind(&WiMax::OnDisableComplete, this, callback), kTimeoutDefault);
Ben Chan99c8a4d2012-05-01 08:11:53 -070061}
62
63bool WiMax::TechnologyIs(const Technology::Identifier type) const {
64 return type == Technology::kWiMax;
65}
66
Darin Petkov9893d9c2012-05-17 15:27:31 -070067void WiMax::Scan(Error *error) {
Darin Petkov912f0de2012-05-16 14:12:14 +020068 SLOG(WiMax, 2) << __func__;
Darin Petkov9893d9c2012-05-17 15:27:31 -070069 if (scanning_) {
70 Error::PopulateAndLog(
71 error, Error::kInProgress, "Scan already in progress.");
72 return;
73 }
74 scanning_ = true;
75 proxy_->ScanNetworks(
76 error, Bind(&WiMax::OnScanNetworksComplete, this), kTimeoutDefault);
77 if (error->IsFailure()) {
78 OnScanNetworksComplete(*error);
79 }
Ben Chan99c8a4d2012-05-01 08:11:53 -070080}
81
Darin Petkov9893d9c2012-05-17 15:27:31 -070082void WiMax::ConnectTo(const WiMaxServiceRefPtr &service, Error *error) {
83 SLOG(WiMax, 2) << __func__ << "(" << service->friendly_name() << ")";
84 if (pending_service_) {
85 Error::PopulateAndLog(
86 error, Error::kInProgress,
87 base::StringPrintf(
88 "Pending connect to %s, ignoring connect request to %s.",
89 pending_service_->friendly_name().c_str(),
90 service->friendly_name().c_str()));
91 return;
92 }
93 service->SetState(Service::kStateAssociating);
94 pending_service_ = service;
Ben Chan4e5c1312012-05-18 18:45:38 -070095
96 DBusPropertiesMap parameters;
97 service->GetConnectParameters(&parameters);
Darin Petkov9893d9c2012-05-17 15:27:31 -070098 proxy_->Connect(
Ben Chan4e5c1312012-05-18 18:45:38 -070099 service->GetNetworkObjectPath(), parameters,
Darin Petkov9893d9c2012-05-17 15:27:31 -0700100 error, Bind(&WiMax::OnConnectComplete, this), kTimeoutDefault);
101 if (error->IsFailure()) {
102 OnConnectComplete(*error);
103 }
104}
105
106void WiMax::DisconnectFrom(const WiMaxServiceRefPtr &service, Error *error) {
Darin Petkov912f0de2012-05-16 14:12:14 +0200107 SLOG(WiMax, 2) << __func__;
Darin Petkov9893d9c2012-05-17 15:27:31 -0700108 if (pending_service_) {
109 Error::PopulateAndLog(
110 error, Error::kInProgress,
111 base::StringPrintf(
112 "Pending connect to %s, ignoring disconnect request from %s.",
113 pending_service_->friendly_name().c_str(),
114 service->friendly_name().c_str()));
115 return;
116 }
117 if (selected_service() && service != selected_service()) {
118 Error::PopulateAndLog(
119 error, Error::kNotConnected,
120 base::StringPrintf(
121 "Curent service is %s, ignoring disconnect request from %s.",
122 selected_service()->friendly_name().c_str(),
123 service->friendly_name().c_str()));
124 return;
125 }
Darin Petkov912f0de2012-05-16 14:12:14 +0200126 proxy_->Disconnect(
127 error, Bind(&WiMax::OnDisconnectComplete, this), kTimeoutDefault);
Darin Petkov9893d9c2012-05-17 15:27:31 -0700128 if (error->IsFailure()) {
129 OnDisconnectComplete(Error());
130 }
131}
132
133void WiMax::OnScanNetworksComplete(const Error &/*error*/) {
134 SLOG(WiMax, 2) << __func__;
135 scanning_ = false;
136 // The networks are updated when the NetworksChanged signal is received.
Darin Petkov912f0de2012-05-16 14:12:14 +0200137}
138
139void WiMax::OnConnectComplete(const Error &error) {
140 SLOG(WiMax, 2) << __func__;
Darin Petkov9893d9c2012-05-17 15:27:31 -0700141 if (!pending_service_) {
142 LOG(ERROR) << "Unexpected OnConnectComplete callback.";
143 return;
144 }
Darin Petkov126d5862012-05-17 14:39:11 +0200145 if (error.IsSuccess() && AcquireIPConfig()) {
Darin Petkov9893d9c2012-05-17 15:27:31 -0700146 LOG(INFO) << "Connected to " << pending_service_->friendly_name();
147 SelectService(pending_service_);
Darin Petkov126d5862012-05-17 14:39:11 +0200148 SetServiceState(Service::kStateConfiguring);
149 } else {
Darin Petkov9893d9c2012-05-17 15:27:31 -0700150 LOG(ERROR) << "Unable to connect to " << pending_service_->friendly_name();
151 pending_service_->SetState(Service::kStateFailure);
Darin Petkov912f0de2012-05-16 14:12:14 +0200152 }
Darin Petkov9893d9c2012-05-17 15:27:31 -0700153 pending_service_ = NULL;
Darin Petkov912f0de2012-05-16 14:12:14 +0200154}
155
Darin Petkov9893d9c2012-05-17 15:27:31 -0700156void WiMax::OnDisconnectComplete(const Error &/*error*/) {
Darin Petkov912f0de2012-05-16 14:12:14 +0200157 SLOG(WiMax, 2) << __func__;
Darin Petkov126d5862012-05-17 14:39:11 +0200158 DestroyIPConfig();
Darin Petkov912f0de2012-05-16 14:12:14 +0200159 SelectService(NULL);
160}
161
162void WiMax::OnEnableComplete(const EnabledStateChangedCallback &callback,
163 const Error &error) {
164 SLOG(WiMax, 2) << __func__;
165 if (error.IsFailure()) {
166 proxy_.reset();
167 } else {
Darin Petkov9893d9c2012-05-17 15:27:31 -0700168 // Scan for networks to allow service creation when the network list becomes
169 // available.
170 Error e;
171 Scan(&e);
Darin Petkov912f0de2012-05-16 14:12:14 +0200172 }
173 callback.Run(error);
Darin Petkov912f0de2012-05-16 14:12:14 +0200174}
175
176void WiMax::OnDisableComplete(const EnabledStateChangedCallback &callback,
177 const Error &error) {
178 SLOG(WiMax, 2) << __func__;
Darin Petkov9893d9c2012-05-17 15:27:31 -0700179 proxy_.reset();
Darin Petkov912f0de2012-05-16 14:12:14 +0200180 callback.Run(error);
Ben Chan99c8a4d2012-05-01 08:11:53 -0700181}
182
Darin Petkov9893d9c2012-05-17 15:27:31 -0700183void WiMax::OnNetworksChanged(const RpcIdentifiers &networks) {
184 SLOG(WiMax, 2) << __func__;
185 DestroyDeadServices(networks);
186 for (RpcIdentifiers::const_iterator it = networks.begin();
187 it != networks.end(); ++it) {
188 CreateService(*it);
189 }
190}
191
192void WiMax::CreateService(const RpcIdentifier &network) {
193 SLOG(WiMax, 2) << __func__ << "(" << network << ")";
194 if (ContainsKey(services_, network)) {
195 SLOG(WiMax, 2) << "Service already exists.";
196 return;
197 }
198 WiMaxServiceRefPtr service = new WiMaxService(control_interface(),
199 dispatcher(),
200 metrics(),
201 manager(),
202 this);
203 // Creates and passes ownership of the network proxy.
204 if (service->Start(proxy_factory_->CreateWiMaxNetworkProxy(network))) {
205 manager()->RegisterService(service);
206 services_[network] = service;
207 } else {
208 LOG(ERROR) << "Unable to start service: " << network;
209 }
210}
211
212void WiMax::DestroyDeadServices(const RpcIdentifiers &live_networks) {
213 SLOG(WiMax, 2) << __func__ << "(" << live_networks.size() << ")";
214 for (map<string, WiMaxServiceRefPtr>::iterator it = services_.begin();
215 it != services_.end(); ) {
216 if (find(live_networks.begin(), live_networks.end(), it->first) ==
217 live_networks.end()) {
218 WiMaxServiceRefPtr service = it->second;
219 LOG(INFO) << "Destroying service: " << service->friendly_name();
220 if (service == selected_service()) {
221 DestroyIPConfig();
222 SelectService(NULL);
223 }
224 if (pending_service_ == service) {
225 pending_service_ = NULL;
226 }
227 manager()->DeregisterService(service);
228 services_.erase(it++);
229 } else {
230 ++it;
231 }
232 }
233}
234
Ben Chan99c8a4d2012-05-01 08:11:53 -0700235} // namespace shill