blob: 81339ab50e97fe90ddccd9e22a56afc2061c81d8 [file] [log] [blame]
Arman Uguray2717a102013-01-29 23:36:06 -08001// Copyright (c) 2013 The Chromium OS Authors. All rights reserved.
Paul Stewart75897df2011-04-27 09:05:53 -07002// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Chris Masoneb2e326b2011-07-12 13:28:51 -07005#include "shill/service.h"
6
Paul Stewart75897df2011-04-27 09:05:53 -07007#include <time.h>
Paul Stewart75897df2011-04-27 09:05:53 -07008#include <stdio.h>
Chris Masoneee929b72011-05-10 10:02:18 -07009
Chris Masone8fe2c7e2011-06-09 15:51:19 -070010#include <map>
Paul Stewart75897df2011-04-27 09:05:53 -070011#include <string>
Chris Masone8fe2c7e2011-06-09 15:51:19 -070012#include <vector>
Paul Stewart75897df2011-04-27 09:05:53 -070013
Chris Masone3bd3c8c2011-06-13 08:20:26 -070014#include <base/memory/scoped_ptr.h>
mukesh agrawal51a7e932011-07-27 16:18:26 -070015#include <base/string_number_conversions.h>
Paul Stewart2bf424f2012-04-11 18:59:39 -070016#include <base/stringprintf.h>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070017#include <chromeos/dbus/service_constants.h>
Chris Masoneee929b72011-05-10 10:02:18 -070018
Paul Stewartbe5f5b32011-12-07 17:11:11 -080019#include "shill/connection.h"
Paul Stewart75897df2011-04-27 09:05:53 -070020#include "shill/control_interface.h"
Darin Petkov385b9bc2012-12-03 15:25:05 +010021#include "shill/diagnostics_reporter.h"
Paul Stewartc43cbbe2013-04-11 06:29:30 -070022#include "shill/eap_credentials.h"
Chris Masone8fe2c7e2011-06-09 15:51:19 -070023#include "shill/error.h"
Paul Stewartbe5f5b32011-12-07 17:11:11 -080024#include "shill/http_proxy.h"
Christopher Wileyb691efd2012-08-09 13:51:51 -070025#include "shill/logging.h"
Chris Masone6791a432011-07-12 13:23:19 -070026#include "shill/manager.h"
Thieu Le48e6d6d2011-12-06 00:40:27 +000027#include "shill/metrics.h"
Chris Masone7aa5f902011-07-11 11:13:35 -070028#include "shill/profile.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070029#include "shill/property_accessor.h"
Chris Masone7aa5f902011-07-11 11:13:35 -070030#include "shill/refptr_types.h"
Chris Masoned7732e42011-05-20 11:08:56 -070031#include "shill/service_dbus_adaptor.h"
Darin Petkov5eb05422012-05-11 15:45:25 +020032#include "shill/sockets.h"
Darin Petkovba40dd32011-07-11 20:06:39 -070033#include "shill/store_interface.h"
Paul Stewart75897df2011-04-27 09:05:53 -070034
Christopher Wiley0801d192012-09-24 11:57:15 -070035using base::Bind;
Darin Petkov385b9bc2012-12-03 15:25:05 +010036using std::deque;
Chris Masone8fe2c7e2011-06-09 15:51:19 -070037using std::map;
Paul Stewart75897df2011-04-27 09:05:53 -070038using std::string;
Chris Masone8fe2c7e2011-06-09 15:51:19 -070039using std::vector;
Paul Stewart75897df2011-04-27 09:05:53 -070040
41namespace shill {
Darin Petkovba40dd32011-07-11 20:06:39 -070042
mukesh agrawal03c15ce2012-11-29 17:36:21 -080043const char Service::kAutoConnBusy[] = "busy";
mukesh agrawalbf14e942012-03-02 14:36:34 -080044const char Service::kAutoConnConnected[] = "connected";
45const char Service::kAutoConnConnecting[] = "connecting";
46const char Service::kAutoConnExplicitDisconnect[] = "explicitly disconnected";
47const char Service::kAutoConnNotConnectable[] = "not connectable";
Darin Petkov4cbff5b2013-01-29 16:29:05 +010048const char Service::kAutoConnOffline[] = "offline";
Christopher Wiley0801d192012-09-24 11:57:15 -070049const char Service::kAutoConnThrottled[] = "throttled";
mukesh agrawalbf14e942012-03-02 14:36:34 -080050
Paul Stewartbc6e7392012-05-24 07:07:48 -070051const size_t Service::kEAPMaxCertificationElements = 10;
52
Darin Petkovba40dd32011-07-11 20:06:39 -070053const char Service::kCheckPortalAuto[] = "auto";
54const char Service::kCheckPortalFalse[] = "false";
55const char Service::kCheckPortalTrue[] = "true";
56
Darin Petkovaba89322013-03-11 14:48:22 +010057const char Service::kErrorDetailsNone[] = "";
58
Paul Stewartac4ac002011-08-26 12:04:26 -070059const int Service::kPriorityNone = 0;
60
Darin Petkov2f903b32012-04-18 12:56:43 +020061const char Service::kServiceSortAutoConnect[] = "AutoConnect";
62const char Service::kServiceSortConnectable[] = "Connectable";
Paul Stewartdf3c0a82012-11-09 15:54:33 -080063const char Service::kServiceSortDependency[] = "Dependency";
Darin Petkov2f903b32012-04-18 12:56:43 +020064const char Service::kServiceSortFavorite[] = "Favorite";
mukesh agrawalddc378f2012-02-17 18:26:20 -080065const char Service::kServiceSortIsConnected[] = "IsConnected";
66const char Service::kServiceSortIsConnecting[] = "IsConnecting";
67const char Service::kServiceSortIsFailed[] = "IsFailed";
Paul Stewarta121c442012-06-09 14:12:58 -070068const char Service::kServiceSortIsPortalled[] = "IsPortal";
Darin Petkov2f903b32012-04-18 12:56:43 +020069const char Service::kServiceSortPriority[] = "Priority";
mukesh agrawalddc378f2012-02-17 18:26:20 -080070const char Service::kServiceSortSecurityEtc[] = "SecurityEtc";
Darin Petkov2f903b32012-04-18 12:56:43 +020071const char Service::kServiceSortTechnology[] = "Technology";
mukesh agrawalddc378f2012-02-17 18:26:20 -080072const char Service::kServiceSortUniqueName[] = "UniqueName";
73
Darin Petkovba40dd32011-07-11 20:06:39 -070074const char Service::kStorageAutoConnect[] = "AutoConnect";
75const char Service::kStorageCheckPortal[] = "CheckPortal";
Paul Stewart0756db92012-01-27 08:34:47 -080076const char Service::kStorageError[] = "Error";
Darin Petkovba40dd32011-07-11 20:06:39 -070077const char Service::kStorageFavorite[] = "Favorite";
Paul Stewart0756db92012-01-27 08:34:47 -080078const char Service::kStorageGUID[] = "GUID";
mukesh agrawalcf24a242012-05-21 16:46:11 -070079const char Service::kStorageHasEverConnected[] = "HasEverConnected";
Darin Petkovba40dd32011-07-11 20:06:39 -070080const char Service::kStorageName[] = "Name";
81const char Service::kStoragePriority[] = "Priority";
82const char Service::kStorageProxyConfig[] = "ProxyConfig";
83const char Service::kStorageSaveCredentials[] = "SaveCredentials";
Paul Stewart2706aaf2011-12-14 16:44:04 -080084const char Service::kStorageType[] = "Type";
Paul Stewart987e71e2011-12-05 09:45:06 -080085const char Service::kStorageUIData[] = "UIData";
Darin Petkovba40dd32011-07-11 20:06:39 -070086
mukesh agrawal8f3f7752012-02-17 19:42:09 -080087const uint8 Service::kStrengthMax = 100;
88const uint8 Service::kStrengthMin = 0;
89
Christopher Wiley0801d192012-09-24 11:57:15 -070090const uint64 Service::kMaxAutoConnectCooldownTimeMilliseconds = 30 * 60 * 1000;
91const uint64 Service::kMinAutoConnectCooldownTimeMilliseconds = 1000;
92const uint64 Service::kAutoConnectCooldownBackoffFactor = 2;
93
Darin Petkov385b9bc2012-12-03 15:25:05 +010094const int Service::kDisconnectsMonitorSeconds = 5 * 60;
95const int Service::kMisconnectsMonitorSeconds = 5 * 60;
96const int Service::kReportDisconnectsThreshold = 2;
97const int Service::kReportMisconnectsThreshold = 3;
98const int Service::kMaxDisconnectEventHistory = 20;
99
mukesh agrawal51a7e932011-07-27 16:18:26 -0700100// static
101unsigned int Service::serial_number_ = 0;
102
Paul Stewart75897df2011-04-27 09:05:53 -0700103Service::Service(ControlInterface *control_interface,
mukesh agrawalb54601c2011-06-07 17:39:22 -0700104 EventDispatcher *dispatcher,
Thieu Le3426c8f2012-01-11 17:35:11 -0800105 Metrics *metrics,
mukesh agrawal7a4e4002011-09-06 11:26:05 -0700106 Manager *manager,
Gaurav Shah435de2c2011-11-17 19:01:07 -0800107 Technology::Identifier technology)
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700108 : weak_ptr_factory_(this),
109 state_(kStateIdle),
Darin Petkovc8d91e52013-01-21 11:43:47 +0100110 previous_state_(kStateIdle),
Paul Stewart03dba0b2011-08-22 16:32:45 -0700111 failure_(kFailureUnknown),
112 auto_connect_(false),
Darin Petkovba40dd32011-07-11 20:06:39 -0700113 check_portal_(kCheckPortalAuto),
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700114 connectable_(false),
Paul Stewartf2d60912012-07-15 08:37:30 -0700115 error_(ConnectFailureToString(failure_)),
Darin Petkovaba89322013-03-11 14:48:22 +0100116 error_details_(kErrorDetailsNone),
mukesh agrawaladb68482012-01-17 16:31:51 -0800117 explicitly_disconnected_(false),
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700118 favorite_(false),
Darin Petkovba40dd32011-07-11 20:06:39 -0700119 priority_(kPriorityNone),
mukesh agrawal43970a22013-02-15 16:00:07 -0800120 crypto_algorithm_(kCryptoNone),
121 key_rotation_(false),
122 endpoint_auth_(false),
Paul Stewart22aa71b2011-09-16 12:15:11 -0700123 strength_(0),
Darin Petkovba40dd32011-07-11 20:06:39 -0700124 save_credentials_(true),
Gaurav Shah435de2c2011-11-17 19:01:07 -0800125 technology_(technology),
mukesh agrawal568b5c62012-02-28 14:44:47 -0800126 failed_time_(0),
mukesh agrawalcf24a242012-05-21 16:46:11 -0700127 has_ever_connected_(false),
Christopher Wiley0801d192012-09-24 11:57:15 -0700128 auto_connect_cooldown_milliseconds_(0),
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700129 store_(PropertyStore::PropertyChangeCallback(
130 base::Bind(&Service::OnPropertyChanged,
131 weak_ptr_factory_.GetWeakPtr()))),
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700132 dispatcher_(dispatcher),
mukesh agrawald835b202011-10-07 15:26:47 -0700133 unique_name_(base::UintToString(serial_number_++)),
134 friendly_name_(unique_name_),
Chris Masone6791a432011-07-12 13:23:19 -0700135 adaptor_(control_interface->CreateServiceAdaptor(this)),
Thieu Le3426c8f2012-01-11 17:35:11 -0800136 metrics_(metrics),
Darin Petkov5eb05422012-05-11 15:45:25 +0200137 manager_(manager),
Christopher Wiley0801d192012-09-24 11:57:15 -0700138 sockets_(new Sockets()),
Darin Petkov385b9bc2012-12-03 15:25:05 +0100139 time_(Time::GetInstance()),
140 diagnostics_reporter_(DiagnosticsReporter::GetInstance()) {
Thieu Le284fe792012-01-31 17:53:19 -0800141 HelpRegisterDerivedBool(flimflam::kAutoConnectProperty,
142 &Service::GetAutoConnect,
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700143 &Service::SetAutoConnectFull);
Chris Masone4d42df82011-07-02 17:09:39 -0700144
145 // flimflam::kActivationStateProperty: Registered in CellularService
146 // flimflam::kCellularApnProperty: Registered in CellularService
147 // flimflam::kCellularLastGoodApnProperty: Registered in CellularService
148 // flimflam::kNetworkTechnologyProperty: Registered in CellularService
Darin Petkov3335b372011-08-22 11:05:32 -0700149 // flimflam::kOperatorNameProperty: DEPRECATED
150 // flimflam::kOperatorCodeProperty: DEPRECATED
Chris Masone4d42df82011-07-02 17:09:39 -0700151 // flimflam::kRoamingStateProperty: Registered in CellularService
Darin Petkov3335b372011-08-22 11:05:32 -0700152 // flimflam::kServingOperatorProperty: Registered in CellularService
Chris Masone4d42df82011-07-02 17:09:39 -0700153 // flimflam::kPaymentURLProperty: Registered in CellularService
154
Paul Stewartd215af62012-04-24 23:25:50 -0700155 HelpRegisterDerivedString(flimflam::kCheckPortalProperty,
156 &Service::GetCheckPortal,
157 &Service::SetCheckPortal);
Chris Masone27c4aa52011-07-02 13:10:14 -0700158 store_.RegisterConstBool(flimflam::kConnectableProperty, &connectable_);
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700159 HelpRegisterConstDerivedRpcIdentifier(flimflam::kDeviceProperty,
160 &Service::GetDeviceRpcId);
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700161 store_.RegisterConstStrings(kEapRemoteCertificationProperty,
162 &remote_certification_);
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700163 HelpRegisterDerivedString(flimflam::kGuidProperty,
164 &Service::GetGuid,
165 &Service::SetGuid);
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700166
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400167 // TODO(ers): in flimflam clearing Error has the side-effect of
168 // setting the service state to IDLE. Is this important? I could
169 // see an autotest depending on it.
Chris Masone27c4aa52011-07-02 13:10:14 -0700170 store_.RegisterConstString(flimflam::kErrorProperty, &error_);
Darin Petkovaba89322013-03-11 14:48:22 +0100171 store_.RegisterConstString(shill::kErrorDetailsProperty, &error_details_);
Chris Masone27c4aa52011-07-02 13:10:14 -0700172 store_.RegisterConstBool(flimflam::kFavoriteProperty, &favorite_);
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700173 HelpRegisterConstDerivedUint16(shill::kHTTPProxyPortProperty,
174 &Service::GetHTTPProxyPort);
175 HelpRegisterConstDerivedRpcIdentifier(shill::kIPConfigProperty,
176 &Service::GetIPConfigRpcIdentifier);
Chris Masone27c4aa52011-07-02 13:10:14 -0700177 HelpRegisterDerivedBool(flimflam::kIsActiveProperty,
Chris Masoneb2e326b2011-07-12 13:28:51 -0700178 &Service::IsActive,
179 NULL);
Chris Masone4d42df82011-07-02 17:09:39 -0700180 // flimflam::kModeProperty: Registered in WiFiService
Paul Stewart0c438332012-04-11 07:55:27 -0700181
Paul Stewart0c438332012-04-11 07:55:27 -0700182 HelpRegisterDerivedString(flimflam::kNameProperty,
183 &Service::GetNameProperty,
Darin Petkov9c6e9812013-03-26 13:49:07 +0100184 &Service::SetNameProperty);
Chris Masone4d42df82011-07-02 17:09:39 -0700185 // flimflam::kPassphraseProperty: Registered in WiFiService
186 // flimflam::kPassphraseRequiredProperty: Registered in WiFiService
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700187 HelpRegisterDerivedInt32(flimflam::kPriorityProperty,
188 &Service::GetPriority,
189 &Service::SetPriority);
Chris Masone27c4aa52011-07-02 13:10:14 -0700190 HelpRegisterDerivedString(flimflam::kProfileProperty,
191 &Service::GetProfileRpcId,
Paul Stewart1b1a7f22012-01-06 16:24:06 -0800192 &Service::SetProfileRpcId);
Philipp Neubeck79173602012-11-13 21:10:09 +0100193 HelpRegisterDerivedString(flimflam::kProxyConfigProperty,
194 &Service::GetProxyConfig,
195 &Service::SetProxyConfig);
Chris Masoneb2e326b2011-07-12 13:28:51 -0700196 store_.RegisterBool(flimflam::kSaveCredentialsProperty, &save_credentials_);
Gaurav Shah435de2c2011-11-17 19:01:07 -0800197 HelpRegisterDerivedString(flimflam::kTypeProperty,
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200198 &Service::CalculateTechnology,
Gaurav Shah435de2c2011-11-17 19:01:07 -0800199 NULL);
Chris Masone4d42df82011-07-02 17:09:39 -0700200 // flimflam::kSecurityProperty: Registered in WiFiService
Chris Masone27c4aa52011-07-02 13:10:14 -0700201 HelpRegisterDerivedString(flimflam::kStateProperty,
202 &Service::CalculateState,
203 NULL);
Darin Petkovd78ee7e2012-01-12 11:21:10 +0100204 store_.RegisterConstUint8(flimflam::kSignalStrengthProperty, &strength_);
Paul Stewart987e71e2011-12-05 09:45:06 -0800205 store_.RegisterString(flimflam::kUIDataProperty, &ui_data_);
Darin Petkov0c65bdd2012-12-05 13:42:41 +0100206 HelpRegisterConstDerivedStrings(shill::kDiagnosticsDisconnectsProperty,
207 &Service::GetDisconnectsProperty);
208 HelpRegisterConstDerivedStrings(shill::kDiagnosticsMisconnectsProperty,
209 &Service::GetMisconnectsProperty);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000210 metrics_->RegisterService(this);
211
Paul Stewart1062d9d2012-04-27 10:42:27 -0700212 static_ip_parameters_.PlumbPropertyStore(&store_);
213
Paul Stewartcb59fed2012-03-21 21:14:46 -0700214 IgnoreParameterForConfigure(flimflam::kTypeProperty);
Paul Stewart7f61e522012-03-22 11:13:45 -0700215 IgnoreParameterForConfigure(flimflam::kProfileProperty);
Paul Stewartcb59fed2012-03-21 21:14:46 -0700216
Darin Petkov9c366992013-01-10 12:32:21 +0100217 LOG(INFO) << Technology::NameFromIdentifier(technology) << " service "
218 << unique_name_ << " constructed.";
Paul Stewart75897df2011-04-27 09:05:53 -0700219}
220
Thieu Le48e6d6d2011-12-06 00:40:27 +0000221Service::~Service() {
Darin Petkov457728b2013-01-09 09:49:08 +0100222 LOG(INFO) << "Service " << unique_name_ << " destroyed.";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000223 metrics_->DeregisterService(this);
224}
Paul Stewart75897df2011-04-27 09:05:53 -0700225
mukesh agrawal8a3188d2011-12-01 20:56:44 +0000226void Service::AutoConnect() {
Darin Petkov3abc3be2012-06-27 10:48:23 +0200227 const char *reason = NULL;
228 if (IsAutoConnectable(&reason)) {
mukesh agrawaldc7b8442012-09-27 13:48:14 -0700229 Error error;
Darin Petkov457728b2013-01-09 09:49:08 +0100230 LOG(INFO) << "Auto-connecting to service " << unique_name_;
Christopher Wiley0801d192012-09-24 11:57:15 -0700231 ThrottleFutureAutoConnects();
mukesh agrawaldc7b8442012-09-27 13:48:14 -0700232 Connect(&error, __func__);
mukesh agrawal76d13882012-01-12 15:23:11 -0800233 } else {
mukesh agrawal03c15ce2012-11-29 17:36:21 -0800234 if (reason == kAutoConnConnected || reason == kAutoConnBusy) {
235 SLOG(Service, 1)
Darin Petkov457728b2013-01-09 09:49:08 +0100236 << "Suppressed autoconnect to service " << unique_name_ << " "
mukesh agrawal03c15ce2012-11-29 17:36:21 -0800237 << "(" << reason << ")";
238 } else {
Darin Petkov457728b2013-01-09 09:49:08 +0100239 LOG(INFO) << "Suppressed autoconnect to service " << unique_name_ << " "
mukesh agrawal03c15ce2012-11-29 17:36:21 -0800240 << "(" << reason << ")";
241 }
mukesh agrawal8a3188d2011-12-01 20:56:44 +0000242 }
243}
244
mukesh agrawaldc7b8442012-09-27 13:48:14 -0700245void Service::Connect(Error */*error*/, const char *reason) {
246 LOG(INFO) << "Connect to service " << unique_name() <<": " << reason;
mukesh agrawaladb68482012-01-17 16:31:51 -0800247 explicitly_disconnected_ = false;
Thieu Leaf471412013-06-27 14:12:37 -0700248 // Clear any failure state from a previous connect attempt.
249 if (state() == kStateFailure)
250 SetState(kStateIdle);
mukesh agrawaladb68482012-01-17 16:31:51 -0800251}
252
253void Service::Disconnect(Error */*error*/) {
mukesh agrawaldc7b8442012-09-27 13:48:14 -0700254 LOG(INFO) << "Disconnecting from service " << unique_name_;
Christopher Wiley3e7635e2012-08-15 09:46:17 -0700255 MemoryLog::GetInstance()->FlushToDisk();
mukesh agrawaladb68482012-01-17 16:31:51 -0800256}
257
Christopher Wileyabd3b502012-09-26 13:08:52 -0700258void Service::DisconnectWithFailure(ConnectFailure failure, Error *error) {
259 Disconnect(error);
260 SetFailure(failure);
261}
262
263void Service::UserInitiatedDisconnect(Error *error) {
264 Disconnect(error);
265 explicitly_disconnected_ = true;
266}
267
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500268void Service::ActivateCellularModem(const string &/*carrier*/,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500269 Error *error,
270 const ResultCallback &/*callback*/) {
271 Error::PopulateAndLog(error, Error::kNotSupported,
272 "Service doesn't support cellular modem activation.");
Darin Petkovc408e692011-08-17 13:47:15 -0700273}
274
Ben Chan5d924542013-02-14 17:49:08 -0800275void Service::CompleteCellularActivation(Error *error) {
276 Error::PopulateAndLog(
277 error, Error::kNotSupported,
278 "Service doesn't support cellular activation completion.");
279}
280
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800281bool Service::IsActive(Error */*error*/) {
Paul Stewartbfb82552012-10-24 16:48:48 -0700282 return state() != kStateUnknown &&
283 state() != kStateIdle &&
284 state() != kStateFailure;
Paul Stewart03dba0b2011-08-22 16:32:45 -0700285}
286
Darin Petkovc8d91e52013-01-21 11:43:47 +0100287// static
288bool Service::IsConnectedState(ConnectState state) {
289 return (state == kStateConnected ||
290 state == kStatePortal ||
291 state == kStateOnline);
292}
293
294// static
295bool Service::IsConnectingState(ConnectState state) {
296 return (state == kStateAssociating ||
297 state == kStateConfiguring);
298}
299
300bool Service::IsConnected() const {
301 return IsConnectedState(state());
302}
303
304bool Service::IsConnecting() const {
305 return IsConnectingState(state());
306}
307
Paul Stewart03dba0b2011-08-22 16:32:45 -0700308void Service::SetState(ConnectState state) {
309 if (state == state_) {
310 return;
311 }
312
Darin Petkov457728b2013-01-09 09:49:08 +0100313 LOG(INFO) << "Service " << unique_name_ << ": state "
314 << ConnectStateToString(state_) << " -> "
315 << ConnectStateToString(state);
316
Darin Petkov0857f8e2012-12-21 10:49:17 +0100317 if (state == kStateFailure) {
Darin Petkov385b9bc2012-12-03 15:25:05 +0100318 NoteDisconnectEvent();
319 }
320
Darin Petkovc8d91e52013-01-21 11:43:47 +0100321 previous_state_ = state_;
Paul Stewart03dba0b2011-08-22 16:32:45 -0700322 state_ = state;
323 if (state != kStateFailure) {
324 failure_ = kFailureUnknown;
Darin Petkovaba89322013-03-11 14:48:22 +0100325 SetErrorDetails(kErrorDetailsNone);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700326 }
mukesh agrawalcf24a242012-05-21 16:46:11 -0700327 if (state == kStateConnected) {
Christopher Wiley0801d192012-09-24 11:57:15 -0700328 failed_time_ = 0;
mukesh agrawalcf24a242012-05-21 16:46:11 -0700329 has_ever_connected_ = true;
330 SaveToProfile();
Christopher Wiley0801d192012-09-24 11:57:15 -0700331 // When we succeed in connecting, forget that connects failed in the past.
332 // Give services one chance at a fast autoconnect retry by resetting the
333 // cooldown to 0 to indicate that the last connect was successful.
334 auto_connect_cooldown_milliseconds_ = 0;
335 reenable_auto_connect_task_.Cancel();
mukesh agrawalcf24a242012-05-21 16:46:11 -0700336 }
Paul Stewartf2d60912012-07-15 08:37:30 -0700337 UpdateErrorProperty();
Paul Stewart03dba0b2011-08-22 16:32:45 -0700338 manager_->UpdateService(this);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000339 metrics_->NotifyServiceStateChanged(this, state);
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200340 adaptor_->EmitStringChanged(flimflam::kStateProperty, GetStateString());
Paul Stewart03dba0b2011-08-22 16:32:45 -0700341}
342
Christopher Wiley0801d192012-09-24 11:57:15 -0700343void Service::ReEnableAutoConnectTask() {
344 // Kill the thing blocking AutoConnect().
345 reenable_auto_connect_task_.Cancel();
346 // Post to the manager, giving it an opportunity to AutoConnect again.
347 manager_->UpdateService(this);
348}
349
350void Service::ThrottleFutureAutoConnects() {
351 if (auto_connect_cooldown_milliseconds_ > 0) {
mukesh agrawaldc7b8442012-09-27 13:48:14 -0700352 LOG(INFO) << "Throttling future autoconnects to service " << unique_name_
353 << ". Next autoconnect in "
Christopher Wiley0801d192012-09-24 11:57:15 -0700354 << auto_connect_cooldown_milliseconds_ << " milliseconds.";
355 reenable_auto_connect_task_.Reset(Bind(&Service::ReEnableAutoConnectTask,
356 weak_ptr_factory_.GetWeakPtr()));
357 dispatcher_->PostDelayedTask(reenable_auto_connect_task_.callback(),
358 auto_connect_cooldown_milliseconds_);
359 }
360 auto_connect_cooldown_milliseconds_ =
361 std::min(kMaxAutoConnectCooldownTimeMilliseconds,
362 std::max(kMinAutoConnectCooldownTimeMilliseconds,
363 auto_connect_cooldown_milliseconds_ *
364 kAutoConnectCooldownBackoffFactor));
365}
366
Paul Stewart03dba0b2011-08-22 16:32:45 -0700367void Service::SetFailure(ConnectFailure failure) {
368 failure_ = failure;
mukesh agrawal568b5c62012-02-28 14:44:47 -0800369 failed_time_ = time(NULL);
Paul Stewartf2d60912012-07-15 08:37:30 -0700370 UpdateErrorProperty();
Paul Stewart03dba0b2011-08-22 16:32:45 -0700371 SetState(kStateFailure);
372}
373
mukesh agrawal568b5c62012-02-28 14:44:47 -0800374void Service::SetFailureSilent(ConnectFailure failure) {
Darin Petkov0857f8e2012-12-21 10:49:17 +0100375 NoteDisconnectEvent();
mukesh agrawal568b5c62012-02-28 14:44:47 -0800376 // Note that order matters here, since SetState modifies |failure_| and
377 // |failed_time_|.
378 SetState(kStateIdle);
379 failure_ = failure;
Paul Stewartf2d60912012-07-15 08:37:30 -0700380 UpdateErrorProperty();
mukesh agrawal568b5c62012-02-28 14:44:47 -0800381 failed_time_ = time(NULL);
382}
383
Chris Masone6791a432011-07-12 13:23:19 -0700384string Service::GetRpcIdentifier() const {
Chris Masone3c3f6a12011-07-01 10:01:41 -0700385 return adaptor_->GetRpcIdentifier();
386}
387
Paul Stewarte7de2942013-04-25 17:07:31 -0700388string Service::GetLoadableStorageIdentifier(
389 const StoreInterface &storage) const {
390 return IsLoadableFrom(storage) ? GetStorageIdentifier() : "";
391}
392
393bool Service::IsLoadableFrom(const StoreInterface &storage) const {
394 return storage.ContainsGroup(GetStorageIdentifier());
Paul Stewartbba6a5b2011-11-02 18:45:59 -0700395}
396
Chris Masone9d779932011-08-25 16:33:41 -0700397bool Service::Load(StoreInterface *storage) {
398 const string id = GetStorageIdentifier();
Chris Masone34af2182011-08-22 11:59:36 -0700399 if (!storage->ContainsGroup(id)) {
400 LOG(WARNING) << "Service is not available in the persistent store: " << id;
401 return false;
402 }
403 storage->GetBool(id, kStorageAutoConnect, &auto_connect_);
Paul Stewartc3dbff12013-07-17 10:32:48 -0700404 LoadString(storage, id, kStorageCheckPortal, kCheckPortalAuto,
405 &check_portal_);
Chris Masone34af2182011-08-22 11:59:36 -0700406 storage->GetBool(id, kStorageFavorite, &favorite_);
Paul Stewartc3dbff12013-07-17 10:32:48 -0700407 LoadString(storage, id, kStorageGUID, "", &guid_);
mukesh agrawalcf24a242012-05-21 16:46:11 -0700408 storage->GetBool(id, kStorageHasEverConnected, &has_ever_connected_);
Paul Stewartc3dbff12013-07-17 10:32:48 -0700409 if (!storage->GetInt(id, kStoragePriority, &priority_)) {
410 priority_ = kPriorityNone;
411 }
412 LoadString(storage, id, kStorageProxyConfig, "", &proxy_config_);
Chris Masone34af2182011-08-22 11:59:36 -0700413 storage->GetBool(id, kStorageSaveCredentials, &save_credentials_);
Paul Stewartc3dbff12013-07-17 10:32:48 -0700414 LoadString(storage, id, kStorageUIData, "", &ui_data_);
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700415
Paul Stewart1062d9d2012-04-27 10:42:27 -0700416 static_ip_parameters_.Load(storage, id);
Chris Masone34af2182011-08-22 11:59:36 -0700417
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700418 if (mutable_eap()) {
419 mutable_eap()->Load(storage, id);
420 OnEapCredentialsChanged();
421 }
422
mukesh agrawaladb68482012-01-17 16:31:51 -0800423 explicitly_disconnected_ = false;
Paul Stewarta41e38d2011-11-11 07:47:29 -0800424 favorite_ = true;
425
Chris Masone34af2182011-08-22 11:59:36 -0700426 return true;
Darin Petkovba40dd32011-07-11 20:06:39 -0700427}
428
Paul Stewart65512e12012-03-26 18:01:08 -0700429bool Service::Unload() {
Paul Stewart7fb09382012-07-18 17:32:27 -0700430 auto_connect_ = IsAutoConnectByDefault();
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800431 check_portal_ = kCheckPortalAuto;
Christopher Wileyabd3b502012-09-26 13:08:52 -0700432 explicitly_disconnected_ = false;
Paul Stewarta41e38d2011-11-11 07:47:29 -0800433 favorite_ = false;
Paul Stewarte7cce8f2012-09-11 10:56:38 -0700434 guid_ = "";
Paul Stewart88769de2012-09-21 13:14:36 -0700435 has_ever_connected_ = false;
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800436 priority_ = kPriorityNone;
437 proxy_config_ = "";
438 save_credentials_ = true;
439 ui_data_ = "";
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700440 if (mutable_eap()) {
441 mutable_eap()->Reset();
442 }
443 ClearEAPCertification();
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800444
Wade Guthrie9e0c2502012-04-19 15:26:40 -0700445 Error error; // Ignored.
446 Disconnect(&error);
Paul Stewart65512e12012-03-26 18:01:08 -0700447 return false;
Paul Stewarta41e38d2011-11-11 07:47:29 -0800448}
449
Albert Chaulk0e1cdea2013-02-27 15:32:55 -0800450void Service::Remove(Error */*error*/) {
451 Unload();
452}
453
Chris Masone9d779932011-08-25 16:33:41 -0700454bool Service::Save(StoreInterface *storage) {
455 const string id = GetStorageIdentifier();
Chris Masone34af2182011-08-22 11:59:36 -0700456
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200457 storage->SetString(id, kStorageType, GetTechnologyString());
Paul Stewart2706aaf2011-12-14 16:44:04 -0800458
Wade Guthrie4f28e8b2012-04-11 10:52:07 -0700459 storage->SetBool(id, kStorageAutoConnect, auto_connect_);
Chris Masone34af2182011-08-22 11:59:36 -0700460 if (check_portal_ == kCheckPortalAuto) {
461 storage->DeleteKey(id, kStorageCheckPortal);
462 } else {
463 storage->SetString(id, kStorageCheckPortal, check_portal_);
464 }
465 storage->SetBool(id, kStorageFavorite, favorite_);
mukesh agrawalcf24a242012-05-21 16:46:11 -0700466 SaveString(storage, id, kStorageGUID, guid_, false, true);
467 storage->SetBool(id, kStorageHasEverConnected, has_ever_connected_);
mukesh agrawald835b202011-10-07 15:26:47 -0700468 storage->SetString(id, kStorageName, friendly_name_);
Chris Masone34af2182011-08-22 11:59:36 -0700469 if (priority_ != kPriorityNone) {
470 storage->SetInt(id, kStoragePriority, priority_);
471 } else {
472 storage->DeleteKey(id, kStoragePriority);
473 }
Paul Stewart987e71e2011-12-05 09:45:06 -0800474 SaveString(storage, id, kStorageProxyConfig, proxy_config_, false, true);
Darin Petkov0debec02013-01-22 10:40:05 +0100475 storage->SetBool(id, kStorageSaveCredentials, save_credentials_);
Paul Stewart987e71e2011-12-05 09:45:06 -0800476 SaveString(storage, id, kStorageUIData, ui_data_, false, true);
Chris Masone34af2182011-08-22 11:59:36 -0700477
Paul Stewart1062d9d2012-04-27 10:42:27 -0700478 static_ip_parameters_.Save(storage, id);
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700479 if (eap()) {
480 eap()->Save(storage, id, save_credentials_);
481 }
Chris Masone34af2182011-08-22 11:59:36 -0700482 return true;
483}
484
Gary Moraind93615e2012-04-27 11:50:03 -0700485void Service::SaveToCurrentProfile() {
486 // Some unittests do not specify a manager.
487 if (manager()) {
488 manager()->SaveServiceToProfile(this);
489 }
Thieu Led4e9e552012-02-16 16:26:07 -0800490}
491
Paul Stewartcb59fed2012-03-21 21:14:46 -0700492void Service::Configure(const KeyValueStore &args, Error *error) {
Ben Chanfad4a0b2012-04-18 15:49:59 -0700493 SLOG(Service, 5) << "Configuring bool properties:";
Paul Stewart99dc9f32013-06-27 07:39:25 -0700494 for (const auto &bool_it : args.bool_properties()) {
495 if (ContainsKey(parameters_ignored_for_configure_, bool_it.first)) {
Paul Stewartcb59fed2012-03-21 21:14:46 -0700496 continue;
497 }
Paul Stewart99dc9f32013-06-27 07:39:25 -0700498 SLOG(Service, 5) << " " << bool_it.first;
Paul Stewartcb59fed2012-03-21 21:14:46 -0700499 Error set_error;
Paul Stewart99dc9f32013-06-27 07:39:25 -0700500 store_.SetBoolProperty(bool_it.first, bool_it.second, &set_error);
501 OnPropertyChanged(bool_it.first);
Paul Stewartcb59fed2012-03-21 21:14:46 -0700502 if (error->IsSuccess() && set_error.IsFailure()) {
503 error->CopyFrom(set_error);
504 }
505 }
Paul Stewart7a20aa42013-01-17 12:21:41 -0800506 SLOG(Service, 5) << "Configuring int32 properties:";
Paul Stewart99dc9f32013-06-27 07:39:25 -0700507 for (const auto &int_it : args.int_properties()) {
508 if (ContainsKey(parameters_ignored_for_configure_, int_it.first)) {
Paul Stewartcb59fed2012-03-21 21:14:46 -0700509 continue;
510 }
Paul Stewart99dc9f32013-06-27 07:39:25 -0700511 SLOG(Service, 5) << " " << int_it.first;
Paul Stewartcb59fed2012-03-21 21:14:46 -0700512 Error set_error;
Paul Stewart99dc9f32013-06-27 07:39:25 -0700513 store_.SetInt32Property(int_it.first, int_it.second, &set_error);
514 OnPropertyChanged(int_it.first);
515 if (error->IsSuccess() && set_error.IsFailure()) {
516 error->CopyFrom(set_error);
517 }
518 }
519 SLOG(Service, 5) << "Configuring string properties:";
520 for (const auto &string_it : args.string_properties()) {
521 if (ContainsKey(parameters_ignored_for_configure_, string_it.first)) {
522 continue;
523 }
524 SLOG(Service, 5) << " " << string_it.first;
525 Error set_error;
526 store_.SetStringProperty(string_it.first, string_it.second, &set_error);
527 OnPropertyChanged(string_it.first);
528 if (error->IsSuccess() && set_error.IsFailure()) {
529 error->CopyFrom(set_error);
530 }
531 }
532 SLOG(Service, 5) << "Configuring string array properties:";
533 for (const auto &strings_it : args.strings_properties()) {
534 if (ContainsKey(parameters_ignored_for_configure_, strings_it.first)) {
535 continue;
536 }
537 SLOG(Service, 5) << " " << strings_it.first;
538 Error set_error;
539 store_.SetStringsProperty(strings_it.first, strings_it.second, &set_error);
540 OnPropertyChanged(strings_it.first);
Paul Stewartcb59fed2012-03-21 21:14:46 -0700541 if (error->IsSuccess() && set_error.IsFailure()) {
542 error->CopyFrom(set_error);
543 }
544 }
545}
546
Paul Stewart7a20aa42013-01-17 12:21:41 -0800547bool Service::DoPropertiesMatch(const KeyValueStore &args) const {
Paul Stewart7a20aa42013-01-17 12:21:41 -0800548 SLOG(Service, 5) << "Checking bool properties:";
Paul Stewart99dc9f32013-06-27 07:39:25 -0700549 for (const auto &bool_it: args.bool_properties()) {
550 SLOG(Service, 5) << " " << bool_it.first;
Paul Stewart7a20aa42013-01-17 12:21:41 -0800551 Error get_error;
552 bool value;
Paul Stewart99dc9f32013-06-27 07:39:25 -0700553 if (!store_.GetBoolProperty(bool_it.first, &value, &get_error) ||
554 value != bool_it.second) {
Paul Stewart7a20aa42013-01-17 12:21:41 -0800555 return false;
556 }
557 }
558 SLOG(Service, 5) << "Checking int32 properties:";
Paul Stewart99dc9f32013-06-27 07:39:25 -0700559 for (const auto &int_it : args.int_properties()) {
560 SLOG(Service, 5) << " " << int_it.first;
Paul Stewart7a20aa42013-01-17 12:21:41 -0800561 Error get_error;
562 int32 value;
Paul Stewart99dc9f32013-06-27 07:39:25 -0700563 if (!store_.GetInt32Property(int_it.first, &value, &get_error) ||
564 value != int_it.second) {
565 return false;
566 }
567 }
568 SLOG(Service, 5) << "Checking string properties:";
569 for (const auto &string_it : args.string_properties()) {
570 SLOG(Service, 5) << " " << string_it.first;
571 Error get_error;
572 string value;
573 if (!store_.GetStringProperty(string_it.first, &value, &get_error) ||
574 value != string_it.second) {
575 return false;
576 }
577 }
578 SLOG(Service, 5) << "Checking string array properties:";
579 for (const auto &strings_it : args.strings_properties()) {
580 SLOG(Service, 5) << " " << strings_it.first;
581 Error get_error;
582 vector<string> value;
583 if (!store_.GetStringsProperty(strings_it.first, &value, &get_error) ||
584 value != strings_it.second) {
Paul Stewart7a20aa42013-01-17 12:21:41 -0800585 return false;
586 }
587 }
588 return true;
589}
590
Paul Stewart10ccbb32012-04-26 15:59:30 -0700591bool Service::IsRemembered() const {
592 return profile_ && !manager_->IsServiceEphemeral(this);
593}
594
Paul Stewartdf3c0a82012-11-09 15:54:33 -0800595bool Service::IsDependentOn(const ServiceRefPtr &b) const {
Paul Stewartcd7f5852013-03-27 13:54:23 -0700596 if (!connection_ || !b || !b->connection()) {
Paul Stewartdf3c0a82012-11-09 15:54:33 -0800597 return false;
598 }
599 return connection_->GetLowerConnection() == b->connection();
600}
601
mukesh agrawal00917ce2011-11-22 23:56:55 +0000602void Service::MakeFavorite() {
603 if (favorite_) {
604 // We do not want to clobber the value of auto_connect_ (it may
605 // be user-set). So return early.
606 return;
607 }
608
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700609 MarkAsFavorite();
610 SetAutoConnect(true);
mukesh agrawal00917ce2011-11-22 23:56:55 +0000611}
612
Darin Petkov5eb05422012-05-11 15:45:25 +0200613void Service::SetConnection(const ConnectionRefPtr &connection) {
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800614 if (connection.get()) {
Paul Stewart1e3bc4962012-09-14 12:20:22 -0700615 // TODO(pstew): Make this function testable by using a factory here.
Paul Stewartee6b3d72013-07-12 16:07:51 -0700616 // http://crbug.com/216664
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800617 http_proxy_.reset(new HTTPProxy(connection));
Darin Petkov5eb05422012-05-11 15:45:25 +0200618 http_proxy_->Start(dispatcher_, sockets_.get());
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800619 } else {
620 http_proxy_.reset();
Paul Stewartdef189e2012-08-02 20:12:09 -0700621 static_ip_parameters_.ClearSavedParameters();
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800622 }
623 connection_ = connection;
Paul Stewart1e3bc4962012-09-14 12:20:22 -0700624 Error error;
625 string ipconfig = GetIPConfigRpcIdentifier(&error);
626 if (error.IsSuccess()) {
627 adaptor_->EmitRpcIdentifierChanged(shill::kIPConfigProperty, ipconfig);
628 }
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800629}
630
Gaurav Shah10109f22011-11-11 20:16:22 -0800631bool Service::Is8021xConnectable() const {
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700632 return eap() && eap()->IsConnectable();
Gaurav Shah10109f22011-11-11 20:16:22 -0800633}
634
Paul Stewartbc6e7392012-05-24 07:07:48 -0700635bool Service::AddEAPCertification(const string &name, size_t depth) {
636 if (depth >= kEAPMaxCertificationElements) {
637 LOG(WARNING) << "Ignoring certification " << name
638 << " because depth " << depth
639 << " exceeds our maximum of "
640 << kEAPMaxCertificationElements;
641 return false;
642 }
643
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700644 if (depth >= remote_certification_.size()) {
645 remote_certification_.resize(depth + 1);
646 } else if (name == remote_certification_[depth]) {
Paul Stewartbc6e7392012-05-24 07:07:48 -0700647 return true;
648 }
649
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700650 remote_certification_[depth] = name;
Paul Stewartbc6e7392012-05-24 07:07:48 -0700651 LOG(INFO) << "Received certification for "
652 << name
653 << " at depth "
654 << depth;
655 return true;
656}
657
658void Service::ClearEAPCertification() {
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700659 remote_certification_.clear();
Paul Stewartbc6e7392012-05-24 07:07:48 -0700660}
661
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700662void Service::SetAutoConnect(bool connect) {
663 if (auto_connect() == connect) {
664 return;
665 }
666 auto_connect_ = connect;
667 adaptor_->EmitBoolChanged(flimflam::kAutoConnectProperty, auto_connect());
668}
669
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700670void Service::SetEapCredentials(EapCredentials *eap) {
671 // This operation must be done at most once for the lifetime of the service.
672 CHECK(eap && !eap_);
673
674 eap_.reset(eap);
675 eap_->InitPropertyStore(mutable_store());
Gaurav Shah10109f22011-11-11 20:16:22 -0800676}
677
mukesh agrawal00917ce2011-11-22 23:56:55 +0000678// static
Gaurav Shahc6d6c722011-11-17 18:59:39 -0800679const char *Service::ConnectFailureToString(const ConnectFailure &state) {
680 switch (state) {
681 case kFailureUnknown:
682 return "Unknown";
Paul Stewartf2d60912012-07-15 08:37:30 -0700683 case kFailureAAA:
684 return flimflam::kErrorAaaFailed;
685 case kFailureActivation:
686 return flimflam::kErrorActivationFailed;
687 case kFailureBadPassphrase:
688 return flimflam::kErrorBadPassphrase;
689 case kFailureBadWEPKey:
690 return flimflam::kErrorBadWEPKey;
691 case kFailureConnect:
692 return flimflam::kErrorConnectFailed;
693 case kFailureDNSLookup:
694 return flimflam::kErrorDNSLookupFailed;
695 case kFailureDHCP:
696 return flimflam::kErrorDhcpFailed;
Darin Petkov1c049c72013-03-21 13:15:45 +0100697 case kFailureEAPAuthentication:
698 return shill::kErrorEapAuthenticationFailed;
699 case kFailureEAPLocalTLS:
700 return shill::kErrorEapLocalTlsFailed;
701 case kFailureEAPRemoteTLS:
702 return shill::kErrorEapRemoteTlsFailed;
Paul Stewartf2d60912012-07-15 08:37:30 -0700703 case kFailureHTTPGet:
704 return flimflam::kErrorHTTPGetFailed;
Darin Petkov1c049c72013-03-21 13:15:45 +0100705 case kFailureInternal:
706 return flimflam::kErrorInternal;
707 case kFailureIPSecCertAuth:
708 return flimflam::kErrorIpsecCertAuthFailed;
709 case kFailureIPSecPSKAuth:
710 return flimflam::kErrorIpsecPskAuthFailed;
Gaurav Shahc6d6c722011-11-17 18:59:39 -0800711 case kFailureNeedEVDO:
Paul Stewartf2d60912012-07-15 08:37:30 -0700712 return flimflam::kErrorNeedEvdo;
Gaurav Shahc6d6c722011-11-17 18:59:39 -0800713 case kFailureNeedHomeNetwork:
Paul Stewartf2d60912012-07-15 08:37:30 -0700714 return flimflam::kErrorNeedHomeNetwork;
715 case kFailureOTASP:
716 return flimflam::kErrorOtaspFailed;
717 case kFailureOutOfRange:
718 return flimflam::kErrorOutOfRange;
719 case kFailurePinMissing:
720 return flimflam::kErrorPinMissing;
721 case kFailurePPPAuth:
722 return flimflam::kErrorPppAuthFailed;
Thieu Le48e6d6d2011-12-06 00:40:27 +0000723 case kFailureMax:
Darin Petkov1c049c72013-03-21 13:15:45 +0100724 NOTREACHED();
Gaurav Shahc6d6c722011-11-17 18:59:39 -0800725 }
726 return "Invalid";
727}
728
729// static
730const char *Service::ConnectStateToString(const ConnectState &state) {
731 switch (state) {
732 case kStateUnknown:
733 return "Unknown";
734 case kStateIdle:
735 return "Idle";
736 case kStateAssociating:
737 return "Associating";
738 case kStateConfiguring:
739 return "Configuring";
740 case kStateConnected:
741 return "Connected";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000742 case kStatePortal:
743 return "Portal";
Gaurav Shahc6d6c722011-11-17 18:59:39 -0800744 case kStateFailure:
745 return "Failure";
746 case kStateOnline:
747 return "Online";
748 }
749 return "Invalid";
750}
751
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200752string Service::GetTechnologyString() const {
Gaurav Shah435de2c2011-11-17 19:01:07 -0800753 return Technology::NameFromIdentifier(technology());
754}
755
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200756string Service::CalculateTechnology(Error */*error*/) {
757 return GetTechnologyString();
758}
759
Paul Stewart483e4722012-12-18 10:23:17 -0800760// static
761void Service::ExpireEventsBefore(
762 int seconds_ago, const Timestamp &now, std::deque<Timestamp> *events) {
763 struct timeval period = (const struct timeval){ seconds_ago };
764 while (!events->empty()) {
765 if (events->size() < static_cast<size_t>(kMaxDisconnectEventHistory)) {
766 struct timeval elapsed = (const struct timeval){ 0 };
767 timersub(&now.monotonic, &events->front().monotonic, &elapsed);
768 if (timercmp(&elapsed, &period, <)) {
769 break;
770 }
771 }
772 events->pop_front();
773 }
774}
775
Darin Petkov385b9bc2012-12-03 15:25:05 +0100776void Service::NoteDisconnectEvent() {
777 SLOG(Service, 2) << __func__;
Darin Petkovcb0b5662012-12-13 09:59:44 +0100778 // Ignore the event if it's user-initiated explicit disconnect.
Darin Petkov385b9bc2012-12-03 15:25:05 +0100779 if (explicitly_disconnected_) {
Darin Petkovcb0b5662012-12-13 09:59:44 +0100780 SLOG(Service, 2) << "Explicit disconnect ignored.";
781 return;
782 }
783 // Ignore the event if manager is not running (e.g., service disconnects on
784 // shutdown).
785 if (!manager_->running()) {
786 SLOG(Service, 2) << "Disconnect while manager stopped ignored.";
787 return;
788 }
789 // Ignore the event if the power state is not on (e.g., when suspending).
790 PowerManager *power_manager = manager_->power_manager();
791 if (!power_manager ||
792 (power_manager->power_state() != PowerManager::kOn &&
793 power_manager->power_state() != PowerManager::kUnknown)) {
794 SLOG(Service, 2) << "Disconnect in transitional power state ignored.";
Darin Petkov385b9bc2012-12-03 15:25:05 +0100795 return;
796 }
Paul Stewart483e4722012-12-18 10:23:17 -0800797 int period = 0;
Darin Petkov385b9bc2012-12-03 15:25:05 +0100798 size_t threshold = 0;
Darin Petkov0c65bdd2012-12-05 13:42:41 +0100799 deque<Timestamp> *events = NULL;
Darin Petkovc8d91e52013-01-21 11:43:47 +0100800 // Sometimes services transition to Idle before going into a failed state so
801 // take into account the last non-idle state.
802 ConnectState state = state_ == kStateIdle ? previous_state_ : state_;
803 if (IsConnectedState(state)) {
Darin Petkovcb0b5662012-12-13 09:59:44 +0100804 LOG(INFO) << "Noting an unexpected connection drop.";
Paul Stewart483e4722012-12-18 10:23:17 -0800805 period = kDisconnectsMonitorSeconds;
Darin Petkov385b9bc2012-12-03 15:25:05 +0100806 threshold = kReportDisconnectsThreshold;
807 events = &disconnects_;
Darin Petkovc8d91e52013-01-21 11:43:47 +0100808 } else if (IsConnectingState(state)) {
Darin Petkovcb0b5662012-12-13 09:59:44 +0100809 LOG(INFO) << "Noting an unexpected failure to connect.";
Paul Stewart483e4722012-12-18 10:23:17 -0800810 period = kMisconnectsMonitorSeconds;
Darin Petkov385b9bc2012-12-03 15:25:05 +0100811 threshold = kReportMisconnectsThreshold;
812 events = &misconnects_;
813 } else {
Darin Petkovcb0b5662012-12-13 09:59:44 +0100814 SLOG(Service, 2)
815 << "Not connected or connecting, state transition ignored.";
Darin Petkov385b9bc2012-12-03 15:25:05 +0100816 return;
817 }
Darin Petkov0c65bdd2012-12-05 13:42:41 +0100818 Timestamp now = time_->GetNow();
Paul Stewart483e4722012-12-18 10:23:17 -0800819 // Discard old events first.
820 ExpireEventsBefore(period, now, events);
Darin Petkov385b9bc2012-12-03 15:25:05 +0100821 events->push_back(now);
822 if (events->size() >= threshold) {
823 diagnostics_reporter_->OnConnectivityEvent();
824 }
825}
826
Paul Stewart483e4722012-12-18 10:23:17 -0800827bool Service::HasRecentConnectionIssues() {
828 Timestamp now = time_->GetNow();
829 ExpireEventsBefore(kDisconnectsMonitorSeconds, now, &disconnects_);
830 ExpireEventsBefore(kMisconnectsMonitorSeconds, now, &misconnects_);
831 return !disconnects_.empty() || !misconnects_.empty();
832}
833
Jason Glasgowb5790052012-01-27 01:03:52 -0500834// static
Paul Stewart22aa71b2011-09-16 12:15:11 -0700835bool Service::DecideBetween(int a, int b, bool *decision) {
836 if (a == b)
837 return false;
838 *decision = (a > b);
839 return true;
840}
841
mukesh agrawal43970a22013-02-15 16:00:07 -0800842uint16 Service::SecurityLevel() {
843 return (crypto_algorithm_ << 2) | (key_rotation_ << 1) | endpoint_auth_;
844}
845
mukesh agrawal00917ce2011-11-22 23:56:55 +0000846// static
Paul Stewart22aa71b2011-09-16 12:15:11 -0700847bool Service::Compare(ServiceRefPtr a,
848 ServiceRefPtr b,
Paul Stewart39db5ca2013-03-18 14:15:17 -0700849 bool compare_connectivity_state,
mukesh agrawalddc378f2012-02-17 18:26:20 -0800850 const vector<Technology::Identifier> &tech_order,
851 const char **reason) {
Paul Stewart22aa71b2011-09-16 12:15:11 -0700852 bool ret;
853
Paul Stewart39db5ca2013-03-18 14:15:17 -0700854 if (compare_connectivity_state && a->state() != b->state()) {
Paul Stewart22aa71b2011-09-16 12:15:11 -0700855 if (DecideBetween(a->IsConnected(), b->IsConnected(), &ret)) {
mukesh agrawalddc378f2012-02-17 18:26:20 -0800856 *reason = kServiceSortIsConnected;
Paul Stewart22aa71b2011-09-16 12:15:11 -0700857 return ret;
858 }
859
Paul Stewarta121c442012-06-09 14:12:58 -0700860 if (DecideBetween(!a->IsPortalled(), !b->IsPortalled(), &ret)) {
861 *reason = kServiceSortIsPortalled;
862 return ret;
863 }
Paul Stewart22aa71b2011-09-16 12:15:11 -0700864
865 if (DecideBetween(a->IsConnecting(), b->IsConnecting(), &ret)) {
mukesh agrawalddc378f2012-02-17 18:26:20 -0800866 *reason = kServiceSortIsConnecting;
Paul Stewart22aa71b2011-09-16 12:15:11 -0700867 return ret;
868 }
mukesh agrawal8a3188d2011-12-01 20:56:44 +0000869
870 if (DecideBetween(!a->IsFailed(), !b->IsFailed(), &ret)) {
mukesh agrawalddc378f2012-02-17 18:26:20 -0800871 *reason = kServiceSortIsFailed;
mukesh agrawal8a3188d2011-12-01 20:56:44 +0000872 return ret;
873 }
Paul Stewart22aa71b2011-09-16 12:15:11 -0700874 }
875
Darin Petkov2f903b32012-04-18 12:56:43 +0200876 if (DecideBetween(a->connectable(), b->connectable(), &ret)) {
877 *reason = kServiceSortConnectable;
878 return ret;
879 }
880
Paul Stewartdf3c0a82012-11-09 15:54:33 -0800881 if (DecideBetween(a->IsDependentOn(b), b->IsDependentOn(a), &ret)) {
882 *reason = kServiceSortDependency;
883 return ret;
884 }
885
Darin Petkov2f903b32012-04-18 12:56:43 +0200886 // Ignore the auto-connect property if both services are connected
887 // already. This allows connected non-autoconnectable VPN services to be
888 // sorted higher than other connected services based on technology order.
889 if (!a->IsConnected() &&
890 DecideBetween(a->auto_connect(), b->auto_connect(), &ret)) {
891 *reason = kServiceSortAutoConnect;
892 return ret;
893 }
894
895 if (DecideBetween(a->favorite(), b->favorite(), &ret)) {
896 *reason = kServiceSortFavorite;
897 return ret;
898 }
899
900 if (DecideBetween(a->priority(), b->priority(), &ret)) {
901 *reason = kServiceSortPriority;
Paul Stewart22aa71b2011-09-16 12:15:11 -0700902 return ret;
903 }
904
905 // TODO(pstew): Below this point we are making value judgements on
906 // services that are not related to anything intrinsic or
907 // user-specified. These heuristics should be richer (contain
908 // historical information, for example) and be subject to user
909 // customization.
Paul Stewart22aa71b2011-09-16 12:15:11 -0700910 for (vector<Technology::Identifier>::const_iterator it = tech_order.begin();
911 it != tech_order.end();
912 ++it) {
Joshua Kroll053fa822012-06-05 09:50:43 -0700913 if (DecideBetween(a->technology() == *it, b->technology() == *it, &ret)) {
mukesh agrawalddc378f2012-02-17 18:26:20 -0800914 *reason = kServiceSortTechnology;
Paul Stewart22aa71b2011-09-16 12:15:11 -0700915 return ret;
mukesh agrawalddc378f2012-02-17 18:26:20 -0800916 }
Paul Stewart22aa71b2011-09-16 12:15:11 -0700917 }
918
mukesh agrawal43970a22013-02-15 16:00:07 -0800919 if (DecideBetween(a->SecurityLevel(), b->SecurityLevel(), &ret) ||
Paul Stewart22aa71b2011-09-16 12:15:11 -0700920 DecideBetween(a->strength(), b->strength(), &ret)) {
mukesh agrawalddc378f2012-02-17 18:26:20 -0800921 *reason = kServiceSortSecurityEtc;
Paul Stewart22aa71b2011-09-16 12:15:11 -0700922 return ret;
923 }
924
mukesh agrawalddc378f2012-02-17 18:26:20 -0800925 *reason = kServiceSortUniqueName;
Darin Petkov457728b2013-01-09 09:49:08 +0100926 return a->unique_name() < b->unique_name();
Paul Stewart22aa71b2011-09-16 12:15:11 -0700927}
928
Chris Masone34af2182011-08-22 11:59:36 -0700929const ProfileRefPtr &Service::profile() const { return profile_; }
930
931void Service::set_profile(const ProfileRefPtr &p) { profile_ = p; }
932
Philipp Neubeck79173602012-11-13 21:10:09 +0100933void Service::SetProfile(const ProfileRefPtr &p) {
934 SLOG(Service, 2) << "SetProfile from "
935 << (profile_ ? profile_->GetFriendlyName() : "")
936 << " to " << (p ? p->GetFriendlyName() : "");
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700937 if (profile_ == p) {
938 return;
939 }
Philipp Neubeck79173602012-11-13 21:10:09 +0100940 profile_ = p;
941 Error error;
942 string profile_rpc_id = GetProfileRpcId(&error);
943 if (!error.IsSuccess()) {
944 return;
945 }
946 adaptor_->EmitStringChanged(flimflam::kProfileProperty, profile_rpc_id);
947}
948
Paul Stewartff14b022012-04-24 20:06:23 -0700949void Service::OnPropertyChanged(const string &property) {
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700950 if (Is8021x() && EapCredentials::IsEapAuthenticationProperty(property)) {
951 OnEapCredentialsChanged();
Paul Stewart81426132012-05-16 10:05:10 -0700952 }
mukesh agrawalcf24a242012-05-21 16:46:11 -0700953 SaveToProfile();
Paul Stewartd215af62012-04-24 23:25:50 -0700954 if ((property == flimflam::kCheckPortalProperty ||
955 property == flimflam::kProxyConfigProperty) &&
956 (state_ == kStateConnected ||
957 state_ == kStatePortal ||
958 state_ == kStateOnline)) {
959 manager_->RecheckPortalOnService(this);
960 }
Paul Stewartff14b022012-04-24 20:06:23 -0700961}
962
Christopher Wiley0801d192012-09-24 11:57:15 -0700963void Service::OnAfterResume() {
964 // Forget old autoconnect failures across suspend/resume.
965 auto_connect_cooldown_milliseconds_ = 0;
966 reenable_auto_connect_task_.Cancel();
Christopher Wileya4c61ae2012-10-01 11:04:30 -0700967 // Forget if the user disconnected us, we might be able to connect now.
968 explicitly_disconnected_ = false;
Christopher Wiley0801d192012-09-24 11:57:15 -0700969}
970
Paul Stewart10241e32012-04-23 18:15:06 -0700971string Service::GetIPConfigRpcIdentifier(Error *error) {
972 if (!connection_) {
973 error->Populate(Error::kNotFound);
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700974 return DBusAdaptor::kNullPath;
Paul Stewart10241e32012-04-23 18:15:06 -0700975 }
976
977 string id = connection_->ipconfig_rpc_identifier();
978
979 if (id.empty()) {
980 // Do not return an empty IPConfig.
981 error->Populate(Error::kNotFound);
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700982 return DBusAdaptor::kNullPath;
Paul Stewart10241e32012-04-23 18:15:06 -0700983 }
984
985 return id;
986}
987
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700988void Service::SetConnectable(bool connectable) {
989 if (connectable_ == connectable)
990 return;
mukesh agrawal29c13a12011-11-24 00:09:19 +0000991 connectable_ = connectable;
992 adaptor_->EmitBoolChanged(flimflam::kConnectableProperty, connectable_);
993}
994
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700995void Service::SetConnectableFull(bool connectable) {
Darin Petkovb2ba39f2012-06-06 10:33:43 +0200996 if (connectable_ == connectable) {
997 return;
998 }
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700999 SetConnectable(connectable);
Darin Petkovb2ba39f2012-06-06 10:33:43 +02001000 if (manager_->HasService(this)) {
1001 manager_->UpdateService(this);
1002 }
1003}
1004
Darin Petkov58f0b6d2012-06-12 12:52:30 +02001005string Service::GetStateString() const {
mukesh agrawalf2f68a52011-09-01 12:15:48 -07001006 switch (state_) {
Gaurav Shahc6d6c722011-11-17 18:59:39 -08001007 case kStateIdle:
1008 return flimflam::kStateIdle;
1009 case kStateAssociating:
1010 return flimflam::kStateAssociation;
1011 case kStateConfiguring:
1012 return flimflam::kStateConfiguration;
mukesh agrawalf2f68a52011-09-01 12:15:48 -07001013 case kStateConnected:
Paul Stewart20088d82012-02-16 06:58:55 -08001014 return flimflam::kStateReady;
Gaurav Shahc6d6c722011-11-17 18:59:39 -08001015 case kStateFailure:
1016 return flimflam::kStateFailure;
Paul Stewart20088d82012-02-16 06:58:55 -08001017 case kStatePortal:
1018 return flimflam::kStatePortal;
Gaurav Shahc6d6c722011-11-17 18:59:39 -08001019 case kStateOnline:
1020 return flimflam::kStateOnline;
1021 case kStateUnknown:
mukesh agrawalf2f68a52011-09-01 12:15:48 -07001022 default:
Gaurav Shahc6d6c722011-11-17 18:59:39 -08001023 return "";
mukesh agrawalf2f68a52011-09-01 12:15:48 -07001024 }
1025}
1026
Darin Petkov58f0b6d2012-06-12 12:52:30 +02001027string Service::CalculateState(Error */*error*/) {
1028 return GetStateString();
1029}
1030
mukesh agrawalbf14e942012-03-02 14:36:34 -08001031bool Service::IsAutoConnectable(const char **reason) const {
1032 if (!connectable()) {
1033 *reason = kAutoConnNotConnectable;
1034 return false;
1035 }
1036
1037 if (IsConnected()) {
1038 *reason = kAutoConnConnected;
1039 return false;
1040 }
1041
1042 if (IsConnecting()) {
1043 *reason = kAutoConnConnecting;
1044 return false;
1045 }
1046
1047 if (explicitly_disconnected_) {
1048 *reason = kAutoConnExplicitDisconnect;
1049 return false;
1050 }
1051
Christopher Wiley0801d192012-09-24 11:57:15 -07001052 if (!reenable_auto_connect_task_.IsCancelled()) {
1053 *reason = kAutoConnThrottled;
1054 return false;
1055 }
1056
Darin Petkov4cbff5b2013-01-29 16:29:05 +01001057 if (!Technology::IsPrimaryConnectivityTechnology(technology_) &&
1058 !manager_->IsOnline()) {
1059 *reason = kAutoConnOffline;
1060 return false;
1061 }
1062
mukesh agrawalbf14e942012-03-02 14:36:34 -08001063 return true;
mukesh agrawal76d13882012-01-12 15:23:11 -08001064}
1065
Paul Stewartd215af62012-04-24 23:25:50 -07001066bool Service::IsPortalDetectionDisabled() const {
1067 return check_portal_ == kCheckPortalFalse;
1068}
1069
1070bool Service::IsPortalDetectionAuto() const {
1071 return check_portal_ == kCheckPortalAuto;
1072}
1073
mukesh agrawalffa3d042011-10-06 15:26:10 -07001074void Service::HelpRegisterDerivedBool(
1075 const string &name,
Gaurav Shah1b7a6162011-11-09 11:41:01 -08001076 bool(Service::*get)(Error *),
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001077 bool(Service::*set)(const bool&, Error *)) {
Chris Masone27c4aa52011-07-02 13:10:14 -07001078 store_.RegisterDerivedBool(
1079 name,
1080 BoolAccessor(new CustomAccessor<Service, bool>(this, get, set)));
Chris Masone3bd3c8c2011-06-13 08:20:26 -07001081}
1082
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001083void Service::HelpRegisterDerivedInt32(
1084 const string &name,
1085 int32(Service::*get)(Error *),
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001086 bool(Service::*set)(const int32&, Error *)) {
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001087 store_.RegisterDerivedInt32(
1088 name,
1089 Int32Accessor(new CustomAccessor<Service, int32>(this, get, set)));
1090}
1091
mukesh agrawalffa3d042011-10-06 15:26:10 -07001092void Service::HelpRegisterDerivedString(
1093 const string &name,
Gaurav Shah1b7a6162011-11-09 11:41:01 -08001094 string(Service::*get)(Error *),
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001095 bool(Service::*set)(const string&, Error *)) {
Chris Masone27c4aa52011-07-02 13:10:14 -07001096 store_.RegisterDerivedString(
1097 name,
1098 StringAccessor(new CustomAccessor<Service, string>(this, get, set)));
Chris Masone3bd3c8c2011-06-13 08:20:26 -07001099}
1100
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001101void Service::HelpRegisterConstDerivedRpcIdentifier(
Jason Glasgowacdc11f2012-03-30 14:12:22 -04001102 const string &name,
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001103 RpcIdentifier(Service::*get)(Error *)) {
Jason Glasgowacdc11f2012-03-30 14:12:22 -04001104 store_.RegisterDerivedRpcIdentifier(
1105 name,
1106 RpcIdentifierAccessor(new CustomAccessor<Service, RpcIdentifier>(
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001107 this, get, NULL)));
Jason Glasgowacdc11f2012-03-30 14:12:22 -04001108}
1109
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001110void Service::HelpRegisterConstDerivedUint16(
Paul Stewartbe5f5b32011-12-07 17:11:11 -08001111 const string &name,
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001112 uint16(Service::*get)(Error *)) {
Paul Stewartbe5f5b32011-12-07 17:11:11 -08001113 store_.RegisterDerivedUint16(
1114 name,
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001115 Uint16Accessor(new CustomAccessor<Service, uint16>(this, get, NULL)));
Paul Stewartbe5f5b32011-12-07 17:11:11 -08001116}
1117
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001118void Service::HelpRegisterConstDerivedStrings(
1119 const string &name, Strings(Service::*get)(Error *error)) {
1120 store_.RegisterDerivedStrings(
1121 name,
1122 StringsAccessor(new CustomAccessor<Service, Strings>(this, get, NULL)));
1123}
1124
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001125// static
Paul Stewartc3dbff12013-07-17 10:32:48 -07001126void Service::LoadString(StoreInterface *storage,
1127 const string &id,
1128 const string &key,
1129 const string &default_value,
1130 string *value) {
1131 if (!storage->GetString(id, key, value)) {
1132 *value = default_value;
1133 }
1134}
1135
1136// static
Darin Petkovba40dd32011-07-11 20:06:39 -07001137void Service::SaveString(StoreInterface *storage,
Chris Masone34af2182011-08-22 11:59:36 -07001138 const string &id,
Darin Petkovba40dd32011-07-11 20:06:39 -07001139 const string &key,
1140 const string &value,
1141 bool crypted,
1142 bool save) {
1143 if (value.empty() || !save) {
Chris Masone34af2182011-08-22 11:59:36 -07001144 storage->DeleteKey(id, key);
Darin Petkovba40dd32011-07-11 20:06:39 -07001145 return;
1146 }
1147 if (crypted) {
Chris Masone34af2182011-08-22 11:59:36 -07001148 storage->SetCryptedString(id, key, value);
Darin Petkovba40dd32011-07-11 20:06:39 -07001149 return;
1150 }
Chris Masone34af2182011-08-22 11:59:36 -07001151 storage->SetString(id, key, value);
Darin Petkovba40dd32011-07-11 20:06:39 -07001152}
1153
Paul Stewart967eaeb2013-04-25 19:53:07 -07001154map<string, string> Service::GetLoadableProfileEntries() {
1155 return manager_->GetLoadableProfileEntriesForService(this);
1156}
1157
Paul Stewartcb59fed2012-03-21 21:14:46 -07001158void Service::IgnoreParameterForConfigure(const string &parameter) {
1159 parameters_ignored_for_configure_.insert(parameter);
1160}
1161
Paul Stewartac4ac002011-08-26 12:04:26 -07001162const string &Service::GetEAPKeyManagement() const {
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001163 CHECK(eap());
1164 return eap()->key_management();
Paul Stewartac4ac002011-08-26 12:04:26 -07001165}
1166
1167void Service::SetEAPKeyManagement(const string &key_management) {
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001168 CHECK(mutable_eap());
1169 mutable_eap()->SetKeyManagement(key_management, NULL);
Paul Stewartac4ac002011-08-26 12:04:26 -07001170}
1171
Thieu Le284fe792012-01-31 17:53:19 -08001172bool Service::GetAutoConnect(Error */*error*/) {
1173 return auto_connect();
1174}
1175
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001176bool Service::SetAutoConnectFull(const bool &connect, Error */*error*/) {
Darin Petkov36d962d2013-03-25 13:03:14 +01001177 LOG(INFO) << "Service " << unique_name() << ": AutoConnect="
1178 << auto_connect() << "->" << connect;
1179 if (auto_connect() == connect) {
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001180 return false;
Darin Petkov36d962d2013-03-25 13:03:14 +01001181 }
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001182 SetAutoConnect(connect);
Darin Petkov36d962d2013-03-25 13:03:14 +01001183 manager_->UpdateService(this);
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001184 return true;
Thieu Le284fe792012-01-31 17:53:19 -08001185}
1186
Paul Stewartd215af62012-04-24 23:25:50 -07001187string Service::GetCheckPortal(Error *error) {
1188 return check_portal_;
1189}
1190
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001191bool Service::SetCheckPortal(const string &check_portal, Error *error) {
Paul Stewartd215af62012-04-24 23:25:50 -07001192 if (check_portal != kCheckPortalFalse &&
1193 check_portal != kCheckPortalTrue &&
1194 check_portal != kCheckPortalAuto) {
1195 Error::PopulateAndLog(error, Error::kInvalidArguments,
1196 base::StringPrintf(
1197 "Invalid Service CheckPortal property value: %s",
1198 check_portal.c_str()));
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001199 return false;
1200 }
1201 if (check_portal == check_portal_) {
1202 return false;
Paul Stewartd215af62012-04-24 23:25:50 -07001203 }
1204 check_portal_ = check_portal;
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001205 return true;
Paul Stewartd215af62012-04-24 23:25:50 -07001206}
1207
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001208string Service::GetGuid(Error *error) {
1209 return guid_;
1210}
1211
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001212bool Service::SetGuid(const string &guid, Error */*error*/) {
1213 if (guid_ == guid) {
1214 return false;
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001215 }
1216 guid_ = guid;
1217 adaptor_->EmitStringChanged(flimflam::kGuidProperty, guid_);
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001218 return true;
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001219}
1220
1221void Service::MarkAsFavorite() {
1222 favorite_ = true;
1223 adaptor_->EmitBoolChanged(flimflam::kFavoriteProperty, favorite_);
1224}
1225
mukesh agrawal43970a22013-02-15 16:00:07 -08001226void Service::SetSecurity(CryptoAlgorithm crypto_algorithm, bool key_rotation,
1227 bool endpoint_auth) {
1228 crypto_algorithm_ = crypto_algorithm;
1229 key_rotation_ = key_rotation;
1230 endpoint_auth_ = endpoint_auth;
1231}
1232
mukesh agrawald4dc0832013-03-25 14:38:26 -07001233string Service::GetNameProperty(Error */*error*/) {
Paul Stewart0c438332012-04-11 07:55:27 -07001234 return friendly_name_;
1235}
1236
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001237bool Service::SetNameProperty(const string &name, Error *error) {
Paul Stewart0c438332012-04-11 07:55:27 -07001238 if (name != friendly_name_) {
1239 Error::PopulateAndLog(error, Error::kInvalidArguments,
Paul Stewart2bf424f2012-04-11 18:59:39 -07001240 base::StringPrintf(
Darin Petkov457728b2013-01-09 09:49:08 +01001241 "Service %s Name property cannot be modified.",
1242 unique_name_.c_str()));
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001243 return false;
Paul Stewart0c438332012-04-11 07:55:27 -07001244 }
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001245 return false;
Paul Stewart0c438332012-04-11 07:55:27 -07001246}
1247
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001248int32 Service::GetPriority(Error *error) {
1249 return priority_;
1250}
1251
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001252bool Service::SetPriority(const int32 &priority, Error *error) {
1253 if (priority_ == priority) {
1254 return false;
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001255 }
1256 priority_ = priority;
1257 adaptor_->EmitIntChanged(flimflam::kPriorityProperty, priority_);
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001258 return true;
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001259}
1260
Paul Stewart1b1a7f22012-01-06 16:24:06 -08001261string Service::GetProfileRpcId(Error *error) {
1262 if (!profile_) {
1263 // This happens in some unit tests where profile_ is not set.
1264 error->Populate(Error::kNotFound);
1265 return "";
1266 }
1267 return profile_->GetRpcIdentifier();
1268}
1269
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001270bool Service::SetProfileRpcId(const string &profile, Error *error) {
1271 if (profile_ && profile_->GetRpcIdentifier() == profile) {
1272 return false;
1273 }
1274 ProfileConstRefPtr old_profile = profile_;
1275 // No need to Emit afterwards, since SetProfileForService will call
1276 // into SetProfile (if the profile actually changes).
Paul Stewart1b1a7f22012-01-06 16:24:06 -08001277 manager_->SetProfileForService(this, profile, error);
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001278 // Can't just use error.IsSuccess(), because that also requires saving
1279 // the profile to succeed. (See Profile::AdoptService)
1280 return (profile_ != old_profile);
Paul Stewart1b1a7f22012-01-06 16:24:06 -08001281}
1282
Paul Stewartbe5f5b32011-12-07 17:11:11 -08001283uint16 Service::GetHTTPProxyPort(Error */*error*/) {
1284 if (http_proxy_.get()) {
1285 return static_cast<uint16>(http_proxy_->proxy_port());
1286 }
1287 return 0;
1288}
1289
Philipp Neubeck79173602012-11-13 21:10:09 +01001290string Service::GetProxyConfig(Error *error) {
1291 return proxy_config_;
1292}
1293
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001294bool Service::SetProxyConfig(const string &proxy_config, Error *error) {
1295 if (proxy_config_ == proxy_config)
1296 return false;
Philipp Neubeck79173602012-11-13 21:10:09 +01001297 proxy_config_ = proxy_config;
1298 adaptor_->EmitStringChanged(flimflam::kProxyConfigProperty, proxy_config_);
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001299 return true;
Philipp Neubeck79173602012-11-13 21:10:09 +01001300}
1301
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001302// static
1303Strings Service::ExtractWallClockToStrings(
1304 const deque<Timestamp> &timestamps) {
1305 Strings strings;
1306 for (deque<Timestamp>::const_iterator it = timestamps.begin();
1307 it != timestamps.end(); ++it) {
1308 strings.push_back(it->wall_clock);
1309 }
1310 return strings;
1311}
1312
1313Strings Service::GetDisconnectsProperty(Error */*error*/) {
1314 return ExtractWallClockToStrings(disconnects_);
1315}
1316
1317Strings Service::GetMisconnectsProperty(Error */*error*/) {
1318 return ExtractWallClockToStrings(misconnects_);
1319}
1320
mukesh agrawalcf24a242012-05-21 16:46:11 -07001321void Service::SaveToProfile() {
1322 if (profile_.get() && profile_->GetConstStorage()) {
1323 profile_->UpdateService(this);
1324 }
1325}
1326
Arman Uguray2717a102013-01-29 23:36:06 -08001327void Service::SetFriendlyName(const string &friendly_name) {
1328 if (friendly_name == friendly_name_)
1329 return;
1330 friendly_name_ = friendly_name;
1331 adaptor()->EmitStringChanged(flimflam::kNameProperty, friendly_name_);
1332}
1333
Darin Petkovd78ee7e2012-01-12 11:21:10 +01001334void Service::SetStrength(uint8 strength) {
1335 if (strength == strength_) {
1336 return;
1337 }
1338 strength_ = strength;
1339 adaptor_->EmitUint8Changed(flimflam::kSignalStrengthProperty, strength);
1340}
1341
Darin Petkovaba89322013-03-11 14:48:22 +01001342void Service::SetErrorDetails(const string &details) {
1343 if (error_details_ == details) {
1344 return;
1345 }
1346 error_details_ = details;
1347 adaptor_->EmitStringChanged(shill::kErrorDetailsProperty, error_details_);
1348}
1349
Paul Stewartf2d60912012-07-15 08:37:30 -07001350void Service::UpdateErrorProperty() {
1351 const string error(ConnectFailureToString(failure_));
1352 if (error == error_) {
1353 return;
1354 }
1355 error_ = error;
1356 adaptor_->EmitStringChanged(flimflam::kErrorProperty, error);
1357}
1358
Paul Stewart75897df2011-04-27 09:05:53 -07001359} // namespace shill