blob: a9eaff941d4068559aa7f3a9078fae03418309a9 [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
Ben Chana0ddf462014-02-06 11:32:42 -08009#include <base/strings/string_number_conversions.h>
10#include <base/strings/string_util.h>
11#include <base/strings/stringprintf.h>
Darin Petkove4b27022012-05-16 13:28:50 +020012#include <chromeos/dbus/service_constants.h>
13
mukesh agrawalcbfb34e2013-04-17 19:33:25 -070014#include "shill/dbus_adaptor.h"
Paul Stewartc43cbbe2013-04-11 06:29:30 -070015#include "shill/eap_credentials.h"
Darin Petkov25665aa2012-05-21 14:08:12 +020016#include "shill/key_value_store.h"
Christopher Wileyb691efd2012-08-09 13:51:51 -070017#include "shill/logging.h"
Darin Petkovc63dcf02012-05-24 11:51:43 +020018#include "shill/manager.h"
Darin Petkovd1cd7972012-05-22 15:26:15 +020019#include "shill/store_interface.h"
Ben Chan99c8a4d2012-05-01 08:11:53 -070020#include "shill/technology.h"
21#include "shill/wimax.h"
22
Darin Petkov9893d9c2012-05-17 15:27:31 -070023using std::replace_if;
Ben Chanc07362b2012-05-12 10:54:11 -070024using std::string;
25
Ben Chan99c8a4d2012-05-01 08:11:53 -070026namespace shill {
27
Darin Petkovd1cd7972012-05-22 15:26:15 +020028const char WiMaxService::kStorageNetworkId[] = "NetworkId";
29const char WiMaxService::kNetworkIdProperty[] = "NetworkId";
Darin Petkov6b9b2e12012-07-10 15:51:42 +020030
Ben Chan99c8a4d2012-05-01 08:11:53 -070031WiMaxService::WiMaxService(ControlInterface *control,
32 EventDispatcher *dispatcher,
33 Metrics *metrics,
Darin Petkovc63dcf02012-05-24 11:51:43 +020034 Manager *manager)
Ben Chan99c8a4d2012-05-01 08:11:53 -070035 : Service(control, dispatcher, metrics, manager, Technology::kWiMax),
Darin Petkovc1e52732012-05-25 15:23:45 +020036 need_passphrase_(true),
37 is_default_(false) {
Ben Chan4e5c1312012-05-18 18:45:38 -070038 PropertyStore *store = this->mutable_store();
39 // TODO(benchan): Support networks that require no user credentials or
40 // implicitly defined credentials.
Ben Chan4276cca2013-09-20 10:07:04 -070041 store->RegisterBool(kPassphraseRequiredProperty, &need_passphrase_);
Darin Petkovd1cd7972012-05-22 15:26:15 +020042 store->RegisterConstString(kNetworkIdProperty, &network_id_);
43
Paul Stewartc43cbbe2013-04-11 06:29:30 -070044 SetEapCredentials(new EapCredentials());
45
Darin Petkovd1cd7972012-05-22 15:26:15 +020046 IgnoreParameterForConfigure(kNetworkIdProperty);
Darin Petkovc1e52732012-05-25 15:23:45 +020047
48 // Initialize a default storage identifier based on the service's unique
49 // name. The identifier most likely needs to be reinitialized by the caller
50 // when its components have been set.
51 InitStorageIdentifier();
Paul Stewart45170bc2014-06-02 15:49:34 -070052
53 // Now that |this| is a fully constructed WiMaxService, synchronize observers
54 // with our current state, and emit the appropriate change notifications.
55 // (Initial observer state may have been set in our base class.)
56 NotifyPropertyChanges();
Ben Chan4e5c1312012-05-18 18:45:38 -070057}
Ben Chan99c8a4d2012-05-01 08:11:53 -070058
59WiMaxService::~WiMaxService() {}
60
Darin Petkov25665aa2012-05-21 14:08:12 +020061void WiMaxService::GetConnectParameters(KeyValueStore *parameters) const {
Ben Chan4e5c1312012-05-18 18:45:38 -070062 CHECK(parameters);
Paul Stewartc43cbbe2013-04-11 06:29:30 -070063 eap()->PopulateWiMaxProperties(parameters);
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);
mukesh agrawalcbfb34e2013-04-17 19:33:25 -070080 SetDevice(NULL);
Darin Petkovc63dcf02012-05-24 11:51:43 +020081 }
Darin Petkovc1e52732012-05-25 15:23:45 +020082 UpdateConnectable();
Paul Stewart45170bc2014-06-02 15:49:34 -070083 NotifyPropertyChanges();
Darin Petkovd1cd7972012-05-22 15:26:15 +020084}
85
Darin Petkov9893d9c2012-05-17 15:27:31 -070086bool WiMaxService::Start(WiMaxNetworkProxyInterface *proxy) {
87 SLOG(WiMax, 2) << __func__;
Darin Petkov1e52a1b2012-05-21 10:35:56 +020088 CHECK(proxy);
Darin Petkovd1cd7972012-05-22 15:26:15 +020089 scoped_ptr<WiMaxNetworkProxyInterface> local_proxy(proxy);
90 if (IsStarted()) {
91 return true;
92 }
93 if (friendly_name().empty()) {
94 LOG(ERROR) << "Empty service name.";
95 return false;
96 }
Darin Petkov9893d9c2012-05-17 15:27:31 -070097 Error error;
Darin Petkovd1cd7972012-05-22 15:26:15 +020098 network_name_ = proxy->Name(&error);
99 if (error.IsFailure()) {
Darin Petkov9893d9c2012-05-17 15:27:31 -0700100 return false;
101 }
Darin Petkovd1cd7972012-05-22 15:26:15 +0200102 uint32 identifier = proxy->Identifier(&error);
103 if (error.IsFailure()) {
Darin Petkov9893d9c2012-05-17 15:27:31 -0700104 return false;
105 }
Darin Petkovd1cd7972012-05-22 15:26:15 +0200106 WiMaxNetworkId id = ConvertIdentifierToNetworkId(identifier);
107 if (id != network_id_) {
108 LOG(ERROR) << "Network identifiers don't match: "
109 << id << " != " << network_id_;
110 return false;
111 }
112 int signal_strength = proxy->SignalStrength(&error);
113 if (error.IsFailure()) {
Ben Chanac6e8362012-05-20 00:39:58 -0700114 return false;
115 }
116 SetStrength(signal_strength);
Darin Petkovd1cd7972012-05-22 15:26:15 +0200117 proxy->set_signal_strength_changed_callback(
Darin Petkov1e52a1b2012-05-21 10:35:56 +0200118 Bind(&WiMaxService::OnSignalStrengthChanged, Unretained(this)));
Darin Petkovd1cd7972012-05-22 15:26:15 +0200119 proxy_.reset(local_proxy.release());
Darin Petkova3f9f772012-05-31 12:11:28 +0200120 UpdateConnectable();
Paul Stewart45170bc2014-06-02 15:49:34 -0700121 NotifyPropertyChanges();
Darin Petkovc63dcf02012-05-24 11:51:43 +0200122 LOG(INFO) << "WiMAX service started: " << GetStorageIdentifier();
Darin Petkov9893d9c2012-05-17 15:27:31 -0700123 return true;
124}
125
Darin Petkovd1cd7972012-05-22 15:26:15 +0200126bool WiMaxService::IsStarted() const {
127 return proxy_.get();
128}
129
mukesh agrawaldc7b8442012-09-27 13:48:14 -0700130void WiMaxService::Connect(Error *error, const char *reason) {
Ben Chane494e312013-08-23 12:56:05 -0700131 SLOG(WiMax, 2) << __func__;
Darin Petkovc63dcf02012-05-24 11:51:43 +0200132 if (device_) {
Ben Chanb5310a12012-06-15 13:53:29 -0700133 // TODO(benchan): Populate error again after changing the way that
134 // Chrome handles Error::kAlreadyConnected situation.
135 LOG(WARNING) << "Service " << GetStorageIdentifier()
136 << " is already being connected or already connected.";
Darin Petkovc63dcf02012-05-24 11:51:43 +0200137 return;
138 }
Darin Petkova3f9f772012-05-31 12:11:28 +0200139 if (!connectable()) {
140 LOG(ERROR) << "Can't connect. Service " << GetStorageIdentifier()
141 << " is not connectable.";
142 Error::PopulateAndLog(error, Error::kOperationFailed,
143 Error::GetDefaultMessage(Error::kOperationFailed));
144 return;
145 }
Darin Petkov8ea0eaf2012-05-29 11:21:33 +0200146 WiMaxRefPtr carrier = manager()->wimax_provider()->SelectCarrier(this);
147 if (!carrier) {
Darin Petkovc63dcf02012-05-24 11:51:43 +0200148 Error::PopulateAndLog(
149 error, Error::kNoCarrier, "No suitable WiMAX device available.");
150 return;
151 }
mukesh agrawaldc7b8442012-09-27 13:48:14 -0700152 Service::Connect(error, reason);
Darin Petkov8ea0eaf2012-05-29 11:21:33 +0200153 carrier->ConnectTo(this, error);
154 if (error->IsSuccess()) {
155 // Associate with the carrier device if the connection process has been
156 // initiated successfully.
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700157 SetDevice(carrier);
Darin Petkov8ea0eaf2012-05-29 11:21:33 +0200158 }
Ben Chan99c8a4d2012-05-01 08:11:53 -0700159}
160
Samuel Tan0d061192014-07-07 15:45:15 -0700161void WiMaxService::Disconnect(Error *error, const char *reason) {
Ben Chane494e312013-08-23 12:56:05 -0700162 SLOG(WiMax, 2) << __func__;
Darin Petkovc63dcf02012-05-24 11:51:43 +0200163 if (!device_) {
164 Error::PopulateAndLog(
165 error, Error::kNotConnected, "Not connected.");
166 return;
167 }
Samuel Tan0d061192014-07-07 15:45:15 -0700168 Service::Disconnect(error, reason);
Darin Petkovc63dcf02012-05-24 11:51:43 +0200169 device_->DisconnectFrom(this, error);
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700170 SetDevice(NULL);
Ben Chan99c8a4d2012-05-01 08:11:53 -0700171}
172
Ben Chanc07362b2012-05-12 10:54:11 -0700173string WiMaxService::GetStorageIdentifier() const {
Darin Petkove4b27022012-05-16 13:28:50 +0200174 return storage_id_;
Ben Chanc07362b2012-05-12 10:54:11 -0700175}
176
Paul Stewart1cf7eb82013-12-03 19:34:36 -0800177string WiMaxService::GetDeviceRpcId(Error *error) const {
mukesh agrawald4dc0832013-03-25 14:38:26 -0700178 if (!device_) {
179 error->Populate(Error::kNotFound, "Not associated with a device");
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700180 return DBusAdaptor::kNullPath;
Darin Petkovc63dcf02012-05-24 11:51:43 +0200181 }
mukesh agrawald4dc0832013-03-25 14:38:26 -0700182 return device_->GetRpcIdentifier();
Ben Chanc07362b2012-05-12 10:54:11 -0700183}
184
Darin Petkov6b9b2e12012-07-10 15:51:42 +0200185bool WiMaxService::IsAutoConnectable(const char **reason) const {
186 if (!Service::IsAutoConnectable(reason)) {
187 return false;
188 }
189 WiMaxRefPtr device = manager()->wimax_provider()->SelectCarrier(this);
190 DCHECK(device);
191 if (!device->IsIdle()) {
192 *reason = kAutoConnBusy;
193 return false;
194 }
195 return true;
196}
197
Darin Petkov8021e7f2012-05-21 12:15:00 +0200198bool WiMaxService::Is8021x() const {
199 return true;
200}
201
Ben Chanf4647d42013-05-02 22:01:01 -0700202bool WiMaxService::IsVisible() const {
203 // WiMAX services should be displayed only if they are in range (i.e.
204 // a corresponding network is exposed by WiMAX manager).
205 return IsStarted();
206}
207
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700208void WiMaxService::OnEapCredentialsChanged() {
209 need_passphrase_ = !eap()->IsConnectableUsingPassphrase();
Rebecca Silbersteinb6df8b12014-07-10 16:07:08 -0700210 SetHasEverConnected(false);
Darin Petkov8021e7f2012-05-21 12:15:00 +0200211 UpdateConnectable();
212}
213
214void WiMaxService::UpdateConnectable() {
Ben Chane494e312013-08-23 12:56:05 -0700215 SLOG(WiMax, 2) << __func__ << "(started: " << IsStarted()
216 << ", need passphrase: " << need_passphrase_ << ")";
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700217 SetConnectableFull(IsStarted() && !need_passphrase_);
Darin Petkov8021e7f2012-05-21 12:15:00 +0200218}
219
Darin Petkov1e52a1b2012-05-21 10:35:56 +0200220void WiMaxService::OnSignalStrengthChanged(int strength) {
221 SLOG(WiMax, 2) << __func__ << "(" << strength << ")";
222 SetStrength(strength);
223}
224
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700225void WiMaxService::SetDevice(WiMaxRefPtr new_device) {
226 if (device_ == new_device)
227 return;
228 if (new_device) {
Ben Chan4276cca2013-09-20 10:07:04 -0700229 adaptor()->EmitRpcIdentifierChanged(kDeviceProperty,
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700230 new_device->GetRpcIdentifier());
231 } else {
Ben Chan4276cca2013-09-20 10:07:04 -0700232 adaptor()->EmitRpcIdentifierChanged(kDeviceProperty,
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700233 DBusAdaptor::kNullPath);
234 }
235 device_ = new_device;
236}
237
Darin Petkovd1cd7972012-05-22 15:26:15 +0200238bool WiMaxService::Save(StoreInterface *storage) {
239 SLOG(WiMax, 2) << __func__;
240 if (!Service::Save(storage)) {
241 return false;
242 }
243 const string id = GetStorageIdentifier();
244 storage->SetString(id, kStorageNetworkId, network_id_);
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700245
Darin Petkovd1cd7972012-05-22 15:26:15 +0200246 return true;
247}
248
Darin Petkovc1e52732012-05-25 15:23:45 +0200249bool WiMaxService::Unload() {
Ben Chane494e312013-08-23 12:56:05 -0700250 SLOG(WiMax, 2) << __func__;
Darin Petkovc1e52732012-05-25 15:23:45 +0200251 // The base method also disconnects the service.
252 Service::Unload();
Darin Petkova3f9f772012-05-31 12:11:28 +0200253 ClearPassphrase();
Darin Petkovc1e52732012-05-25 15:23:45 +0200254 // Notify the WiMAX provider that this service has been unloaded. If the
255 // provider releases ownership of this service, it needs to be deregistered.
256 return manager()->wimax_provider()->OnServiceUnloaded(this);
257}
258
Darin Petkov8ea0eaf2012-05-29 11:21:33 +0200259void WiMaxService::SetState(ConnectState state) {
260 Service::SetState(state);
261 if (!IsConnecting() && !IsConnected()) {
262 // Disassociate from any carrier device if it's not connected anymore.
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700263 SetDevice(NULL);
Darin Petkov8ea0eaf2012-05-29 11:21:33 +0200264 }
265}
266
Darin Petkovd1cd7972012-05-22 15:26:15 +0200267// static
268WiMaxNetworkId WiMaxService::ConvertIdentifierToNetworkId(uint32 identifier) {
269 return base::StringPrintf("%08x", identifier);
270}
271
272void WiMaxService::InitStorageIdentifier() {
273 storage_id_ = CreateStorageIdentifier(network_id_, friendly_name());
274}
275
276// static
277string WiMaxService::CreateStorageIdentifier(const WiMaxNetworkId &id,
278 const string &name) {
279 string storage_id =
280 base::StringPrintf("%s_%s_%s",
Ben Chan4276cca2013-09-20 10:07:04 -0700281 kTypeWimax, name.c_str(), id.c_str());
Darin Petkovd1cd7972012-05-22 15:26:15 +0200282 StringToLowerASCII(&storage_id);
283 replace_if(storage_id.begin(), storage_id.end(), &Service::IllegalChar, '_');
284 return storage_id;
285}
286
Darin Petkova3f9f772012-05-31 12:11:28 +0200287void WiMaxService::ClearPassphrase() {
Ben Chane494e312013-08-23 12:56:05 -0700288 SLOG(WiMax, 2) << __func__;
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700289 mutable_eap()->set_password("");
290 OnEapCredentialsChanged();
Darin Petkova3f9f772012-05-31 12:11:28 +0200291}
292
Ben Chan99c8a4d2012-05-01 08:11:53 -0700293} // namespace shill