blob: 06463f3d815e53f438bf01b67e6494ce5a2706db [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_service.h"
6
Darin Petkov9893d9c2012-05-17 15:27:31 -07007#include <algorithm>
8
Darin Petkovd1cd7972012-05-22 15:26:15 +02009#include <base/string_number_conversions.h>
Darin Petkove4b27022012-05-16 13:28:50 +020010#include <base/string_util.h>
Darin Petkov9893d9c2012-05-17 15:27:31 -070011#include <base/stringprintf.h>
Darin Petkove4b27022012-05-16 13:28:50 +020012#include <chromeos/dbus/service_constants.h>
13
Darin Petkov25665aa2012-05-21 14:08:12 +020014#include "shill/key_value_store.h"
Darin Petkovc63dcf02012-05-24 11:51:43 +020015#include "shill/manager.h"
Darin Petkov9893d9c2012-05-17 15:27:31 -070016#include "shill/scope_logger.h"
Darin Petkovd1cd7972012-05-22 15:26:15 +020017#include "shill/store_interface.h"
Ben Chan99c8a4d2012-05-01 08:11:53 -070018#include "shill/technology.h"
19#include "shill/wimax.h"
20
Darin Petkov9893d9c2012-05-17 15:27:31 -070021using std::replace_if;
Ben Chanc07362b2012-05-12 10:54:11 -070022using std::string;
23
Ben Chan99c8a4d2012-05-01 08:11:53 -070024namespace shill {
25
Darin Petkovd1cd7972012-05-22 15:26:15 +020026const char WiMaxService::kStorageNetworkId[] = "NetworkId";
27const char WiMaxService::kNetworkIdProperty[] = "NetworkId";
28
Ben Chan99c8a4d2012-05-01 08:11:53 -070029WiMaxService::WiMaxService(ControlInterface *control,
30 EventDispatcher *dispatcher,
31 Metrics *metrics,
Darin Petkovc63dcf02012-05-24 11:51:43 +020032 Manager *manager)
Ben Chan99c8a4d2012-05-01 08:11:53 -070033 : Service(control, dispatcher, metrics, manager, Technology::kWiMax),
Darin Petkovc1e52732012-05-25 15:23:45 +020034 need_passphrase_(true),
35 is_default_(false) {
Ben Chan4e5c1312012-05-18 18:45:38 -070036 PropertyStore *store = this->mutable_store();
37 // TODO(benchan): Support networks that require no user credentials or
38 // implicitly defined credentials.
39 store->RegisterBool(flimflam::kPassphraseRequiredProperty, &need_passphrase_);
Darin Petkovd1cd7972012-05-22 15:26:15 +020040 store->RegisterConstString(kNetworkIdProperty, &network_id_);
41
42 IgnoreParameterForConfigure(kNetworkIdProperty);
Darin Petkovc1e52732012-05-25 15:23:45 +020043
44 // Initialize a default storage identifier based on the service's unique
45 // name. The identifier most likely needs to be reinitialized by the caller
46 // when its components have been set.
47 InitStorageIdentifier();
Ben Chan4e5c1312012-05-18 18:45:38 -070048}
Ben Chan99c8a4d2012-05-01 08:11:53 -070049
50WiMaxService::~WiMaxService() {}
51
Darin Petkov25665aa2012-05-21 14:08:12 +020052void WiMaxService::GetConnectParameters(KeyValueStore *parameters) const {
Ben Chan4e5c1312012-05-18 18:45:38 -070053 CHECK(parameters);
Darin Petkov25665aa2012-05-21 14:08:12 +020054 if (!eap().anonymous_identity.empty()) {
55 parameters->SetString(wimax_manager::kEAPAnonymousIdentity,
56 eap().anonymous_identity);
57 }
58 if (!eap().identity.empty()) {
59 parameters->SetString(wimax_manager::kEAPUserIdentity, eap().identity);
60 }
61 if (!eap().password.empty()) {
62 parameters->SetString(wimax_manager::kEAPUserPassword, eap().password);
63 }
Ben Chan4e5c1312012-05-18 18:45:38 -070064}
65
Darin Petkov1e52a1b2012-05-21 10:35:56 +020066RpcIdentifier WiMaxService::GetNetworkObjectPath() const {
Ben Chan4e5c1312012-05-18 18:45:38 -070067 CHECK(proxy_.get());
Darin Petkov1e52a1b2012-05-21 10:35:56 +020068 return proxy_->path();
Ben Chan4e5c1312012-05-18 18:45:38 -070069}
70
Darin Petkovd1cd7972012-05-22 15:26:15 +020071void WiMaxService::Stop() {
Darin Petkovc63dcf02012-05-24 11:51:43 +020072 if (!IsStarted()) {
73 return;
74 }
75 LOG(INFO) << "Stopping WiMAX service: " << GetStorageIdentifier();
Darin Petkovd1cd7972012-05-22 15:26:15 +020076 proxy_.reset();
77 SetStrength(0);
Darin Petkovc63dcf02012-05-24 11:51:43 +020078 if (device_) {
79 device_->OnServiceStopped(this);
80 device_ = NULL;
81 }
Darin Petkovc1e52732012-05-25 15:23:45 +020082 UpdateConnectable();
Darin Petkovd1cd7972012-05-22 15:26:15 +020083}
84
Darin Petkov9893d9c2012-05-17 15:27:31 -070085bool WiMaxService::Start(WiMaxNetworkProxyInterface *proxy) {
86 SLOG(WiMax, 2) << __func__;
Darin Petkov1e52a1b2012-05-21 10:35:56 +020087 CHECK(proxy);
Darin Petkovd1cd7972012-05-22 15:26:15 +020088 scoped_ptr<WiMaxNetworkProxyInterface> local_proxy(proxy);
89 if (IsStarted()) {
90 return true;
91 }
92 if (friendly_name().empty()) {
93 LOG(ERROR) << "Empty service name.";
94 return false;
95 }
Darin Petkov9893d9c2012-05-17 15:27:31 -070096 Error error;
Darin Petkovd1cd7972012-05-22 15:26:15 +020097 network_name_ = proxy->Name(&error);
98 if (error.IsFailure()) {
Darin Petkov9893d9c2012-05-17 15:27:31 -070099 return false;
100 }
Darin Petkovd1cd7972012-05-22 15:26:15 +0200101 uint32 identifier = proxy->Identifier(&error);
102 if (error.IsFailure()) {
Darin Petkov9893d9c2012-05-17 15:27:31 -0700103 return false;
104 }
Darin Petkovd1cd7972012-05-22 15:26:15 +0200105 WiMaxNetworkId id = ConvertIdentifierToNetworkId(identifier);
106 if (id != network_id_) {
107 LOG(ERROR) << "Network identifiers don't match: "
108 << id << " != " << network_id_;
109 return false;
110 }
111 int signal_strength = proxy->SignalStrength(&error);
112 if (error.IsFailure()) {
Ben Chanac6e8362012-05-20 00:39:58 -0700113 return false;
114 }
115 SetStrength(signal_strength);
Darin Petkovd1cd7972012-05-22 15:26:15 +0200116 proxy->set_signal_strength_changed_callback(
Darin Petkov1e52a1b2012-05-21 10:35:56 +0200117 Bind(&WiMaxService::OnSignalStrengthChanged, Unretained(this)));
Darin Petkov8021e7f2012-05-21 12:15:00 +0200118 UpdateConnectable();
Darin Petkovd1cd7972012-05-22 15:26:15 +0200119 proxy_.reset(local_proxy.release());
Darin Petkovc63dcf02012-05-24 11:51:43 +0200120 LOG(INFO) << "WiMAX service started: " << GetStorageIdentifier();
Darin Petkov9893d9c2012-05-17 15:27:31 -0700121 return true;
122}
123
Darin Petkovd1cd7972012-05-22 15:26:15 +0200124bool WiMaxService::IsStarted() const {
125 return proxy_.get();
126}
127
Ben Chan99c8a4d2012-05-01 08:11:53 -0700128bool WiMaxService::TechnologyIs(const Technology::Identifier type) const {
129 return type == Technology::kWiMax;
130}
131
132void WiMaxService::Connect(Error *error) {
Darin Petkovc63dcf02012-05-24 11:51:43 +0200133 if (device_) {
134 Error::PopulateAndLog(
135 error, Error::kAlreadyConnected, "Already connected.");
136 return;
137 }
Darin Petkov8ea0eaf2012-05-29 11:21:33 +0200138 WiMaxRefPtr carrier = manager()->wimax_provider()->SelectCarrier(this);
139 if (!carrier) {
Darin Petkovc63dcf02012-05-24 11:51:43 +0200140 Error::PopulateAndLog(
141 error, Error::kNoCarrier, "No suitable WiMAX device available.");
142 return;
143 }
Ben Chan99c8a4d2012-05-01 08:11:53 -0700144 Service::Connect(error);
Darin Petkov8ea0eaf2012-05-29 11:21:33 +0200145 carrier->ConnectTo(this, error);
146 if (error->IsSuccess()) {
147 // Associate with the carrier device if the connection process has been
148 // initiated successfully.
149 device_ = carrier;
150 }
Ben Chan99c8a4d2012-05-01 08:11:53 -0700151}
152
153void WiMaxService::Disconnect(Error *error) {
Darin Petkovc63dcf02012-05-24 11:51:43 +0200154 if (!device_) {
155 Error::PopulateAndLog(
156 error, Error::kNotConnected, "Not connected.");
157 return;
158 }
Ben Chan99c8a4d2012-05-01 08:11:53 -0700159 Service::Disconnect(error);
Darin Petkovc63dcf02012-05-24 11:51:43 +0200160 device_->DisconnectFrom(this, error);
161 device_ = NULL;
Ben Chan99c8a4d2012-05-01 08:11:53 -0700162}
163
Ben Chanc07362b2012-05-12 10:54:11 -0700164string WiMaxService::GetStorageIdentifier() const {
Darin Petkove4b27022012-05-16 13:28:50 +0200165 return storage_id_;
Ben Chanc07362b2012-05-12 10:54:11 -0700166}
167
168string WiMaxService::GetDeviceRpcId(Error *error) {
Darin Petkovc63dcf02012-05-24 11:51:43 +0200169 if (device_) {
170 return device_->GetRpcIdentifier();
171 }
172 error->Populate(Error::kNotSupported);
173 return "/";
Ben Chanc07362b2012-05-12 10:54:11 -0700174}
175
Darin Petkov8021e7f2012-05-21 12:15:00 +0200176bool WiMaxService::Is8021x() const {
177 return true;
178}
179
180void WiMaxService::set_eap(const EapCredentials &eap) {
181 Service::set_eap(eap);
182 UpdateConnectable();
183}
184
185void WiMaxService::UpdateConnectable() {
186 // Don't use Service::Is8021xConnectable because we don't support the full set
187 // of authentication methods.
188 bool is_connectable = false;
Darin Petkovc1e52732012-05-25 15:23:45 +0200189 if (IsStarted()) {
190 if (!eap().identity.empty()) {
191 is_connectable = !eap().password.empty();
192 }
Darin Petkov8021e7f2012-05-21 12:15:00 +0200193 }
194 set_connectable(is_connectable);
195}
196
Darin Petkov1e52a1b2012-05-21 10:35:56 +0200197void WiMaxService::OnSignalStrengthChanged(int strength) {
198 SLOG(WiMax, 2) << __func__ << "(" << strength << ")";
199 SetStrength(strength);
200}
201
Darin Petkovd1cd7972012-05-22 15:26:15 +0200202bool WiMaxService::Save(StoreInterface *storage) {
203 SLOG(WiMax, 2) << __func__;
204 if (!Service::Save(storage)) {
205 return false;
206 }
207 const string id = GetStorageIdentifier();
208 storage->SetString(id, kStorageNetworkId, network_id_);
209 return true;
210}
211
Darin Petkovc1e52732012-05-25 15:23:45 +0200212bool WiMaxService::Unload() {
213 // The base method also disconnects the service.
214 Service::Unload();
215 // Notify the WiMAX provider that this service has been unloaded. If the
216 // provider releases ownership of this service, it needs to be deregistered.
217 return manager()->wimax_provider()->OnServiceUnloaded(this);
218}
219
Darin Petkov8ea0eaf2012-05-29 11:21:33 +0200220void WiMaxService::SetState(ConnectState state) {
221 Service::SetState(state);
222 if (!IsConnecting() && !IsConnected()) {
223 // Disassociate from any carrier device if it's not connected anymore.
224 device_ = NULL;
225 }
226}
227
Darin Petkovd1cd7972012-05-22 15:26:15 +0200228// static
229WiMaxNetworkId WiMaxService::ConvertIdentifierToNetworkId(uint32 identifier) {
230 return base::StringPrintf("%08x", identifier);
231}
232
233void WiMaxService::InitStorageIdentifier() {
234 storage_id_ = CreateStorageIdentifier(network_id_, friendly_name());
235}
236
237// static
238string WiMaxService::CreateStorageIdentifier(const WiMaxNetworkId &id,
239 const string &name) {
240 string storage_id =
241 base::StringPrintf("%s_%s_%s",
242 flimflam::kTypeWimax, name.c_str(), id.c_str());
243 StringToLowerASCII(&storage_id);
244 replace_if(storage_id.begin(), storage_id.end(), &Service::IllegalChar, '_');
245 return storage_id;
246}
247
Ben Chan99c8a4d2012-05-01 08:11:53 -0700248} // namespace shill