blob: 24e060489c5001345b7613f14e450cff0414be99 [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),
Ben Chan4e5c1312012-05-18 18:45:38 -070034 need_passphrase_(true) {
35 PropertyStore *store = this->mutable_store();
36 // TODO(benchan): Support networks that require no user credentials or
37 // implicitly defined credentials.
38 store->RegisterBool(flimflam::kPassphraseRequiredProperty, &need_passphrase_);
Darin Petkovd1cd7972012-05-22 15:26:15 +020039 store->RegisterConstString(kNetworkIdProperty, &network_id_);
40
41 IgnoreParameterForConfigure(kNetworkIdProperty);
Ben Chan4e5c1312012-05-18 18:45:38 -070042}
Ben Chan99c8a4d2012-05-01 08:11:53 -070043
44WiMaxService::~WiMaxService() {}
45
Darin Petkov25665aa2012-05-21 14:08:12 +020046void WiMaxService::GetConnectParameters(KeyValueStore *parameters) const {
Ben Chan4e5c1312012-05-18 18:45:38 -070047 CHECK(parameters);
Darin Petkov25665aa2012-05-21 14:08:12 +020048 if (!eap().anonymous_identity.empty()) {
49 parameters->SetString(wimax_manager::kEAPAnonymousIdentity,
50 eap().anonymous_identity);
51 }
52 if (!eap().identity.empty()) {
53 parameters->SetString(wimax_manager::kEAPUserIdentity, eap().identity);
54 }
55 if (!eap().password.empty()) {
56 parameters->SetString(wimax_manager::kEAPUserPassword, eap().password);
57 }
Ben Chan4e5c1312012-05-18 18:45:38 -070058}
59
Darin Petkov1e52a1b2012-05-21 10:35:56 +020060RpcIdentifier WiMaxService::GetNetworkObjectPath() const {
Ben Chan4e5c1312012-05-18 18:45:38 -070061 CHECK(proxy_.get());
Darin Petkov1e52a1b2012-05-21 10:35:56 +020062 return proxy_->path();
Ben Chan4e5c1312012-05-18 18:45:38 -070063}
64
Darin Petkovd1cd7972012-05-22 15:26:15 +020065void WiMaxService::Stop() {
Darin Petkovc63dcf02012-05-24 11:51:43 +020066 if (!IsStarted()) {
67 return;
68 }
69 LOG(INFO) << "Stopping WiMAX service: " << GetStorageIdentifier();
Darin Petkovd1cd7972012-05-22 15:26:15 +020070 proxy_.reset();
71 SetStrength(0);
Darin Petkovc63dcf02012-05-24 11:51:43 +020072 if (device_) {
73 device_->OnServiceStopped(this);
74 device_ = NULL;
75 }
Darin Petkovd1cd7972012-05-22 15:26:15 +020076}
77
Darin Petkov9893d9c2012-05-17 15:27:31 -070078bool WiMaxService::Start(WiMaxNetworkProxyInterface *proxy) {
79 SLOG(WiMax, 2) << __func__;
Darin Petkov1e52a1b2012-05-21 10:35:56 +020080 CHECK(proxy);
Darin Petkovd1cd7972012-05-22 15:26:15 +020081 scoped_ptr<WiMaxNetworkProxyInterface> local_proxy(proxy);
82 if (IsStarted()) {
83 return true;
84 }
85 if (friendly_name().empty()) {
86 LOG(ERROR) << "Empty service name.";
87 return false;
88 }
Darin Petkov9893d9c2012-05-17 15:27:31 -070089 Error error;
Darin Petkovd1cd7972012-05-22 15:26:15 +020090 network_name_ = proxy->Name(&error);
91 if (error.IsFailure()) {
Darin Petkov9893d9c2012-05-17 15:27:31 -070092 return false;
93 }
Darin Petkovd1cd7972012-05-22 15:26:15 +020094 uint32 identifier = proxy->Identifier(&error);
95 if (error.IsFailure()) {
Darin Petkov9893d9c2012-05-17 15:27:31 -070096 return false;
97 }
Darin Petkovd1cd7972012-05-22 15:26:15 +020098 WiMaxNetworkId id = ConvertIdentifierToNetworkId(identifier);
99 if (id != network_id_) {
100 LOG(ERROR) << "Network identifiers don't match: "
101 << id << " != " << network_id_;
102 return false;
103 }
104 int signal_strength = proxy->SignalStrength(&error);
105 if (error.IsFailure()) {
Ben Chanac6e8362012-05-20 00:39:58 -0700106 return false;
107 }
108 SetStrength(signal_strength);
Darin Petkovd1cd7972012-05-22 15:26:15 +0200109 proxy->set_signal_strength_changed_callback(
Darin Petkov1e52a1b2012-05-21 10:35:56 +0200110 Bind(&WiMaxService::OnSignalStrengthChanged, Unretained(this)));
Darin Petkov8021e7f2012-05-21 12:15:00 +0200111 UpdateConnectable();
Darin Petkovd1cd7972012-05-22 15:26:15 +0200112 proxy_.reset(local_proxy.release());
Darin Petkovc63dcf02012-05-24 11:51:43 +0200113 LOG(INFO) << "WiMAX service started: " << GetStorageIdentifier();
Darin Petkov9893d9c2012-05-17 15:27:31 -0700114 return true;
115}
116
Darin Petkovd1cd7972012-05-22 15:26:15 +0200117bool WiMaxService::IsStarted() const {
118 return proxy_.get();
119}
120
Ben Chan99c8a4d2012-05-01 08:11:53 -0700121bool WiMaxService::TechnologyIs(const Technology::Identifier type) const {
122 return type == Technology::kWiMax;
123}
124
125void WiMaxService::Connect(Error *error) {
Darin Petkovc63dcf02012-05-24 11:51:43 +0200126 if (device_) {
127 Error::PopulateAndLog(
128 error, Error::kAlreadyConnected, "Already connected.");
129 return;
130 }
131 device_ = manager()->wimax_provider()->SelectCarrier(this);
132 if (!device_) {
133 Error::PopulateAndLog(
134 error, Error::kNoCarrier, "No suitable WiMAX device available.");
135 return;
136 }
Ben Chan99c8a4d2012-05-01 08:11:53 -0700137 Service::Connect(error);
Darin Petkovc63dcf02012-05-24 11:51:43 +0200138 device_->ConnectTo(this, error);
Ben Chan99c8a4d2012-05-01 08:11:53 -0700139}
140
141void WiMaxService::Disconnect(Error *error) {
Darin Petkovc63dcf02012-05-24 11:51:43 +0200142 if (!device_) {
143 Error::PopulateAndLog(
144 error, Error::kNotConnected, "Not connected.");
145 return;
146 }
Ben Chan99c8a4d2012-05-01 08:11:53 -0700147 Service::Disconnect(error);
Darin Petkovc63dcf02012-05-24 11:51:43 +0200148 device_->DisconnectFrom(this, error);
149 device_ = NULL;
Ben Chan99c8a4d2012-05-01 08:11:53 -0700150}
151
Ben Chanc07362b2012-05-12 10:54:11 -0700152string WiMaxService::GetStorageIdentifier() const {
Darin Petkove4b27022012-05-16 13:28:50 +0200153 return storage_id_;
Ben Chanc07362b2012-05-12 10:54:11 -0700154}
155
156string WiMaxService::GetDeviceRpcId(Error *error) {
Darin Petkovc63dcf02012-05-24 11:51:43 +0200157 if (device_) {
158 return device_->GetRpcIdentifier();
159 }
160 error->Populate(Error::kNotSupported);
161 return "/";
Ben Chanc07362b2012-05-12 10:54:11 -0700162}
163
Darin Petkov8021e7f2012-05-21 12:15:00 +0200164bool WiMaxService::Is8021x() const {
165 return true;
166}
167
168void WiMaxService::set_eap(const EapCredentials &eap) {
169 Service::set_eap(eap);
170 UpdateConnectable();
171}
172
173void WiMaxService::UpdateConnectable() {
174 // Don't use Service::Is8021xConnectable because we don't support the full set
175 // of authentication methods.
176 bool is_connectable = false;
177 if (!eap().identity.empty()) {
178 is_connectable = !eap().password.empty();
179 }
180 set_connectable(is_connectable);
181}
182
Darin Petkov1e52a1b2012-05-21 10:35:56 +0200183void WiMaxService::OnSignalStrengthChanged(int strength) {
184 SLOG(WiMax, 2) << __func__ << "(" << strength << ")";
185 SetStrength(strength);
186}
187
Darin Petkovd1cd7972012-05-22 15:26:15 +0200188bool WiMaxService::Save(StoreInterface *storage) {
189 SLOG(WiMax, 2) << __func__;
190 if (!Service::Save(storage)) {
191 return false;
192 }
193 const string id = GetStorageIdentifier();
194 storage->SetString(id, kStorageNetworkId, network_id_);
195 return true;
196}
197
198// static
199WiMaxNetworkId WiMaxService::ConvertIdentifierToNetworkId(uint32 identifier) {
200 return base::StringPrintf("%08x", identifier);
201}
202
203void WiMaxService::InitStorageIdentifier() {
204 storage_id_ = CreateStorageIdentifier(network_id_, friendly_name());
205}
206
207// static
208string WiMaxService::CreateStorageIdentifier(const WiMaxNetworkId &id,
209 const string &name) {
210 string storage_id =
211 base::StringPrintf("%s_%s_%s",
212 flimflam::kTypeWimax, name.c_str(), id.c_str());
213 StringToLowerASCII(&storage_id);
214 replace_if(storage_id.begin(), storage_id.end(), &Service::IllegalChar, '_');
215 return storage_id;
216}
217
Ben Chan99c8a4d2012-05-01 08:11:53 -0700218} // namespace shill