blob: 3bb709676dec901e8f05ba39cc34fd3e41001f59 [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 }
138 device_ = manager()->wimax_provider()->SelectCarrier(this);
139 if (!device_) {
140 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 Petkovc63dcf02012-05-24 11:51:43 +0200145 device_->ConnectTo(this, error);
Ben Chan99c8a4d2012-05-01 08:11:53 -0700146}
147
148void WiMaxService::Disconnect(Error *error) {
Darin Petkovc63dcf02012-05-24 11:51:43 +0200149 if (!device_) {
150 Error::PopulateAndLog(
151 error, Error::kNotConnected, "Not connected.");
152 return;
153 }
Ben Chan99c8a4d2012-05-01 08:11:53 -0700154 Service::Disconnect(error);
Darin Petkovc63dcf02012-05-24 11:51:43 +0200155 device_->DisconnectFrom(this, error);
156 device_ = NULL;
Ben Chan99c8a4d2012-05-01 08:11:53 -0700157}
158
Ben Chanc07362b2012-05-12 10:54:11 -0700159string WiMaxService::GetStorageIdentifier() const {
Darin Petkove4b27022012-05-16 13:28:50 +0200160 return storage_id_;
Ben Chanc07362b2012-05-12 10:54:11 -0700161}
162
163string WiMaxService::GetDeviceRpcId(Error *error) {
Darin Petkovc63dcf02012-05-24 11:51:43 +0200164 if (device_) {
165 return device_->GetRpcIdentifier();
166 }
167 error->Populate(Error::kNotSupported);
168 return "/";
Ben Chanc07362b2012-05-12 10:54:11 -0700169}
170
Darin Petkov8021e7f2012-05-21 12:15:00 +0200171bool WiMaxService::Is8021x() const {
172 return true;
173}
174
175void WiMaxService::set_eap(const EapCredentials &eap) {
176 Service::set_eap(eap);
177 UpdateConnectable();
178}
179
180void WiMaxService::UpdateConnectable() {
181 // Don't use Service::Is8021xConnectable because we don't support the full set
182 // of authentication methods.
183 bool is_connectable = false;
Darin Petkovc1e52732012-05-25 15:23:45 +0200184 if (IsStarted()) {
185 if (!eap().identity.empty()) {
186 is_connectable = !eap().password.empty();
187 }
Darin Petkov8021e7f2012-05-21 12:15:00 +0200188 }
189 set_connectable(is_connectable);
190}
191
Darin Petkov1e52a1b2012-05-21 10:35:56 +0200192void WiMaxService::OnSignalStrengthChanged(int strength) {
193 SLOG(WiMax, 2) << __func__ << "(" << strength << ")";
194 SetStrength(strength);
195}
196
Darin Petkovd1cd7972012-05-22 15:26:15 +0200197bool WiMaxService::Save(StoreInterface *storage) {
198 SLOG(WiMax, 2) << __func__;
199 if (!Service::Save(storage)) {
200 return false;
201 }
202 const string id = GetStorageIdentifier();
203 storage->SetString(id, kStorageNetworkId, network_id_);
204 return true;
205}
206
Darin Petkovc1e52732012-05-25 15:23:45 +0200207bool WiMaxService::Unload() {
208 // The base method also disconnects the service.
209 Service::Unload();
210 // Notify the WiMAX provider that this service has been unloaded. If the
211 // provider releases ownership of this service, it needs to be deregistered.
212 return manager()->wimax_provider()->OnServiceUnloaded(this);
213}
214
Darin Petkovd1cd7972012-05-22 15:26:15 +0200215// static
216WiMaxNetworkId WiMaxService::ConvertIdentifierToNetworkId(uint32 identifier) {
217 return base::StringPrintf("%08x", identifier);
218}
219
220void WiMaxService::InitStorageIdentifier() {
221 storage_id_ = CreateStorageIdentifier(network_id_, friendly_name());
222}
223
224// static
225string WiMaxService::CreateStorageIdentifier(const WiMaxNetworkId &id,
226 const string &name) {
227 string storage_id =
228 base::StringPrintf("%s_%s_%s",
229 flimflam::kTypeWimax, name.c_str(), id.c_str());
230 StringToLowerASCII(&storage_id);
231 replace_if(storage_id.begin(), storage_id.end(), &Service::IllegalChar, '_');
232 return storage_id;
233}
234
Ben Chan99c8a4d2012-05-01 08:11:53 -0700235} // namespace shill