blob: fd054f0f6ebc2ea8dea15bde6595a20870741d25 [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 <stdio.h>
Alex Vakulenkoa41ab512014-07-23 14:24:23 -07008#include <time.h>
Chris Masoneee929b72011-05-10 10:02:18 -07009
Alex Vakulenko8a532292014-06-16 17:18:44 -070010#include <algorithm>
Chris Masone8fe2c7e2011-06-09 15:51:19 -070011#include <map>
Ben Chancd477322014-10-17 14:19:30 -070012#include <memory>
Paul Stewart75897df2011-04-27 09:05:53 -070013#include <string>
Chris Masone8fe2c7e2011-06-09 15:51:19 -070014#include <vector>
Paul Stewart75897df2011-04-27 09:05:53 -070015
Ben Chana0ddf462014-02-06 11:32:42 -080016#include <base/strings/string_number_conversions.h>
17#include <base/strings/stringprintf.h>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070018#include <chromeos/dbus/service_constants.h>
Chris Masoneee929b72011-05-10 10:02:18 -070019
Paul Stewartbe5f5b32011-12-07 17:11:11 -080020#include "shill/connection.h"
Paul Stewart75897df2011-04-27 09:05:53 -070021#include "shill/control_interface.h"
Darin Petkov385b9bc2012-12-03 15:25:05 +010022#include "shill/diagnostics_reporter.h"
Paul Stewartc43cbbe2013-04-11 06:29:30 -070023#include "shill/eap_credentials.h"
Chris Masone8fe2c7e2011-06-09 15:51:19 -070024#include "shill/error.h"
Paul Stewartbe5f5b32011-12-07 17:11:11 -080025#include "shill/http_proxy.h"
Christopher Wileyb691efd2012-08-09 13:51:51 -070026#include "shill/logging.h"
Chris Masone6791a432011-07-12 13:23:19 -070027#include "shill/manager.h"
Thieu Le48e6d6d2011-12-06 00:40:27 +000028#include "shill/metrics.h"
Samuel Tan07dfabc2015-01-20 15:10:39 -080029#include "shill/net/event_history.h"
Peter Qiu8d6b5972014-10-28 15:33:34 -070030#include "shill/net/sockets.h"
Chris Masone7aa5f902011-07-11 11:13:35 -070031#include "shill/profile.h"
Chris Masone3bd3c8c2011-06-13 08:20:26 -070032#include "shill/property_accessor.h"
Chris Masone7aa5f902011-07-11 11:13:35 -070033#include "shill/refptr_types.h"
Chris Masoned7732e42011-05-20 11:08:56 -070034#include "shill/service_dbus_adaptor.h"
Paul Stewart45170bc2014-06-02 15:49:34 -070035#include "shill/service_property_change_notifier.h"
Darin Petkovba40dd32011-07-11 20:06:39 -070036#include "shill/store_interface.h"
Paul Stewart75897df2011-04-27 09:05:53 -070037
Christopher Wiley0801d192012-09-24 11:57:15 -070038using base::Bind;
Chris Masone8fe2c7e2011-06-09 15:51:19 -070039using std::map;
Paul Stewart75897df2011-04-27 09:05:53 -070040using std::string;
Chris Masone8fe2c7e2011-06-09 15:51:19 -070041using std::vector;
Paul Stewart75897df2011-04-27 09:05:53 -070042
43namespace shill {
Darin Petkovba40dd32011-07-11 20:06:39 -070044
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -070045namespace Logging {
46static auto kModuleLogScope = ScopeLogger::kService;
47static string ObjectID(const Service *s) { return s->GetRpcIdentifier(); }
48}
49
mukesh agrawal03c15ce2012-11-29 17:36:21 -080050const char Service::kAutoConnBusy[] = "busy";
mukesh agrawalbf14e942012-03-02 14:36:34 -080051const char Service::kAutoConnConnected[] = "connected";
52const char Service::kAutoConnConnecting[] = "connecting";
53const char Service::kAutoConnExplicitDisconnect[] = "explicitly disconnected";
54const char Service::kAutoConnNotConnectable[] = "not connectable";
Darin Petkov4cbff5b2013-01-29 16:29:05 +010055const char Service::kAutoConnOffline[] = "offline";
Ben Chan8e6b8ef2014-07-14 21:50:18 -070056const char Service::kAutoConnTechnologyNotConnectable[] =
57 "technology not connectable";
Christopher Wiley0801d192012-09-24 11:57:15 -070058const char Service::kAutoConnThrottled[] = "throttled";
mukesh agrawalbf14e942012-03-02 14:36:34 -080059
Paul Stewartbc6e7392012-05-24 07:07:48 -070060const size_t Service::kEAPMaxCertificationElements = 10;
61
Darin Petkovba40dd32011-07-11 20:06:39 -070062const char Service::kCheckPortalAuto[] = "auto";
63const char Service::kCheckPortalFalse[] = "false";
64const char Service::kCheckPortalTrue[] = "true";
65
Darin Petkovaba89322013-03-11 14:48:22 +010066const char Service::kErrorDetailsNone[] = "";
67
Paul Stewartac4ac002011-08-26 12:04:26 -070068const int Service::kPriorityNone = 0;
69
Darin Petkov2f903b32012-04-18 12:56:43 +020070const char Service::kServiceSortAutoConnect[] = "AutoConnect";
71const char Service::kServiceSortConnectable[] = "Connectable";
Paul Stewartdf3c0a82012-11-09 15:54:33 -080072const char Service::kServiceSortDependency[] = "Dependency";
Paul Stewart2da34c02013-10-17 15:28:56 -070073const char Service::kServiceSortHasEverConnected[] = "HasEverConnected";
mukesh agrawalddc378f2012-02-17 18:26:20 -080074const char Service::kServiceSortIsConnected[] = "IsConnected";
75const char Service::kServiceSortIsConnecting[] = "IsConnecting";
76const char Service::kServiceSortIsFailed[] = "IsFailed";
Paul Stewarta121c442012-06-09 14:12:58 -070077const char Service::kServiceSortIsPortalled[] = "IsPortal";
Darin Petkov2f903b32012-04-18 12:56:43 +020078const char Service::kServiceSortPriority[] = "Priority";
Paul Stewartd9c7cfc2015-01-06 14:26:22 -080079const char Service::kServiceSortPriorityWithinTechnology[] =
80 "PriorityWithinTechnology";
Rebecca Silberstein6d4836b2014-07-16 14:28:28 -070081const char Service::kServiceSortSecurity[] = "Security";
82const char Service::kServiceSortProfileOrder[] = "ProfileOrder";
83const char Service::kServiceSortEtc[] = "Etc";
mukesh agrawale37ad322013-10-08 16:33:56 -070084const char Service::kServiceSortSerialNumber[] = "SerialNumber";
Darin Petkov2f903b32012-04-18 12:56:43 +020085const char Service::kServiceSortTechnology[] = "Technology";
mukesh agrawalddc378f2012-02-17 18:26:20 -080086
Darin Petkovba40dd32011-07-11 20:06:39 -070087const char Service::kStorageAutoConnect[] = "AutoConnect";
88const char Service::kStorageCheckPortal[] = "CheckPortal";
Peter Qiua89154b2014-05-23 15:45:42 -070089const char Service::kStorageDNSAutoFallback[] = "DNSAutoFallback";
Paul Stewart0756db92012-01-27 08:34:47 -080090const char Service::kStorageError[] = "Error";
Darin Petkovba40dd32011-07-11 20:06:39 -070091const char Service::kStorageFavorite[] = "Favorite";
Paul Stewart0756db92012-01-27 08:34:47 -080092const char Service::kStorageGUID[] = "GUID";
mukesh agrawalcf24a242012-05-21 16:46:11 -070093const char Service::kStorageHasEverConnected[] = "HasEverConnected";
Darin Petkovba40dd32011-07-11 20:06:39 -070094const char Service::kStorageName[] = "Name";
95const char Service::kStoragePriority[] = "Priority";
Paul Stewartd9c7cfc2015-01-06 14:26:22 -080096const char Service::kStoragePriorityWithinTechnology[]
97 = "PriorityWithinTechnology";
Darin Petkovba40dd32011-07-11 20:06:39 -070098const char Service::kStorageProxyConfig[] = "ProxyConfig";
99const char Service::kStorageSaveCredentials[] = "SaveCredentials";
Paul Stewart2706aaf2011-12-14 16:44:04 -0800100const char Service::kStorageType[] = "Type";
Paul Stewart987e71e2011-12-05 09:45:06 -0800101const char Service::kStorageUIData[] = "UIData";
Peter Qiu9d581932014-04-14 16:37:37 -0700102const char Service::kStorageConnectionId[] = "ConnectionId";
Peter Qiud49760e2014-09-19 16:13:42 -0700103const char Service::kStorageLinkMonitorDisabled[] = "LinkMonitorDisabled";
Paul Stewart3fee7e32014-10-15 21:39:29 -0700104const char Service::kStorageManagedCredentials[] = "ManagedCredentials";
Darin Petkovba40dd32011-07-11 20:06:39 -0700105
Ben Chan7fab8972014-08-10 17:14:46 -0700106const uint8_t Service::kStrengthMax = 100;
107const uint8_t Service::kStrengthMin = 0;
mukesh agrawal8f3f7752012-02-17 19:42:09 -0800108
Ben Chan7fab8972014-08-10 17:14:46 -0700109const uint64_t Service::kMaxAutoConnectCooldownTimeMilliseconds =
110 30 * 60 * 1000;
111const uint64_t Service::kMinAutoConnectCooldownTimeMilliseconds = 1000;
112const uint64_t Service::kAutoConnectCooldownBackoffFactor = 2;
Christopher Wiley0801d192012-09-24 11:57:15 -0700113
Darin Petkov385b9bc2012-12-03 15:25:05 +0100114const int Service::kDisconnectsMonitorSeconds = 5 * 60;
115const int Service::kMisconnectsMonitorSeconds = 5 * 60;
116const int Service::kReportDisconnectsThreshold = 2;
117const int Service::kReportMisconnectsThreshold = 3;
118const int Service::kMaxDisconnectEventHistory = 20;
Samuel Tan07dfabc2015-01-20 15:10:39 -0800119const int Service::kMaxMisconnectEventHistory = 20;
Darin Petkov385b9bc2012-12-03 15:25:05 +0100120
mukesh agrawal51a7e932011-07-27 16:18:26 -0700121// static
mukesh agrawale37ad322013-10-08 16:33:56 -0700122unsigned int Service::next_serial_number_ = 0;
mukesh agrawal51a7e932011-07-27 16:18:26 -0700123
Paul Stewart75897df2011-04-27 09:05:53 -0700124Service::Service(ControlInterface *control_interface,
mukesh agrawalb54601c2011-06-07 17:39:22 -0700125 EventDispatcher *dispatcher,
Thieu Le3426c8f2012-01-11 17:35:11 -0800126 Metrics *metrics,
mukesh agrawal7a4e4002011-09-06 11:26:05 -0700127 Manager *manager,
Gaurav Shah435de2c2011-11-17 19:01:07 -0800128 Technology::Identifier technology)
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700129 : weak_ptr_factory_(this),
130 state_(kStateIdle),
Darin Petkovc8d91e52013-01-21 11:43:47 +0100131 previous_state_(kStateIdle),
Paul Stewart03dba0b2011-08-22 16:32:45 -0700132 failure_(kFailureUnknown),
133 auto_connect_(false),
Paul Stewart2da34c02013-10-17 15:28:56 -0700134 retain_auto_connect_(false),
Darin Petkovba40dd32011-07-11 20:06:39 -0700135 check_portal_(kCheckPortalAuto),
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700136 connectable_(false),
Paul Stewartf2d60912012-07-15 08:37:30 -0700137 error_(ConnectFailureToString(failure_)),
Darin Petkovaba89322013-03-11 14:48:22 +0100138 error_details_(kErrorDetailsNone),
Paul Stewartd7c09a52014-02-19 12:50:29 -0800139 previous_error_serial_number_(0),
mukesh agrawaladb68482012-01-17 16:31:51 -0800140 explicitly_disconnected_(false),
Peter Qiudc4e0992014-05-01 10:02:52 -0700141 is_in_user_connect_(false),
Darin Petkovba40dd32011-07-11 20:06:39 -0700142 priority_(kPriorityNone),
Paul Stewartd9c7cfc2015-01-06 14:26:22 -0800143 priority_within_technology_(kPriorityNone),
mukesh agrawal43970a22013-02-15 16:00:07 -0800144 crypto_algorithm_(kCryptoNone),
145 key_rotation_(false),
146 endpoint_auth_(false),
Paul Stewart22aa71b2011-09-16 12:15:11 -0700147 strength_(0),
Darin Petkovba40dd32011-07-11 20:06:39 -0700148 save_credentials_(true),
Gaurav Shah435de2c2011-11-17 19:01:07 -0800149 technology_(technology),
mukesh agrawal568b5c62012-02-28 14:44:47 -0800150 failed_time_(0),
mukesh agrawalcf24a242012-05-21 16:46:11 -0700151 has_ever_connected_(false),
Samuel Tan07dfabc2015-01-20 15:10:39 -0800152 disconnects_(kMaxDisconnectEventHistory),
153 misconnects_(kMaxMisconnectEventHistory),
Christopher Wiley0801d192012-09-24 11:57:15 -0700154 auto_connect_cooldown_milliseconds_(0),
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700155 store_(PropertyStore::PropertyChangeCallback(
156 base::Bind(&Service::OnPropertyChanged,
157 weak_ptr_factory_.GetWeakPtr()))),
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700158 dispatcher_(dispatcher),
mukesh agrawale37ad322013-10-08 16:33:56 -0700159 serial_number_(next_serial_number_++),
160 unique_name_(base::UintToString(serial_number_)),
mukesh agrawald835b202011-10-07 15:26:47 -0700161 friendly_name_(unique_name_),
Chris Masone6791a432011-07-12 13:23:19 -0700162 adaptor_(control_interface->CreateServiceAdaptor(this)),
Paul Stewart45170bc2014-06-02 15:49:34 -0700163 property_change_notifier_(
164 new ServicePropertyChangeNotifier(adaptor_.get())),
Thieu Le3426c8f2012-01-11 17:35:11 -0800165 metrics_(metrics),
Darin Petkov5eb05422012-05-11 15:45:25 +0200166 manager_(manager),
Christopher Wiley0801d192012-09-24 11:57:15 -0700167 sockets_(new Sockets()),
Darin Petkov385b9bc2012-12-03 15:25:05 +0100168 time_(Time::GetInstance()),
Paul Stewartdded0072013-10-24 12:38:54 -0700169 diagnostics_reporter_(DiagnosticsReporter::GetInstance()),
Peter Qiua89154b2014-05-23 15:45:42 -0700170 connection_id_(0),
Peter Qiud49760e2014-09-19 16:13:42 -0700171 is_dns_auto_fallback_allowed_(false),
Paul Stewart3fee7e32014-10-15 21:39:29 -0700172 link_monitor_disabled_(false),
173 managed_credentials_(false) {
Ben Chan923a5022013-09-20 11:23:23 -0700174 HelpRegisterDerivedBool(kAutoConnectProperty,
Thieu Le284fe792012-01-31 17:53:19 -0800175 &Service::GetAutoConnect,
Paul Stewart43d8dc02013-10-17 10:32:53 -0700176 &Service::SetAutoConnectFull,
177 &Service::ClearAutoConnect);
Chris Masone4d42df82011-07-02 17:09:39 -0700178
Thieu Le71f81a62014-07-11 15:17:47 -0700179 // kActivationTypeProperty: Registered in CellularService
Ben Chan923a5022013-09-20 11:23:23 -0700180 // kActivationStateProperty: Registered in CellularService
181 // kCellularApnProperty: Registered in CellularService
182 // kCellularLastGoodApnProperty: Registered in CellularService
183 // kNetworkTechnologyProperty: Registered in CellularService
Ben Chan408a8562014-02-05 00:02:18 -0800184 // kOutOfCreditsProperty: Registered in CellularService
185 // kPaymentPortalProperty: Registered in CellularService
Ben Chan923a5022013-09-20 11:23:23 -0700186 // kRoamingStateProperty: Registered in CellularService
187 // kServingOperatorProperty: Registered in CellularService
Ben Chan408a8562014-02-05 00:02:18 -0800188 // kUsageURLProperty: Registered in CellularService
189 // kCellularPPPUsernameProperty: Registered in CellularService
190 // kCellularPPPPasswordProperty: Registered in CellularService
191
192 // kNetworkIdProperty: Registered in WiMaxService
Chris Masone4d42df82011-07-02 17:09:39 -0700193
Ben Chan923a5022013-09-20 11:23:23 -0700194 HelpRegisterDerivedString(kCheckPortalProperty,
Paul Stewartd215af62012-04-24 23:25:50 -0700195 &Service::GetCheckPortal,
196 &Service::SetCheckPortal);
Ben Chan923a5022013-09-20 11:23:23 -0700197 store_.RegisterConstBool(kConnectableProperty, &connectable_);
198 HelpRegisterConstDerivedRpcIdentifier(kDeviceProperty,
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700199 &Service::GetDeviceRpcId);
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700200 store_.RegisterConstStrings(kEapRemoteCertificationProperty,
201 &remote_certification_);
Ben Chan923a5022013-09-20 11:23:23 -0700202 HelpRegisterDerivedString(kGuidProperty,
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700203 &Service::GetGuid,
204 &Service::SetGuid);
Chris Masone3bd3c8c2011-06-13 08:20:26 -0700205
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400206 // TODO(ers): in flimflam clearing Error has the side-effect of
207 // setting the service state to IDLE. Is this important? I could
208 // see an autotest depending on it.
Ben Chan923a5022013-09-20 11:23:23 -0700209 store_.RegisterConstString(kErrorProperty, &error_);
Ben Chan39a7beb2013-09-21 11:28:00 -0700210 store_.RegisterConstString(kErrorDetailsProperty, &error_details_);
Ben Chan39a7beb2013-09-21 11:28:00 -0700211 HelpRegisterConstDerivedUint16(kHTTPProxyPortProperty,
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700212 &Service::GetHTTPProxyPort);
Ben Chan39a7beb2013-09-21 11:28:00 -0700213 HelpRegisterConstDerivedRpcIdentifier(kIPConfigProperty,
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700214 &Service::GetIPConfigRpcIdentifier);
Ben Chancc225ef2014-09-30 13:26:51 -0700215 HelpRegisterDerivedBool(kIsActiveProperty, &Service::IsActive, nullptr,
216 nullptr);
Ben Chan923a5022013-09-20 11:23:23 -0700217 // kModeProperty: Registered in WiFiService
Paul Stewart0c438332012-04-11 07:55:27 -0700218
Ben Chan923a5022013-09-20 11:23:23 -0700219 HelpRegisterDerivedString(kNameProperty,
Paul Stewart0c438332012-04-11 07:55:27 -0700220 &Service::GetNameProperty,
Darin Petkov9c6e9812013-03-26 13:49:07 +0100221 &Service::SetNameProperty);
Ben Chan923a5022013-09-20 11:23:23 -0700222 // kPassphraseProperty: Registered in WiFiService
Ben Chan408a8562014-02-05 00:02:18 -0800223 // kPassphraseRequiredProperty: Registered in WiFiService, WiMaxService
Paul Stewartd7c09a52014-02-19 12:50:29 -0800224 store_.RegisterConstString(kPreviousErrorProperty,
225 &previous_error_);
226 store_.RegisterConstInt32(kPreviousErrorSerialNumberProperty,
227 &previous_error_serial_number_);
Ben Chan923a5022013-09-20 11:23:23 -0700228 HelpRegisterDerivedInt32(kPriorityProperty,
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700229 &Service::GetPriority,
230 &Service::SetPriority);
Paul Stewartd9c7cfc2015-01-06 14:26:22 -0800231 HelpRegisterDerivedInt32(kPriorityWithinTechnologyProperty,
232 &Service::GetPriorityWithinTechnology,
233 &Service::SetPriorityWithinTechnology);
Ben Chan923a5022013-09-20 11:23:23 -0700234 HelpRegisterDerivedString(kProfileProperty,
Chris Masone27c4aa52011-07-02 13:10:14 -0700235 &Service::GetProfileRpcId,
Paul Stewart1b1a7f22012-01-06 16:24:06 -0800236 &Service::SetProfileRpcId);
Ben Chan923a5022013-09-20 11:23:23 -0700237 HelpRegisterDerivedString(kProxyConfigProperty,
Philipp Neubeck79173602012-11-13 21:10:09 +0100238 &Service::GetProxyConfig,
239 &Service::SetProxyConfig);
Ben Chan923a5022013-09-20 11:23:23 -0700240 store_.RegisterBool(kSaveCredentialsProperty, &save_credentials_);
Paul Stewartfa11e282013-12-02 22:04:25 -0800241 HelpRegisterConstDerivedString(kTetheringProperty,
242 &Service::GetTethering);
Ben Chan923a5022013-09-20 11:23:23 -0700243 HelpRegisterDerivedString(kTypeProperty,
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200244 &Service::CalculateTechnology,
Ben Chancc225ef2014-09-30 13:26:51 -0700245 nullptr);
Ben Chan923a5022013-09-20 11:23:23 -0700246 // kSecurityProperty: Registered in WiFiService
247 HelpRegisterDerivedString(kStateProperty,
Chris Masone27c4aa52011-07-02 13:10:14 -0700248 &Service::CalculateState,
Ben Chancc225ef2014-09-30 13:26:51 -0700249 nullptr);
Ben Chan923a5022013-09-20 11:23:23 -0700250 store_.RegisterConstUint8(kSignalStrengthProperty, &strength_);
251 store_.RegisterString(kUIDataProperty, &ui_data_);
Ben Chan39a7beb2013-09-21 11:28:00 -0700252 HelpRegisterConstDerivedStrings(kDiagnosticsDisconnectsProperty,
Darin Petkov0c65bdd2012-12-05 13:42:41 +0100253 &Service::GetDisconnectsProperty);
Ben Chan39a7beb2013-09-21 11:28:00 -0700254 HelpRegisterConstDerivedStrings(kDiagnosticsMisconnectsProperty,
Darin Petkov0c65bdd2012-12-05 13:42:41 +0100255 &Service::GetMisconnectsProperty);
Peter Qiu9d581932014-04-14 16:37:37 -0700256 store_.RegisterConstInt32(kConnectionIdProperty, &connection_id_);
Peter Qiua89154b2014-05-23 15:45:42 -0700257 store_.RegisterBool(kDnsAutoFallbackProperty, &is_dns_auto_fallback_allowed_);
Peter Qiud49760e2014-09-19 16:13:42 -0700258 store_.RegisterBool(kLinkMonitorDisableProperty, &link_monitor_disabled_);
Paul Stewart3fee7e32014-10-15 21:39:29 -0700259 store_.RegisterBool(kManagedCredentialsProperty, &managed_credentials_);
Peter Qiu9d581932014-04-14 16:37:37 -0700260
Paul Stewart45170bc2014-06-02 15:49:34 -0700261 HelpRegisterObservedDerivedBool(kVisibleProperty,
262 &Service::GetVisibleProperty,
Ben Chancc225ef2014-09-30 13:26:51 -0700263 nullptr,
264 nullptr);
Paul Stewartcca85b12014-05-30 13:56:35 -0700265
Peter Qiu9b83c892014-08-09 23:06:02 -0700266 store_.RegisterConstString(kPortalDetectionFailedPhaseProperty,
267 &portal_detection_failure_phase_);
268 store_.RegisterConstString(kPortalDetectionFailedStatusProperty,
269 &portal_detection_failure_status_);
270
Wade Guthrie7ac610b2013-10-01 17:48:14 -0700271 metrics_->RegisterService(*this);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000272
Paul Stewart1062d9d2012-04-27 10:42:27 -0700273 static_ip_parameters_.PlumbPropertyStore(&store_);
274
Ben Chan923a5022013-09-20 11:23:23 -0700275 IgnoreParameterForConfigure(kTypeProperty);
276 IgnoreParameterForConfigure(kProfileProperty);
Paul Stewartcb59fed2012-03-21 21:14:46 -0700277
Darin Petkov9c366992013-01-10 12:32:21 +0100278 LOG(INFO) << Technology::NameFromIdentifier(technology) << " service "
279 << unique_name_ << " constructed.";
Paul Stewart75897df2011-04-27 09:05:53 -0700280}
281
Thieu Le48e6d6d2011-12-06 00:40:27 +0000282Service::~Service() {
Wade Guthrie7ac610b2013-10-01 17:48:14 -0700283 metrics_->DeregisterService(*this);
mukesh agrawal6cfe53f2013-08-13 13:39:01 -0700284 LOG(INFO) << "Service " << unique_name_ << " destroyed.";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000285}
Paul Stewart75897df2011-04-27 09:05:53 -0700286
mukesh agrawal8a3188d2011-12-01 20:56:44 +0000287void Service::AutoConnect() {
Ben Chancc225ef2014-09-30 13:26:51 -0700288 const char *reason = nullptr;
Darin Petkov3abc3be2012-06-27 10:48:23 +0200289 if (IsAutoConnectable(&reason)) {
mukesh agrawaldc7b8442012-09-27 13:48:14 -0700290 Error error;
Darin Petkov457728b2013-01-09 09:49:08 +0100291 LOG(INFO) << "Auto-connecting to service " << unique_name_;
Christopher Wiley0801d192012-09-24 11:57:15 -0700292 ThrottleFutureAutoConnects();
mukesh agrawaldc7b8442012-09-27 13:48:14 -0700293 Connect(&error, __func__);
mukesh agrawal76d13882012-01-12 15:23:11 -0800294 } else {
mukesh agrawal03c15ce2012-11-29 17:36:21 -0800295 if (reason == kAutoConnConnected || reason == kAutoConnBusy) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700296 SLOG(this, 1)
Darin Petkov457728b2013-01-09 09:49:08 +0100297 << "Suppressed autoconnect to service " << unique_name_ << " "
mukesh agrawal03c15ce2012-11-29 17:36:21 -0800298 << "(" << reason << ")";
299 } else {
Darin Petkov457728b2013-01-09 09:49:08 +0100300 LOG(INFO) << "Suppressed autoconnect to service " << unique_name_ << " "
mukesh agrawal03c15ce2012-11-29 17:36:21 -0800301 << "(" << reason << ")";
302 }
mukesh agrawal8a3188d2011-12-01 20:56:44 +0000303 }
304}
305
mukesh agrawaldc7b8442012-09-27 13:48:14 -0700306void Service::Connect(Error */*error*/, const char *reason) {
307 LOG(INFO) << "Connect to service " << unique_name() <<": " << reason;
Paul Stewart2eee6132014-05-09 13:33:26 -0700308 ClearExplicitlyDisconnected();
Thieu Leaf471412013-06-27 14:12:37 -0700309 // Clear any failure state from a previous connect attempt.
310 if (state() == kStateFailure)
311 SetState(kStateIdle);
mukesh agrawaladb68482012-01-17 16:31:51 -0800312}
313
Samuel Tan0d061192014-07-07 15:45:15 -0700314void Service::Disconnect(Error */*error*/, const char *reason) {
Paul Stewart72737352015-02-12 14:49:09 -0800315 string log_message = base::StringPrintf(
316 "Disconnecting from service %s: %s", unique_name_.c_str(), reason);
317 if (IsActive(nullptr)) {
318 LOG(INFO) << log_message;
319 } else {
320 SLOG(this, 1) << log_message;
321 }
mukesh agrawaladb68482012-01-17 16:31:51 -0800322}
323
Samuel Tan0d061192014-07-07 15:45:15 -0700324void Service::DisconnectWithFailure(ConnectFailure failure,
325 Error *error,
326 const char *reason) {
327 Disconnect(error, reason);
Christopher Wileyabd3b502012-09-26 13:08:52 -0700328 SetFailure(failure);
329}
330
331void Service::UserInitiatedDisconnect(Error *error) {
Samuel Tan0d061192014-07-07 15:45:15 -0700332 Disconnect(error, "D-Bus RPC");
Christopher Wileyabd3b502012-09-26 13:08:52 -0700333 explicitly_disconnected_ = true;
334}
335
Peter Qiudc4e0992014-05-01 10:02:52 -0700336void Service::UserInitiatedConnect(Error *error) {
337 Connect(error, "D-Bus RPC");
338 is_in_user_connect_ = true;
339}
340
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500341void Service::ActivateCellularModem(const string &/*carrier*/,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500342 Error *error,
343 const ResultCallback &/*callback*/) {
Paul Stewart34f424e2015-01-16 15:30:20 -0800344 Error::PopulateAndLog(FROM_HERE, error, Error::kNotSupported,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500345 "Service doesn't support cellular modem activation.");
Darin Petkovc408e692011-08-17 13:47:15 -0700346}
347
Ben Chan5d924542013-02-14 17:49:08 -0800348void Service::CompleteCellularActivation(Error *error) {
349 Error::PopulateAndLog(
Paul Stewart34f424e2015-01-16 15:30:20 -0800350 FROM_HERE, error, Error::kNotSupported,
Ben Chan5d924542013-02-14 17:49:08 -0800351 "Service doesn't support cellular activation completion.");
352}
353
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800354bool Service::IsActive(Error */*error*/) {
Paul Stewartbfb82552012-10-24 16:48:48 -0700355 return state() != kStateUnknown &&
356 state() != kStateIdle &&
357 state() != kStateFailure;
Paul Stewart03dba0b2011-08-22 16:32:45 -0700358}
359
Darin Petkovc8d91e52013-01-21 11:43:47 +0100360// static
361bool Service::IsConnectedState(ConnectState state) {
362 return (state == kStateConnected ||
363 state == kStatePortal ||
364 state == kStateOnline);
365}
366
367// static
368bool Service::IsConnectingState(ConnectState state) {
369 return (state == kStateAssociating ||
370 state == kStateConfiguring);
371}
372
373bool Service::IsConnected() const {
374 return IsConnectedState(state());
375}
376
377bool Service::IsConnecting() const {
378 return IsConnectingState(state());
379}
380
Paul Stewart03dba0b2011-08-22 16:32:45 -0700381void Service::SetState(ConnectState state) {
382 if (state == state_) {
383 return;
384 }
385
Darin Petkov457728b2013-01-09 09:49:08 +0100386 LOG(INFO) << "Service " << unique_name_ << ": state "
387 << ConnectStateToString(state_) << " -> "
388 << ConnectStateToString(state);
389
Peter Qiudc4e0992014-05-01 10:02:52 -0700390 // Metric reporting for result of user-initiated connection attempt.
391 if (is_in_user_connect_ && ((state == kStateConnected) ||
392 (state == kStateFailure) || (state == kStateIdle))) {
393 ReportUserInitiatedConnectionResult(state);
394 is_in_user_connect_ = false;
395 }
396
Darin Petkov0857f8e2012-12-21 10:49:17 +0100397 if (state == kStateFailure) {
Darin Petkov385b9bc2012-12-03 15:25:05 +0100398 NoteDisconnectEvent();
399 }
400
Darin Petkovc8d91e52013-01-21 11:43:47 +0100401 previous_state_ = state_;
Paul Stewart03dba0b2011-08-22 16:32:45 -0700402 state_ = state;
403 if (state != kStateFailure) {
404 failure_ = kFailureUnknown;
Darin Petkovaba89322013-03-11 14:48:22 +0100405 SetErrorDetails(kErrorDetailsNone);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700406 }
mukesh agrawalcf24a242012-05-21 16:46:11 -0700407 if (state == kStateConnected) {
Christopher Wiley0801d192012-09-24 11:57:15 -0700408 failed_time_ = 0;
mukesh agrawalcf24a242012-05-21 16:46:11 -0700409 has_ever_connected_ = true;
410 SaveToProfile();
Christopher Wiley0801d192012-09-24 11:57:15 -0700411 // When we succeed in connecting, forget that connects failed in the past.
412 // Give services one chance at a fast autoconnect retry by resetting the
413 // cooldown to 0 to indicate that the last connect was successful.
414 auto_connect_cooldown_milliseconds_ = 0;
415 reenable_auto_connect_task_.Cancel();
mukesh agrawalcf24a242012-05-21 16:46:11 -0700416 }
Paul Stewartf2d60912012-07-15 08:37:30 -0700417 UpdateErrorProperty();
Paul Stewart03dba0b2011-08-22 16:32:45 -0700418 manager_->UpdateService(this);
Wade Guthrie7ac610b2013-10-01 17:48:14 -0700419 metrics_->NotifyServiceStateChanged(*this, state);
Ben Chan923a5022013-09-20 11:23:23 -0700420 adaptor_->EmitStringChanged(kStateProperty, GetStateString());
Paul Stewart03dba0b2011-08-22 16:32:45 -0700421}
422
Peter Qiu9b83c892014-08-09 23:06:02 -0700423void Service::SetPortalDetectionFailure(const string &phase,
424 const string &status) {
425 portal_detection_failure_phase_ = phase;
426 portal_detection_failure_status_ = status;
427 adaptor_->EmitStringChanged(kPortalDetectionFailedPhaseProperty, phase);
428 adaptor_->EmitStringChanged(kPortalDetectionFailedStatusProperty, status);
429}
430
Christopher Wiley0801d192012-09-24 11:57:15 -0700431void Service::ReEnableAutoConnectTask() {
432 // Kill the thing blocking AutoConnect().
433 reenable_auto_connect_task_.Cancel();
434 // Post to the manager, giving it an opportunity to AutoConnect again.
435 manager_->UpdateService(this);
436}
437
438void Service::ThrottleFutureAutoConnects() {
439 if (auto_connect_cooldown_milliseconds_ > 0) {
mukesh agrawaldc7b8442012-09-27 13:48:14 -0700440 LOG(INFO) << "Throttling future autoconnects to service " << unique_name_
441 << ". Next autoconnect in "
Christopher Wiley0801d192012-09-24 11:57:15 -0700442 << auto_connect_cooldown_milliseconds_ << " milliseconds.";
443 reenable_auto_connect_task_.Reset(Bind(&Service::ReEnableAutoConnectTask,
444 weak_ptr_factory_.GetWeakPtr()));
445 dispatcher_->PostDelayedTask(reenable_auto_connect_task_.callback(),
446 auto_connect_cooldown_milliseconds_);
447 }
448 auto_connect_cooldown_milliseconds_ =
449 std::min(kMaxAutoConnectCooldownTimeMilliseconds,
450 std::max(kMinAutoConnectCooldownTimeMilliseconds,
451 auto_connect_cooldown_milliseconds_ *
452 kAutoConnectCooldownBackoffFactor));
453}
454
Paul Stewartd7c09a52014-02-19 12:50:29 -0800455void Service::SaveFailure() {
456 previous_error_ = ConnectFailureToString(failure_);
457 ++previous_error_serial_number_;
458}
459
Paul Stewart03dba0b2011-08-22 16:32:45 -0700460void Service::SetFailure(ConnectFailure failure) {
461 failure_ = failure;
Paul Stewartd7c09a52014-02-19 12:50:29 -0800462 SaveFailure();
Ben Chancc225ef2014-09-30 13:26:51 -0700463 failed_time_ = time(nullptr);
Paul Stewartf2d60912012-07-15 08:37:30 -0700464 UpdateErrorProperty();
Paul Stewart03dba0b2011-08-22 16:32:45 -0700465 SetState(kStateFailure);
466}
467
mukesh agrawal568b5c62012-02-28 14:44:47 -0800468void Service::SetFailureSilent(ConnectFailure failure) {
Darin Petkov0857f8e2012-12-21 10:49:17 +0100469 NoteDisconnectEvent();
mukesh agrawal568b5c62012-02-28 14:44:47 -0800470 // Note that order matters here, since SetState modifies |failure_| and
471 // |failed_time_|.
472 SetState(kStateIdle);
473 failure_ = failure;
Paul Stewartd7c09a52014-02-19 12:50:29 -0800474 SaveFailure();
Paul Stewartf2d60912012-07-15 08:37:30 -0700475 UpdateErrorProperty();
Ben Chancc225ef2014-09-30 13:26:51 -0700476 failed_time_ = time(nullptr);
mukesh agrawal568b5c62012-02-28 14:44:47 -0800477}
478
Chris Masone6791a432011-07-12 13:23:19 -0700479string Service::GetRpcIdentifier() const {
Chris Masone3c3f6a12011-07-01 10:01:41 -0700480 return adaptor_->GetRpcIdentifier();
481}
482
Paul Stewarte7de2942013-04-25 17:07:31 -0700483string Service::GetLoadableStorageIdentifier(
484 const StoreInterface &storage) const {
485 return IsLoadableFrom(storage) ? GetStorageIdentifier() : "";
486}
487
488bool Service::IsLoadableFrom(const StoreInterface &storage) const {
489 return storage.ContainsGroup(GetStorageIdentifier());
Paul Stewartbba6a5b2011-11-02 18:45:59 -0700490}
491
Chris Masone9d779932011-08-25 16:33:41 -0700492bool Service::Load(StoreInterface *storage) {
493 const string id = GetStorageIdentifier();
Chris Masone34af2182011-08-22 11:59:36 -0700494 if (!storage->ContainsGroup(id)) {
495 LOG(WARNING) << "Service is not available in the persistent store: " << id;
496 return false;
497 }
Paul Stewart2da34c02013-10-17 15:28:56 -0700498
Paul Stewart000f0332013-10-25 13:30:28 -0700499 auto_connect_ = IsAutoConnectByDefault();
Paul Stewart2da34c02013-10-17 15:28:56 -0700500 retain_auto_connect_ =
501 storage->GetBool(id, kStorageAutoConnect, &auto_connect_);
502 // The legacy "Favorite" flag will override retain_auto_connect_ if present.
503 storage->GetBool(id, kStorageFavorite, &retain_auto_connect_);
504
Paul Stewartc3dbff12013-07-17 10:32:48 -0700505 LoadString(storage, id, kStorageCheckPortal, kCheckPortalAuto,
506 &check_portal_);
Paul Stewartc3dbff12013-07-17 10:32:48 -0700507 LoadString(storage, id, kStorageGUID, "", &guid_);
Paul Stewartc3dbff12013-07-17 10:32:48 -0700508 if (!storage->GetInt(id, kStoragePriority, &priority_)) {
509 priority_ = kPriorityNone;
510 }
Paul Stewartd9c7cfc2015-01-06 14:26:22 -0800511 if (!storage->GetInt(id, kStoragePriorityWithinTechnology,
512 &priority_within_technology_)) {
513 priority_within_technology_ = kPriorityNone;
514 }
Paul Stewartc3dbff12013-07-17 10:32:48 -0700515 LoadString(storage, id, kStorageProxyConfig, "", &proxy_config_);
Chris Masone34af2182011-08-22 11:59:36 -0700516 storage->GetBool(id, kStorageSaveCredentials, &save_credentials_);
Paul Stewartc3dbff12013-07-17 10:32:48 -0700517 LoadString(storage, id, kStorageUIData, "", &ui_data_);
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700518
Peter Qiu9d581932014-04-14 16:37:37 -0700519 storage->GetInt(id, kStorageConnectionId, &connection_id_);
Peter Qiua89154b2014-05-23 15:45:42 -0700520 storage->GetBool(id, kStorageDNSAutoFallback, &is_dns_auto_fallback_allowed_);
Peter Qiud49760e2014-09-19 16:13:42 -0700521 storage->GetBool(id, kStorageLinkMonitorDisabled, &link_monitor_disabled_);
Paul Stewart3fee7e32014-10-15 21:39:29 -0700522 if (!storage->GetBool(id, kStorageManagedCredentials,
523 &managed_credentials_)) {
524 managed_credentials_ = false;
525 }
Paul Stewartdded0072013-10-24 12:38:54 -0700526
Paul Stewart1062d9d2012-04-27 10:42:27 -0700527 static_ip_parameters_.Load(storage, id);
Chris Masone34af2182011-08-22 11:59:36 -0700528
Rebecca Silberstein57776902014-09-15 21:43:02 -0700529 // Call OnEapCredentialsChanged with kReasonCredentialsLoaded to avoid
530 // resetting the has_ever_connected value.
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700531 if (mutable_eap()) {
532 mutable_eap()->Load(storage, id);
Rebecca Silberstein57776902014-09-15 21:43:02 -0700533 OnEapCredentialsChanged(kReasonCredentialsLoaded);
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700534 }
535
Paul Stewart2eee6132014-05-09 13:33:26 -0700536 ClearExplicitlyDisconnected();
Paul Stewarta41e38d2011-11-11 07:47:29 -0800537
Rebecca Silberstein73dd0dc2014-08-07 16:44:23 -0700538 // Read has_ever_connected_ value from stored profile
539 // now that the credentials have been loaded.
540 storage->GetBool(id, kStorageHasEverConnected, &has_ever_connected_);
541
Chris Masone34af2182011-08-22 11:59:36 -0700542 return true;
Darin Petkovba40dd32011-07-11 20:06:39 -0700543}
544
Paul Stewart65512e12012-03-26 18:01:08 -0700545bool Service::Unload() {
Paul Stewart7fb09382012-07-18 17:32:27 -0700546 auto_connect_ = IsAutoConnectByDefault();
Paul Stewart2da34c02013-10-17 15:28:56 -0700547 retain_auto_connect_ = false;
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800548 check_portal_ = kCheckPortalAuto;
Paul Stewart2eee6132014-05-09 13:33:26 -0700549 ClearExplicitlyDisconnected();
Paul Stewarte7cce8f2012-09-11 10:56:38 -0700550 guid_ = "";
Paul Stewart88769de2012-09-21 13:14:36 -0700551 has_ever_connected_ = false;
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800552 priority_ = kPriorityNone;
Paul Stewartd9c7cfc2015-01-06 14:26:22 -0800553 priority_within_technology_ = kPriorityNone;
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800554 proxy_config_ = "";
555 save_credentials_ = true;
556 ui_data_ = "";
Peter Qiua89154b2014-05-23 15:45:42 -0700557 connection_id_ = 0;
558 is_dns_auto_fallback_allowed_ = false;
Peter Qiud49760e2014-09-19 16:13:42 -0700559 link_monitor_disabled_ = false;
Paul Stewart3fee7e32014-10-15 21:39:29 -0700560 managed_credentials_ = false;
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700561 if (mutable_eap()) {
562 mutable_eap()->Reset();
563 }
564 ClearEAPCertification();
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800565
Wade Guthrie9e0c2502012-04-19 15:26:40 -0700566 Error error; // Ignored.
Samuel Tan0d061192014-07-07 15:45:15 -0700567 Disconnect(&error, __func__);
Paul Stewart65512e12012-03-26 18:01:08 -0700568 return false;
Paul Stewarta41e38d2011-11-11 07:47:29 -0800569}
570
Albert Chaulk0e1cdea2013-02-27 15:32:55 -0800571void Service::Remove(Error */*error*/) {
Paul Stewartd3d03882013-08-29 15:43:42 -0700572 manager()->RemoveService(this);
573 // |this| may no longer be valid now.
Albert Chaulk0e1cdea2013-02-27 15:32:55 -0800574}
575
Chris Masone9d779932011-08-25 16:33:41 -0700576bool Service::Save(StoreInterface *storage) {
577 const string id = GetStorageIdentifier();
Chris Masone34af2182011-08-22 11:59:36 -0700578
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200579 storage->SetString(id, kStorageType, GetTechnologyString());
Paul Stewart2706aaf2011-12-14 16:44:04 -0800580
Paul Stewart2da34c02013-10-17 15:28:56 -0700581 if (retain_auto_connect_) {
582 storage->SetBool(id, kStorageAutoConnect, auto_connect_);
583 } else {
584 storage->DeleteKey(id, kStorageAutoConnect);
585 }
586
587 // Remove this legacy flag.
588 storage->DeleteKey(id, kStorageFavorite);
589
Chris Masone34af2182011-08-22 11:59:36 -0700590 if (check_portal_ == kCheckPortalAuto) {
591 storage->DeleteKey(id, kStorageCheckPortal);
592 } else {
593 storage->SetString(id, kStorageCheckPortal, check_portal_);
594 }
Paul Stewart2da34c02013-10-17 15:28:56 -0700595
mukesh agrawalcf24a242012-05-21 16:46:11 -0700596 SaveString(storage, id, kStorageGUID, guid_, false, true);
597 storage->SetBool(id, kStorageHasEverConnected, has_ever_connected_);
mukesh agrawald835b202011-10-07 15:26:47 -0700598 storage->SetString(id, kStorageName, friendly_name_);
Chris Masone34af2182011-08-22 11:59:36 -0700599 if (priority_ != kPriorityNone) {
600 storage->SetInt(id, kStoragePriority, priority_);
601 } else {
602 storage->DeleteKey(id, kStoragePriority);
603 }
Paul Stewartd9c7cfc2015-01-06 14:26:22 -0800604 if (priority_within_technology_ != kPriorityNone) {
605 storage->SetInt(id, kStoragePriorityWithinTechnology,
606 priority_within_technology_);
607 } else {
608 storage->DeleteKey(id, kStoragePriorityWithinTechnology);
609 }
Paul Stewart987e71e2011-12-05 09:45:06 -0800610 SaveString(storage, id, kStorageProxyConfig, proxy_config_, false, true);
Darin Petkov0debec02013-01-22 10:40:05 +0100611 storage->SetBool(id, kStorageSaveCredentials, save_credentials_);
Paul Stewart987e71e2011-12-05 09:45:06 -0800612 SaveString(storage, id, kStorageUIData, ui_data_, false, true);
Chris Masone34af2182011-08-22 11:59:36 -0700613
Peter Qiu9d581932014-04-14 16:37:37 -0700614 storage->SetInt(id, kStorageConnectionId, connection_id_);
Peter Qiua89154b2014-05-23 15:45:42 -0700615 storage->SetBool(id, kStorageDNSAutoFallback, is_dns_auto_fallback_allowed_);
Peter Qiud49760e2014-09-19 16:13:42 -0700616 storage->SetBool(id, kStorageLinkMonitorDisabled, link_monitor_disabled_);
Paul Stewart3fee7e32014-10-15 21:39:29 -0700617 storage->SetBool(id, kStorageManagedCredentials, managed_credentials_);
Paul Stewartdded0072013-10-24 12:38:54 -0700618
Paul Stewart1062d9d2012-04-27 10:42:27 -0700619 static_ip_parameters_.Save(storage, id);
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700620 if (eap()) {
621 eap()->Save(storage, id, save_credentials_);
622 }
Chris Masone34af2182011-08-22 11:59:36 -0700623 return true;
624}
625
Gary Moraind93615e2012-04-27 11:50:03 -0700626void Service::SaveToCurrentProfile() {
627 // Some unittests do not specify a manager.
628 if (manager()) {
629 manager()->SaveServiceToProfile(this);
630 }
Thieu Led4e9e552012-02-16 16:26:07 -0800631}
632
Paul Stewartcb59fed2012-03-21 21:14:46 -0700633void Service::Configure(const KeyValueStore &args, Error *error) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700634 SLOG(this, 5) << "Configuring bool properties:";
Paul Stewart99dc9f32013-06-27 07:39:25 -0700635 for (const auto &bool_it : args.bool_properties()) {
636 if (ContainsKey(parameters_ignored_for_configure_, bool_it.first)) {
Paul Stewartcb59fed2012-03-21 21:14:46 -0700637 continue;
638 }
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700639 SLOG(this, 5) << " " << bool_it.first;
Paul Stewartcb59fed2012-03-21 21:14:46 -0700640 Error set_error;
Paul Stewart99dc9f32013-06-27 07:39:25 -0700641 store_.SetBoolProperty(bool_it.first, bool_it.second, &set_error);
Paul Stewartcb59fed2012-03-21 21:14:46 -0700642 if (error->IsSuccess() && set_error.IsFailure()) {
643 error->CopyFrom(set_error);
644 }
645 }
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700646 SLOG(this, 5) << "Configuring int32_t properties:";
Paul Stewart99dc9f32013-06-27 07:39:25 -0700647 for (const auto &int_it : args.int_properties()) {
648 if (ContainsKey(parameters_ignored_for_configure_, int_it.first)) {
Paul Stewartcb59fed2012-03-21 21:14:46 -0700649 continue;
650 }
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700651 SLOG(this, 5) << " " << int_it.first;
Paul Stewartcb59fed2012-03-21 21:14:46 -0700652 Error set_error;
Paul Stewart99dc9f32013-06-27 07:39:25 -0700653 store_.SetInt32Property(int_it.first, int_it.second, &set_error);
Paul Stewart99dc9f32013-06-27 07:39:25 -0700654 if (error->IsSuccess() && set_error.IsFailure()) {
655 error->CopyFrom(set_error);
656 }
657 }
Paul Stewartbb833562015-01-21 23:30:46 -0800658 SLOG(this, 5) << "Configuring key value store properties:";
659 for (const auto &key_value_it : args.key_value_store_properties()) {
660 if (ContainsKey(parameters_ignored_for_configure_, key_value_it.first)) {
661 continue;
662 }
663 SLOG(this, 5) << " " << key_value_it.first;
664 Error set_error;
665 store_.SetKeyValueStoreProperty(key_value_it.first,
666 key_value_it.second, &set_error);
667 if (error->IsSuccess() && set_error.IsFailure()) {
668 error->CopyFrom(set_error);
669 }
670 }
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700671 SLOG(this, 5) << "Configuring string properties:";
Paul Stewart99dc9f32013-06-27 07:39:25 -0700672 for (const auto &string_it : args.string_properties()) {
673 if (ContainsKey(parameters_ignored_for_configure_, string_it.first)) {
674 continue;
675 }
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700676 SLOG(this, 5) << " " << string_it.first;
Paul Stewart99dc9f32013-06-27 07:39:25 -0700677 Error set_error;
678 store_.SetStringProperty(string_it.first, string_it.second, &set_error);
Paul Stewart99dc9f32013-06-27 07:39:25 -0700679 if (error->IsSuccess() && set_error.IsFailure()) {
680 error->CopyFrom(set_error);
681 }
682 }
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700683 SLOG(this, 5) << "Configuring string array properties:";
Paul Stewart99dc9f32013-06-27 07:39:25 -0700684 for (const auto &strings_it : args.strings_properties()) {
685 if (ContainsKey(parameters_ignored_for_configure_, strings_it.first)) {
686 continue;
687 }
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700688 SLOG(this, 5) << " " << strings_it.first;
Paul Stewart99dc9f32013-06-27 07:39:25 -0700689 Error set_error;
690 store_.SetStringsProperty(strings_it.first, strings_it.second, &set_error);
Paul Stewartcb59fed2012-03-21 21:14:46 -0700691 if (error->IsSuccess() && set_error.IsFailure()) {
692 error->CopyFrom(set_error);
693 }
694 }
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700695 SLOG(this, 5) << "Configuring string map properties:";
Arman Uguray631c7e42013-07-30 16:41:12 -0700696 for (const auto &stringmap_it : args.stringmap_properties()) {
697 if (ContainsKey(parameters_ignored_for_configure_, stringmap_it.first)) {
698 continue;
699 }
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700700 SLOG(this, 5) << " " << stringmap_it.first;
Arman Uguray631c7e42013-07-30 16:41:12 -0700701 Error set_error;
702 store_.SetStringmapProperty(
703 stringmap_it.first, stringmap_it.second, &set_error);
Arman Uguray631c7e42013-07-30 16:41:12 -0700704 if (error->IsSuccess() && set_error.IsFailure()) {
705 error->CopyFrom(set_error);
706 }
707 }
Paul Stewartcb59fed2012-03-21 21:14:46 -0700708}
709
Paul Stewart7a20aa42013-01-17 12:21:41 -0800710bool Service::DoPropertiesMatch(const KeyValueStore &args) const {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700711 SLOG(this, 5) << "Checking bool properties:";
Alex Vakulenko8a532292014-06-16 17:18:44 -0700712 for (const auto &bool_it : args.bool_properties()) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700713 SLOG(this, 5) << " " << bool_it.first;
Paul Stewart7a20aa42013-01-17 12:21:41 -0800714 Error get_error;
715 bool value;
Paul Stewart99dc9f32013-06-27 07:39:25 -0700716 if (!store_.GetBoolProperty(bool_it.first, &value, &get_error) ||
717 value != bool_it.second) {
Paul Stewart7a20aa42013-01-17 12:21:41 -0800718 return false;
719 }
720 }
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700721 SLOG(this, 5) << "Checking int32_t properties:";
Paul Stewart99dc9f32013-06-27 07:39:25 -0700722 for (const auto &int_it : args.int_properties()) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700723 SLOG(this, 5) << " " << int_it.first;
Paul Stewart7a20aa42013-01-17 12:21:41 -0800724 Error get_error;
Ben Chan7fab8972014-08-10 17:14:46 -0700725 int32_t value;
Paul Stewart99dc9f32013-06-27 07:39:25 -0700726 if (!store_.GetInt32Property(int_it.first, &value, &get_error) ||
727 value != int_it.second) {
728 return false;
729 }
730 }
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700731 SLOG(this, 5) << "Checking string properties:";
Paul Stewart99dc9f32013-06-27 07:39:25 -0700732 for (const auto &string_it : args.string_properties()) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700733 SLOG(this, 5) << " " << string_it.first;
Paul Stewart99dc9f32013-06-27 07:39:25 -0700734 Error get_error;
735 string value;
736 if (!store_.GetStringProperty(string_it.first, &value, &get_error) ||
737 value != string_it.second) {
738 return false;
739 }
740 }
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700741 SLOG(this, 5) << "Checking string array properties:";
Paul Stewart99dc9f32013-06-27 07:39:25 -0700742 for (const auto &strings_it : args.strings_properties()) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700743 SLOG(this, 5) << " " << strings_it.first;
Paul Stewart99dc9f32013-06-27 07:39:25 -0700744 Error get_error;
745 vector<string> value;
746 if (!store_.GetStringsProperty(strings_it.first, &value, &get_error) ||
747 value != strings_it.second) {
Paul Stewart7a20aa42013-01-17 12:21:41 -0800748 return false;
749 }
750 }
Paul Stewartbb833562015-01-21 23:30:46 -0800751 SLOG(this, 5) << "Checking key value store properties:";
752 for (const auto &key_value_it : args.key_value_store_properties()) {
753 SLOG(this, 5) << " " << key_value_it.first;
754 Error get_error;
755 KeyValueStore value;
756 if (!store_.GetKeyValueStoreProperty(
757 key_value_it.first, &value, &get_error) ||
758 !value.Equals(key_value_it.second)) {
759 return false;
760 }
761 }
Paul Stewart7a20aa42013-01-17 12:21:41 -0800762 return true;
763}
764
Paul Stewart10ccbb32012-04-26 15:59:30 -0700765bool Service::IsRemembered() const {
766 return profile_ && !manager_->IsServiceEphemeral(this);
767}
768
Paul Stewartdf3c0a82012-11-09 15:54:33 -0800769bool Service::IsDependentOn(const ServiceRefPtr &b) const {
Paul Stewartcd7f5852013-03-27 13:54:23 -0700770 if (!connection_ || !b || !b->connection()) {
Paul Stewartdf3c0a82012-11-09 15:54:33 -0800771 return false;
772 }
773 return connection_->GetLowerConnection() == b->connection();
774}
775
Paul Stewart2da34c02013-10-17 15:28:56 -0700776void Service::EnableAndRetainAutoConnect() {
777 if (retain_auto_connect_) {
mukesh agrawal00917ce2011-11-22 23:56:55 +0000778 // We do not want to clobber the value of auto_connect_ (it may
779 // be user-set). So return early.
780 return;
781 }
782
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700783 SetAutoConnect(true);
Paul Stewart2da34c02013-10-17 15:28:56 -0700784 RetainAutoConnect();
mukesh agrawal00917ce2011-11-22 23:56:55 +0000785}
786
Darin Petkov5eb05422012-05-11 15:45:25 +0200787void Service::SetConnection(const ConnectionRefPtr &connection) {
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800788 if (connection.get()) {
Paul Stewart1e3bc4962012-09-14 12:20:22 -0700789 // TODO(pstew): Make this function testable by using a factory here.
Paul Stewartee6b3d72013-07-12 16:07:51 -0700790 // http://crbug.com/216664
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800791 http_proxy_.reset(new HTTPProxy(connection));
Darin Petkov5eb05422012-05-11 15:45:25 +0200792 http_proxy_->Start(dispatcher_, sockets_.get());
Paul Stewart7f5d9c02013-12-03 18:26:00 -0800793 Error unused_error;
794 connection->set_tethering(GetTethering(&unused_error));
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800795 } else {
796 http_proxy_.reset();
Paul Stewartdef189e2012-08-02 20:12:09 -0700797 static_ip_parameters_.ClearSavedParameters();
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800798 }
799 connection_ = connection;
Peter Qiua89154b2014-05-23 15:45:42 -0700800 NotifyIPConfigChanges();
801}
802
803void Service::NotifyIPConfigChanges() {
Paul Stewart1e3bc4962012-09-14 12:20:22 -0700804 Error error;
805 string ipconfig = GetIPConfigRpcIdentifier(&error);
806 if (error.IsSuccess()) {
Ben Chan39a7beb2013-09-21 11:28:00 -0700807 adaptor_->EmitRpcIdentifierChanged(kIPConfigProperty, ipconfig);
Paul Stewart1e3bc4962012-09-14 12:20:22 -0700808 }
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800809}
810
Gaurav Shah10109f22011-11-11 20:16:22 -0800811bool Service::Is8021xConnectable() const {
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700812 return eap() && eap()->IsConnectable();
Gaurav Shah10109f22011-11-11 20:16:22 -0800813}
814
Paul Stewartbc6e7392012-05-24 07:07:48 -0700815bool Service::AddEAPCertification(const string &name, size_t depth) {
816 if (depth >= kEAPMaxCertificationElements) {
817 LOG(WARNING) << "Ignoring certification " << name
818 << " because depth " << depth
819 << " exceeds our maximum of "
820 << kEAPMaxCertificationElements;
821 return false;
822 }
823
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700824 if (depth >= remote_certification_.size()) {
825 remote_certification_.resize(depth + 1);
826 } else if (name == remote_certification_[depth]) {
Paul Stewartbc6e7392012-05-24 07:07:48 -0700827 return true;
828 }
829
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700830 remote_certification_[depth] = name;
Paul Stewartbc6e7392012-05-24 07:07:48 -0700831 LOG(INFO) << "Received certification for "
832 << name
833 << " at depth "
834 << depth;
835 return true;
836}
837
838void Service::ClearEAPCertification() {
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700839 remote_certification_.clear();
Paul Stewartbc6e7392012-05-24 07:07:48 -0700840}
841
Paul Stewart316acef2014-05-29 18:40:48 -0700842bool Service::HasStaticIPAddress() const {
843 return static_ip_parameters().ContainsAddress();
844}
845
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700846void Service::SetAutoConnect(bool connect) {
847 if (auto_connect() == connect) {
848 return;
849 }
850 auto_connect_ = connect;
Ben Chan923a5022013-09-20 11:23:23 -0700851 adaptor_->EmitBoolChanged(kAutoConnectProperty, auto_connect());
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700852}
853
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700854void Service::SetEapCredentials(EapCredentials *eap) {
855 // This operation must be done at most once for the lifetime of the service.
856 CHECK(eap && !eap_);
857
858 eap_.reset(eap);
859 eap_->InitPropertyStore(mutable_store());
Gaurav Shah10109f22011-11-11 20:16:22 -0800860}
861
mukesh agrawal00917ce2011-11-22 23:56:55 +0000862// static
Gaurav Shahc6d6c722011-11-17 18:59:39 -0800863const char *Service::ConnectFailureToString(const ConnectFailure &state) {
864 switch (state) {
865 case kFailureUnknown:
866 return "Unknown";
Paul Stewartf2d60912012-07-15 08:37:30 -0700867 case kFailureAAA:
Ben Chan923a5022013-09-20 11:23:23 -0700868 return kErrorAaaFailed;
Paul Stewartf2d60912012-07-15 08:37:30 -0700869 case kFailureActivation:
Ben Chan923a5022013-09-20 11:23:23 -0700870 return kErrorActivationFailed;
Paul Stewartf2d60912012-07-15 08:37:30 -0700871 case kFailureBadPassphrase:
Ben Chan923a5022013-09-20 11:23:23 -0700872 return kErrorBadPassphrase;
Paul Stewartf2d60912012-07-15 08:37:30 -0700873 case kFailureBadWEPKey:
Ben Chan923a5022013-09-20 11:23:23 -0700874 return kErrorBadWEPKey;
Paul Stewartf2d60912012-07-15 08:37:30 -0700875 case kFailureConnect:
Ben Chan923a5022013-09-20 11:23:23 -0700876 return kErrorConnectFailed;
Paul Stewartf2d60912012-07-15 08:37:30 -0700877 case kFailureDNSLookup:
Ben Chan923a5022013-09-20 11:23:23 -0700878 return kErrorDNSLookupFailed;
Paul Stewartf2d60912012-07-15 08:37:30 -0700879 case kFailureDHCP:
Ben Chan923a5022013-09-20 11:23:23 -0700880 return kErrorDhcpFailed;
Darin Petkov1c049c72013-03-21 13:15:45 +0100881 case kFailureEAPAuthentication:
Ben Chan39a7beb2013-09-21 11:28:00 -0700882 return kErrorEapAuthenticationFailed;
Darin Petkov1c049c72013-03-21 13:15:45 +0100883 case kFailureEAPLocalTLS:
Ben Chan39a7beb2013-09-21 11:28:00 -0700884 return kErrorEapLocalTlsFailed;
Darin Petkov1c049c72013-03-21 13:15:45 +0100885 case kFailureEAPRemoteTLS:
Ben Chan39a7beb2013-09-21 11:28:00 -0700886 return kErrorEapRemoteTlsFailed;
Paul Stewartf2d60912012-07-15 08:37:30 -0700887 case kFailureHTTPGet:
Ben Chan923a5022013-09-20 11:23:23 -0700888 return kErrorHTTPGetFailed;
Darin Petkov1c049c72013-03-21 13:15:45 +0100889 case kFailureInternal:
Ben Chan923a5022013-09-20 11:23:23 -0700890 return kErrorInternal;
Darin Petkov1c049c72013-03-21 13:15:45 +0100891 case kFailureIPSecCertAuth:
Ben Chan923a5022013-09-20 11:23:23 -0700892 return kErrorIpsecCertAuthFailed;
Darin Petkov1c049c72013-03-21 13:15:45 +0100893 case kFailureIPSecPSKAuth:
Ben Chan923a5022013-09-20 11:23:23 -0700894 return kErrorIpsecPskAuthFailed;
Gaurav Shahc6d6c722011-11-17 18:59:39 -0800895 case kFailureNeedEVDO:
Ben Chan923a5022013-09-20 11:23:23 -0700896 return kErrorNeedEvdo;
Gaurav Shahc6d6c722011-11-17 18:59:39 -0800897 case kFailureNeedHomeNetwork:
Ben Chan923a5022013-09-20 11:23:23 -0700898 return kErrorNeedHomeNetwork;
Paul Stewartf2d60912012-07-15 08:37:30 -0700899 case kFailureOTASP:
Ben Chan923a5022013-09-20 11:23:23 -0700900 return kErrorOtaspFailed;
Paul Stewartf2d60912012-07-15 08:37:30 -0700901 case kFailureOutOfRange:
Ben Chan923a5022013-09-20 11:23:23 -0700902 return kErrorOutOfRange;
Paul Stewartf2d60912012-07-15 08:37:30 -0700903 case kFailurePinMissing:
Ben Chan923a5022013-09-20 11:23:23 -0700904 return kErrorPinMissing;
Paul Stewartf2d60912012-07-15 08:37:30 -0700905 case kFailurePPPAuth:
Ben Chan923a5022013-09-20 11:23:23 -0700906 return kErrorPppAuthFailed;
Thieu Le48e6d6d2011-12-06 00:40:27 +0000907 case kFailureMax:
Darin Petkov1c049c72013-03-21 13:15:45 +0100908 NOTREACHED();
Gaurav Shahc6d6c722011-11-17 18:59:39 -0800909 }
910 return "Invalid";
911}
912
913// static
914const char *Service::ConnectStateToString(const ConnectState &state) {
915 switch (state) {
916 case kStateUnknown:
917 return "Unknown";
918 case kStateIdle:
919 return "Idle";
920 case kStateAssociating:
921 return "Associating";
922 case kStateConfiguring:
923 return "Configuring";
924 case kStateConnected:
925 return "Connected";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000926 case kStatePortal:
927 return "Portal";
Gaurav Shahc6d6c722011-11-17 18:59:39 -0800928 case kStateFailure:
929 return "Failure";
930 case kStateOnline:
931 return "Online";
932 }
933 return "Invalid";
934}
935
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200936string Service::GetTechnologyString() const {
Gaurav Shah435de2c2011-11-17 19:01:07 -0800937 return Technology::NameFromIdentifier(technology());
938}
939
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200940string Service::CalculateTechnology(Error */*error*/) {
941 return GetTechnologyString();
942}
943
Darin Petkov385b9bc2012-12-03 15:25:05 +0100944void Service::NoteDisconnectEvent() {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700945 SLOG(this, 2) << __func__;
Darin Petkovcb0b5662012-12-13 09:59:44 +0100946 // Ignore the event if it's user-initiated explicit disconnect.
Darin Petkov385b9bc2012-12-03 15:25:05 +0100947 if (explicitly_disconnected_) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700948 SLOG(this, 2) << "Explicit disconnect ignored.";
Darin Petkovcb0b5662012-12-13 09:59:44 +0100949 return;
950 }
951 // Ignore the event if manager is not running (e.g., service disconnects on
952 // shutdown).
953 if (!manager_->running()) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700954 SLOG(this, 2) << "Disconnect while manager stopped ignored.";
Darin Petkovcb0b5662012-12-13 09:59:44 +0100955 return;
956 }
Daniel Eratfac09532014-04-17 20:25:59 -0700957 // Ignore the event if the system is suspending.
Darin Petkovcb0b5662012-12-13 09:59:44 +0100958 PowerManager *power_manager = manager_->power_manager();
Daniel Eratfac09532014-04-17 20:25:59 -0700959 if (!power_manager || power_manager->suspending()) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700960 SLOG(this, 2) << "Disconnect in transitional power state ignored.";
Darin Petkov385b9bc2012-12-03 15:25:05 +0100961 return;
962 }
Paul Stewart483e4722012-12-18 10:23:17 -0800963 int period = 0;
Darin Petkov385b9bc2012-12-03 15:25:05 +0100964 size_t threshold = 0;
Samuel Tan07dfabc2015-01-20 15:10:39 -0800965 EventHistory *events = nullptr;
Darin Petkovc8d91e52013-01-21 11:43:47 +0100966 // Sometimes services transition to Idle before going into a failed state so
967 // take into account the last non-idle state.
968 ConnectState state = state_ == kStateIdle ? previous_state_ : state_;
969 if (IsConnectedState(state)) {
Darin Petkovcb0b5662012-12-13 09:59:44 +0100970 LOG(INFO) << "Noting an unexpected connection drop.";
Paul Stewart483e4722012-12-18 10:23:17 -0800971 period = kDisconnectsMonitorSeconds;
Darin Petkov385b9bc2012-12-03 15:25:05 +0100972 threshold = kReportDisconnectsThreshold;
973 events = &disconnects_;
Darin Petkovc8d91e52013-01-21 11:43:47 +0100974 } else if (IsConnectingState(state)) {
Darin Petkovcb0b5662012-12-13 09:59:44 +0100975 LOG(INFO) << "Noting an unexpected failure to connect.";
Paul Stewart483e4722012-12-18 10:23:17 -0800976 period = kMisconnectsMonitorSeconds;
Darin Petkov385b9bc2012-12-03 15:25:05 +0100977 threshold = kReportMisconnectsThreshold;
978 events = &misconnects_;
979 } else {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -0700980 SLOG(this, 2)
Darin Petkovcb0b5662012-12-13 09:59:44 +0100981 << "Not connected or connecting, state transition ignored.";
Darin Petkov385b9bc2012-12-03 15:25:05 +0100982 return;
983 }
Samuel Tan07dfabc2015-01-20 15:10:39 -0800984 events->RecordEventAndExpireEventsBefore(period, false);
985 if (events->Size() >= threshold) {
Darin Petkov385b9bc2012-12-03 15:25:05 +0100986 diagnostics_reporter_->OnConnectivityEvent();
987 }
988}
989
Peter Qiudc4e0992014-05-01 10:02:52 -0700990void Service::ReportUserInitiatedConnectionResult(ConnectState state) {
991 // Report stats for wifi only for now.
992 if (technology_ != Technology::kWifi)
993 return;
994
995 int result;
996 switch (state) {
997 case kStateConnected:
998 result = Metrics::kUserInitiatedConnectionResultSuccess;
999 break;
1000 case kStateFailure:
1001 result = Metrics::kUserInitiatedConnectionResultFailure;
Peter Qiud87179e2014-07-10 18:29:22 -07001002 metrics_->NotifyUserInitiatedConnectionFailureReason(
1003 Metrics::kMetricWifiUserInitiatedConnectionFailureReason, failure_);
Peter Qiudc4e0992014-05-01 10:02:52 -07001004 break;
1005 case kStateIdle:
1006 // This assumes the device specific class (wifi, cellular) will advance
1007 // the service's state from idle to other state after connection attempt
1008 // is initiated for the given service.
1009 result = Metrics::kUserInitiatedConnectionResultAborted;
1010 break;
1011 default:
1012 return;
1013 }
1014
1015 metrics_->NotifyUserInitiatedConnectionResult(
1016 Metrics::kMetricWifiUserInitiatedConnectionResult, result);
1017}
1018
Paul Stewart483e4722012-12-18 10:23:17 -08001019bool Service::HasRecentConnectionIssues() {
Samuel Tan07dfabc2015-01-20 15:10:39 -08001020 disconnects_.ExpireEventsBefore(kDisconnectsMonitorSeconds, false);
1021 misconnects_.ExpireEventsBefore(kMisconnectsMonitorSeconds, false);
1022 return !disconnects_.Empty() || !misconnects_.Empty();
Paul Stewart483e4722012-12-18 10:23:17 -08001023}
1024
Jason Glasgowb5790052012-01-27 01:03:52 -05001025// static
Paul Stewart22aa71b2011-09-16 12:15:11 -07001026bool Service::DecideBetween(int a, int b, bool *decision) {
1027 if (a == b)
1028 return false;
1029 *decision = (a > b);
1030 return true;
1031}
1032
Ben Chan7fab8972014-08-10 17:14:46 -07001033uint16_t Service::SecurityLevel() {
mukesh agrawal43970a22013-02-15 16:00:07 -08001034 return (crypto_algorithm_ << 2) | (key_rotation_ << 1) | endpoint_auth_;
1035}
1036
mukesh agrawal00917ce2011-11-22 23:56:55 +00001037// static
Rebecca Silberstein6d4836b2014-07-16 14:28:28 -07001038bool Service::Compare(Manager *manager,
1039 ServiceRefPtr a,
Paul Stewart22aa71b2011-09-16 12:15:11 -07001040 ServiceRefPtr b,
Paul Stewart39db5ca2013-03-18 14:15:17 -07001041 bool compare_connectivity_state,
mukesh agrawalddc378f2012-02-17 18:26:20 -08001042 const vector<Technology::Identifier> &tech_order,
1043 const char **reason) {
Paul Stewart22aa71b2011-09-16 12:15:11 -07001044 bool ret;
1045
Paul Stewart39db5ca2013-03-18 14:15:17 -07001046 if (compare_connectivity_state && a->state() != b->state()) {
Paul Stewart22aa71b2011-09-16 12:15:11 -07001047 if (DecideBetween(a->IsConnected(), b->IsConnected(), &ret)) {
mukesh agrawalddc378f2012-02-17 18:26:20 -08001048 *reason = kServiceSortIsConnected;
Paul Stewart22aa71b2011-09-16 12:15:11 -07001049 return ret;
1050 }
1051
Paul Stewarta121c442012-06-09 14:12:58 -07001052 if (DecideBetween(!a->IsPortalled(), !b->IsPortalled(), &ret)) {
1053 *reason = kServiceSortIsPortalled;
1054 return ret;
1055 }
Paul Stewart22aa71b2011-09-16 12:15:11 -07001056
1057 if (DecideBetween(a->IsConnecting(), b->IsConnecting(), &ret)) {
mukesh agrawalddc378f2012-02-17 18:26:20 -08001058 *reason = kServiceSortIsConnecting;
Paul Stewart22aa71b2011-09-16 12:15:11 -07001059 return ret;
1060 }
mukesh agrawal8a3188d2011-12-01 20:56:44 +00001061
1062 if (DecideBetween(!a->IsFailed(), !b->IsFailed(), &ret)) {
mukesh agrawalddc378f2012-02-17 18:26:20 -08001063 *reason = kServiceSortIsFailed;
mukesh agrawal8a3188d2011-12-01 20:56:44 +00001064 return ret;
1065 }
Paul Stewart22aa71b2011-09-16 12:15:11 -07001066 }
1067
Darin Petkov2f903b32012-04-18 12:56:43 +02001068 if (DecideBetween(a->connectable(), b->connectable(), &ret)) {
1069 *reason = kServiceSortConnectable;
1070 return ret;
1071 }
1072
Paul Stewartdf3c0a82012-11-09 15:54:33 -08001073 if (DecideBetween(a->IsDependentOn(b), b->IsDependentOn(a), &ret)) {
1074 *reason = kServiceSortDependency;
1075 return ret;
1076 }
1077
Darin Petkov2f903b32012-04-18 12:56:43 +02001078 // Ignore the auto-connect property if both services are connected
1079 // already. This allows connected non-autoconnectable VPN services to be
1080 // sorted higher than other connected services based on technology order.
1081 if (!a->IsConnected() &&
1082 DecideBetween(a->auto_connect(), b->auto_connect(), &ret)) {
1083 *reason = kServiceSortAutoConnect;
1084 return ret;
1085 }
1086
Paul Stewart3fee7e32014-10-15 21:39:29 -07001087 if (DecideBetween(a->has_ever_connected() || a->managed_credentials_,
1088 b->has_ever_connected() || b->managed_credentials_,
1089 &ret)) {
Paul Stewart2da34c02013-10-17 15:28:56 -07001090 *reason = kServiceSortHasEverConnected;
Darin Petkov2f903b32012-04-18 12:56:43 +02001091 return ret;
1092 }
1093
1094 if (DecideBetween(a->priority(), b->priority(), &ret)) {
1095 *reason = kServiceSortPriority;
Paul Stewart22aa71b2011-09-16 12:15:11 -07001096 return ret;
1097 }
1098
1099 // TODO(pstew): Below this point we are making value judgements on
1100 // services that are not related to anything intrinsic or
1101 // user-specified. These heuristics should be richer (contain
1102 // historical information, for example) and be subject to user
1103 // customization.
Paul Stewart22aa71b2011-09-16 12:15:11 -07001104 for (vector<Technology::Identifier>::const_iterator it = tech_order.begin();
1105 it != tech_order.end();
1106 ++it) {
Joshua Kroll053fa822012-06-05 09:50:43 -07001107 if (DecideBetween(a->technology() == *it, b->technology() == *it, &ret)) {
mukesh agrawalddc378f2012-02-17 18:26:20 -08001108 *reason = kServiceSortTechnology;
Paul Stewart22aa71b2011-09-16 12:15:11 -07001109 return ret;
mukesh agrawalddc378f2012-02-17 18:26:20 -08001110 }
Paul Stewart22aa71b2011-09-16 12:15:11 -07001111 }
1112
Paul Stewartd9c7cfc2015-01-06 14:26:22 -08001113 if (DecideBetween(a->priority_within_technology(),
1114 b->priority_within_technology(), &ret)) {
1115 *reason = kServiceSortPriorityWithinTechnology;
1116 return ret;
1117 }
1118
Rebecca Silberstein6d4836b2014-07-16 14:28:28 -07001119 if (DecideBetween(a->SecurityLevel(), b->SecurityLevel(), &ret)) {
1120 *reason = kServiceSortSecurity;
1121 return ret;
1122 }
1123
1124 // If the profiles for the two services are different,
1125 // we want to pick the highest priority one. The
1126 // ephemeral profile is explicitly tested for since it is not
1127 // listed in the manager profiles_ list.
1128 if (a->profile() != b->profile()) {
1129 *reason = kServiceSortProfileOrder;
1130 if (manager->IsServiceEphemeral(b)) {
1131 return true;
1132 } else if (manager->IsServiceEphemeral(a)) {
1133 return false;
1134 } else if (manager->IsProfileBefore(b->profile(), a->profile())) {
1135 return true;
1136 } else {
1137 return false;
1138 }
1139 }
1140
1141 if (DecideBetween(a->strength(), b->strength(), &ret)) {
1142 *reason = kServiceSortEtc;
Paul Stewart22aa71b2011-09-16 12:15:11 -07001143 return ret;
1144 }
1145
mukesh agrawale37ad322013-10-08 16:33:56 -07001146 *reason = kServiceSortSerialNumber;
1147 return a->serial_number_ < b->serial_number_;
Paul Stewart22aa71b2011-09-16 12:15:11 -07001148}
1149
Chris Masone34af2182011-08-22 11:59:36 -07001150const ProfileRefPtr &Service::profile() const { return profile_; }
1151
1152void Service::set_profile(const ProfileRefPtr &p) { profile_ = p; }
1153
Philipp Neubeck79173602012-11-13 21:10:09 +01001154void Service::SetProfile(const ProfileRefPtr &p) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -07001155 SLOG(this, 2) << "SetProfile from "
1156 << (profile_ ? profile_->GetFriendlyName() : "(none)")
1157 << " to " << (p ? p->GetFriendlyName() : "(none)")
1158 << ".";
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001159 if (profile_ == p) {
1160 return;
1161 }
Philipp Neubeck79173602012-11-13 21:10:09 +01001162 profile_ = p;
1163 Error error;
1164 string profile_rpc_id = GetProfileRpcId(&error);
1165 if (!error.IsSuccess()) {
1166 return;
1167 }
Ben Chan923a5022013-09-20 11:23:23 -07001168 adaptor_->EmitStringChanged(kProfileProperty, profile_rpc_id);
Philipp Neubeck79173602012-11-13 21:10:09 +01001169}
1170
Paul Stewartff14b022012-04-24 20:06:23 -07001171void Service::OnPropertyChanged(const string &property) {
Rebecca Silbersteinc9c31d82014-10-21 15:01:00 -07001172 SLOG(this, 1) << __func__ << " " << property;
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001173 if (Is8021x() && EapCredentials::IsEapAuthenticationProperty(property)) {
Rebecca Silberstein57776902014-09-15 21:43:02 -07001174 OnEapCredentialsChanged(kReasonPropertyUpdate);
Paul Stewart81426132012-05-16 10:05:10 -07001175 }
mukesh agrawalcf24a242012-05-21 16:46:11 -07001176 SaveToProfile();
Ben Chan923a5022013-09-20 11:23:23 -07001177 if ((property == kCheckPortalProperty ||
1178 property == kProxyConfigProperty) &&
Paul Stewartd215af62012-04-24 23:25:50 -07001179 (state_ == kStateConnected ||
1180 state_ == kStatePortal ||
1181 state_ == kStateOnline)) {
1182 manager_->RecheckPortalOnService(this);
1183 }
Paul Stewartff14b022012-04-24 20:06:23 -07001184}
1185
Christopher Wiley0801d192012-09-24 11:57:15 -07001186void Service::OnAfterResume() {
1187 // Forget old autoconnect failures across suspend/resume.
1188 auto_connect_cooldown_milliseconds_ = 0;
1189 reenable_auto_connect_task_.Cancel();
Christopher Wileya4c61ae2012-10-01 11:04:30 -07001190 // Forget if the user disconnected us, we might be able to connect now.
Paul Stewart2eee6132014-05-09 13:33:26 -07001191 ClearExplicitlyDisconnected();
Christopher Wiley0801d192012-09-24 11:57:15 -07001192}
1193
Prathmesh Prabhu64ad2382014-08-26 11:19:30 -07001194void Service::OnDarkResume() {
1195 // Nothing to do in the general case.
1196}
1197
Paul Stewart1cf7eb82013-12-03 19:34:36 -08001198string Service::GetIPConfigRpcIdentifier(Error *error) const {
Paul Stewart10241e32012-04-23 18:15:06 -07001199 if (!connection_) {
1200 error->Populate(Error::kNotFound);
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001201 return DBusAdaptor::kNullPath;
Paul Stewart10241e32012-04-23 18:15:06 -07001202 }
1203
1204 string id = connection_->ipconfig_rpc_identifier();
1205
1206 if (id.empty()) {
1207 // Do not return an empty IPConfig.
1208 error->Populate(Error::kNotFound);
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001209 return DBusAdaptor::kNullPath;
Paul Stewart10241e32012-04-23 18:15:06 -07001210 }
1211
1212 return id;
1213}
1214
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001215void Service::SetConnectable(bool connectable) {
1216 if (connectable_ == connectable)
1217 return;
mukesh agrawal29c13a12011-11-24 00:09:19 +00001218 connectable_ = connectable;
Ben Chan923a5022013-09-20 11:23:23 -07001219 adaptor_->EmitBoolChanged(kConnectableProperty, connectable_);
mukesh agrawal29c13a12011-11-24 00:09:19 +00001220}
1221
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001222void Service::SetConnectableFull(bool connectable) {
Darin Petkovb2ba39f2012-06-06 10:33:43 +02001223 if (connectable_ == connectable) {
1224 return;
1225 }
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001226 SetConnectable(connectable);
Darin Petkovb2ba39f2012-06-06 10:33:43 +02001227 if (manager_->HasService(this)) {
1228 manager_->UpdateService(this);
1229 }
1230}
1231
Darin Petkov58f0b6d2012-06-12 12:52:30 +02001232string Service::GetStateString() const {
Ben Chan923a5022013-09-20 11:23:23 -07001233 // TODO(benchan): We may want to rename shill::kState* to avoid name clashing
1234 // with Service::kState*.
Paul Stewart03e29f72013-09-26 00:49:48 -07001235 switch (state()) {
Gaurav Shahc6d6c722011-11-17 18:59:39 -08001236 case kStateIdle:
Ben Chan923a5022013-09-20 11:23:23 -07001237 return shill::kStateIdle;
Gaurav Shahc6d6c722011-11-17 18:59:39 -08001238 case kStateAssociating:
Ben Chan923a5022013-09-20 11:23:23 -07001239 return shill::kStateAssociation;
Gaurav Shahc6d6c722011-11-17 18:59:39 -08001240 case kStateConfiguring:
Ben Chan923a5022013-09-20 11:23:23 -07001241 return shill::kStateConfiguration;
mukesh agrawalf2f68a52011-09-01 12:15:48 -07001242 case kStateConnected:
Ben Chan923a5022013-09-20 11:23:23 -07001243 return shill::kStateReady;
Gaurav Shahc6d6c722011-11-17 18:59:39 -08001244 case kStateFailure:
Ben Chan923a5022013-09-20 11:23:23 -07001245 return shill::kStateFailure;
Paul Stewart20088d82012-02-16 06:58:55 -08001246 case kStatePortal:
Ben Chan923a5022013-09-20 11:23:23 -07001247 return shill::kStatePortal;
Gaurav Shahc6d6c722011-11-17 18:59:39 -08001248 case kStateOnline:
Ben Chan923a5022013-09-20 11:23:23 -07001249 return shill::kStateOnline;
Gaurav Shahc6d6c722011-11-17 18:59:39 -08001250 case kStateUnknown:
mukesh agrawalf2f68a52011-09-01 12:15:48 -07001251 default:
Gaurav Shahc6d6c722011-11-17 18:59:39 -08001252 return "";
mukesh agrawalf2f68a52011-09-01 12:15:48 -07001253 }
1254}
1255
Darin Petkov58f0b6d2012-06-12 12:52:30 +02001256string Service::CalculateState(Error */*error*/) {
1257 return GetStateString();
1258}
1259
mukesh agrawalbf14e942012-03-02 14:36:34 -08001260bool Service::IsAutoConnectable(const char **reason) const {
Ben Chan8e6b8ef2014-07-14 21:50:18 -07001261 if (manager_->IsTechnologyAutoConnectDisabled(technology_)) {
1262 *reason = kAutoConnTechnologyNotConnectable;
1263 return false;
1264 }
1265
mukesh agrawalbf14e942012-03-02 14:36:34 -08001266 if (!connectable()) {
1267 *reason = kAutoConnNotConnectable;
1268 return false;
1269 }
1270
1271 if (IsConnected()) {
1272 *reason = kAutoConnConnected;
1273 return false;
1274 }
1275
1276 if (IsConnecting()) {
1277 *reason = kAutoConnConnecting;
1278 return false;
1279 }
1280
1281 if (explicitly_disconnected_) {
1282 *reason = kAutoConnExplicitDisconnect;
1283 return false;
1284 }
1285
Christopher Wiley0801d192012-09-24 11:57:15 -07001286 if (!reenable_auto_connect_task_.IsCancelled()) {
1287 *reason = kAutoConnThrottled;
1288 return false;
1289 }
1290
Darin Petkov4cbff5b2013-01-29 16:29:05 +01001291 if (!Technology::IsPrimaryConnectivityTechnology(technology_) &&
Peter Qiu700de642014-07-14 16:31:30 -07001292 !manager_->IsConnected()) {
Darin Petkov4cbff5b2013-01-29 16:29:05 +01001293 *reason = kAutoConnOffline;
1294 return false;
1295 }
1296
mukesh agrawalbf14e942012-03-02 14:36:34 -08001297 return true;
mukesh agrawal76d13882012-01-12 15:23:11 -08001298}
1299
Paul Stewartd215af62012-04-24 23:25:50 -07001300bool Service::IsPortalDetectionDisabled() const {
1301 return check_portal_ == kCheckPortalFalse;
1302}
1303
1304bool Service::IsPortalDetectionAuto() const {
1305 return check_portal_ == kCheckPortalAuto;
1306}
1307
mukesh agrawalffa3d042011-10-06 15:26:10 -07001308void Service::HelpRegisterDerivedBool(
1309 const string &name,
Alex Vakulenko8a532292014-06-16 17:18:44 -07001310 bool(Service::*get)(Error *error),
Paul Stewart43d8dc02013-10-17 10:32:53 -07001311 bool(Service::*set)(const bool&, Error *),
1312 void(Service::*clear)(Error *)) {
Chris Masone27c4aa52011-07-02 13:10:14 -07001313 store_.RegisterDerivedBool(
1314 name,
Paul Stewart43d8dc02013-10-17 10:32:53 -07001315 BoolAccessor(new CustomAccessor<Service, bool>(this, get, set, clear)));
Chris Masone3bd3c8c2011-06-13 08:20:26 -07001316}
1317
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001318void Service::HelpRegisterDerivedInt32(
1319 const string &name,
Ben Chan7fab8972014-08-10 17:14:46 -07001320 int32_t(Service::*get)(Error *error),
1321 bool(Service::*set)(const int32_t&, Error *)) {
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001322 store_.RegisterDerivedInt32(
1323 name,
Ben Chan7fab8972014-08-10 17:14:46 -07001324 Int32Accessor(new CustomAccessor<Service, int32_t>(this, get, set)));
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001325}
1326
mukesh agrawalffa3d042011-10-06 15:26:10 -07001327void Service::HelpRegisterDerivedString(
1328 const string &name,
Alex Vakulenko8a532292014-06-16 17:18:44 -07001329 string(Service::*get)(Error *error),
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001330 bool(Service::*set)(const string&, Error *)) {
Chris Masone27c4aa52011-07-02 13:10:14 -07001331 store_.RegisterDerivedString(
1332 name,
1333 StringAccessor(new CustomAccessor<Service, string>(this, get, set)));
Chris Masone3bd3c8c2011-06-13 08:20:26 -07001334}
1335
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001336void Service::HelpRegisterConstDerivedRpcIdentifier(
Jason Glasgowacdc11f2012-03-30 14:12:22 -04001337 const string &name,
Paul Stewart1cf7eb82013-12-03 19:34:36 -08001338 RpcIdentifier(Service::*get)(Error *) const) {
Jason Glasgowacdc11f2012-03-30 14:12:22 -04001339 store_.RegisterDerivedRpcIdentifier(
1340 name,
Paul Stewart1cf7eb82013-12-03 19:34:36 -08001341 RpcIdentifierAccessor(new CustomReadOnlyAccessor<Service, RpcIdentifier>(
1342 this, get)));
Jason Glasgowacdc11f2012-03-30 14:12:22 -04001343}
1344
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001345void Service::HelpRegisterConstDerivedUint16(
Paul Stewartbe5f5b32011-12-07 17:11:11 -08001346 const string &name,
Ben Chan7fab8972014-08-10 17:14:46 -07001347 uint16_t(Service::*get)(Error *) const) {
Paul Stewartbe5f5b32011-12-07 17:11:11 -08001348 store_.RegisterDerivedUint16(
1349 name,
Ben Chan7fab8972014-08-10 17:14:46 -07001350 Uint16Accessor(new CustomReadOnlyAccessor<Service, uint16_t>(this, get)));
Paul Stewartbe5f5b32011-12-07 17:11:11 -08001351}
1352
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001353void Service::HelpRegisterConstDerivedStrings(
Paul Stewart1cf7eb82013-12-03 19:34:36 -08001354 const string &name, Strings(Service::*get)(Error *error) const) {
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001355 store_.RegisterDerivedStrings(
1356 name,
Paul Stewart1cf7eb82013-12-03 19:34:36 -08001357 StringsAccessor(new CustomReadOnlyAccessor<Service, Strings>(this, get)));
1358}
1359
1360void Service::HelpRegisterConstDerivedString(
1361 const string &name, string(Service::*get)(Error *error) const) {
1362 store_.RegisterDerivedString(
1363 name,
1364 StringAccessor(new CustomReadOnlyAccessor<Service, string>(this, get)));
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001365}
1366
Paul Stewart45170bc2014-06-02 15:49:34 -07001367void Service::HelpRegisterObservedDerivedBool(
1368 const string &name,
Alex Vakulenko8a532292014-06-16 17:18:44 -07001369 bool(Service::*get)(Error *error),
Paul Stewart45170bc2014-06-02 15:49:34 -07001370 bool(Service::*set)(const bool&, Error *),
1371 void(Service::*clear)(Error *)) {
1372 BoolAccessor accessor(
1373 new CustomAccessor<Service, bool>(this, get, set, clear));
1374 store_.RegisterDerivedBool(name, accessor);
1375 property_change_notifier_->AddBoolPropertyObserver(name, accessor);
1376}
1377
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001378// static
Paul Stewartc3dbff12013-07-17 10:32:48 -07001379void Service::LoadString(StoreInterface *storage,
1380 const string &id,
1381 const string &key,
1382 const string &default_value,
1383 string *value) {
1384 if (!storage->GetString(id, key, value)) {
1385 *value = default_value;
1386 }
1387}
1388
1389// static
Darin Petkovba40dd32011-07-11 20:06:39 -07001390void Service::SaveString(StoreInterface *storage,
Chris Masone34af2182011-08-22 11:59:36 -07001391 const string &id,
Darin Petkovba40dd32011-07-11 20:06:39 -07001392 const string &key,
1393 const string &value,
1394 bool crypted,
1395 bool save) {
1396 if (value.empty() || !save) {
Chris Masone34af2182011-08-22 11:59:36 -07001397 storage->DeleteKey(id, key);
Darin Petkovba40dd32011-07-11 20:06:39 -07001398 return;
1399 }
1400 if (crypted) {
Chris Masone34af2182011-08-22 11:59:36 -07001401 storage->SetCryptedString(id, key, value);
Darin Petkovba40dd32011-07-11 20:06:39 -07001402 return;
1403 }
Chris Masone34af2182011-08-22 11:59:36 -07001404 storage->SetString(id, key, value);
Darin Petkovba40dd32011-07-11 20:06:39 -07001405}
1406
Paul Stewart967eaeb2013-04-25 19:53:07 -07001407map<string, string> Service::GetLoadableProfileEntries() {
1408 return manager_->GetLoadableProfileEntriesForService(this);
1409}
1410
Paul Stewartcb59fed2012-03-21 21:14:46 -07001411void Service::IgnoreParameterForConfigure(const string &parameter) {
1412 parameters_ignored_for_configure_.insert(parameter);
1413}
1414
Paul Stewartac4ac002011-08-26 12:04:26 -07001415const string &Service::GetEAPKeyManagement() const {
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001416 CHECK(eap());
1417 return eap()->key_management();
Paul Stewartac4ac002011-08-26 12:04:26 -07001418}
1419
1420void Service::SetEAPKeyManagement(const string &key_management) {
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001421 CHECK(mutable_eap());
Ben Chancc225ef2014-09-30 13:26:51 -07001422 mutable_eap()->SetKeyManagement(key_management, nullptr);
Paul Stewartac4ac002011-08-26 12:04:26 -07001423}
1424
Thieu Le284fe792012-01-31 17:53:19 -08001425bool Service::GetAutoConnect(Error */*error*/) {
1426 return auto_connect();
1427}
1428
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001429bool Service::SetAutoConnectFull(const bool &connect, Error */*error*/) {
Darin Petkov36d962d2013-03-25 13:03:14 +01001430 LOG(INFO) << "Service " << unique_name() << ": AutoConnect="
1431 << auto_connect() << "->" << connect;
Prathmesh Prabhu765d5df2014-04-22 16:43:15 -07001432 if (!retain_auto_connect_) {
1433 RetainAutoConnect();
1434 // Irrespective of an actual change in the |kAutoConnectPropety|, we must
1435 // flush the current value of the property to the profile.
1436 if (IsRemembered()) {
1437 SaveToProfile();
1438 }
1439 }
Paul Stewart36e67be2013-12-12 14:36:10 -08001440
1441 if (auto_connect() == connect) {
1442 return false;
Darin Petkov36d962d2013-03-25 13:03:14 +01001443 }
Paul Stewart96a6d092013-08-26 09:32:49 -07001444
Paul Stewart36e67be2013-12-12 14:36:10 -08001445 SetAutoConnect(connect);
1446 manager_->UpdateService(this);
1447 return true;
Thieu Le284fe792012-01-31 17:53:19 -08001448}
1449
Paul Stewart43d8dc02013-10-17 10:32:53 -07001450void Service::ClearAutoConnect(Error */*error*/) {
Paul Stewart43d8dc02013-10-17 10:32:53 -07001451 if (auto_connect()) {
1452 SetAutoConnect(false);
Paul Stewart43d8dc02013-10-17 10:32:53 -07001453 manager_->UpdateService(this);
1454 }
Paul Stewart2da34c02013-10-17 15:28:56 -07001455
1456 retain_auto_connect_ = false;
Paul Stewart43d8dc02013-10-17 10:32:53 -07001457}
1458
Paul Stewartd215af62012-04-24 23:25:50 -07001459string Service::GetCheckPortal(Error *error) {
1460 return check_portal_;
1461}
1462
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001463bool Service::SetCheckPortal(const string &check_portal, Error *error) {
Paul Stewartd215af62012-04-24 23:25:50 -07001464 if (check_portal != kCheckPortalFalse &&
1465 check_portal != kCheckPortalTrue &&
1466 check_portal != kCheckPortalAuto) {
Paul Stewart34f424e2015-01-16 15:30:20 -08001467 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
Paul Stewartd215af62012-04-24 23:25:50 -07001468 base::StringPrintf(
1469 "Invalid Service CheckPortal property value: %s",
1470 check_portal.c_str()));
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001471 return false;
1472 }
1473 if (check_portal == check_portal_) {
1474 return false;
Paul Stewartd215af62012-04-24 23:25:50 -07001475 }
1476 check_portal_ = check_portal;
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001477 return true;
Paul Stewartd215af62012-04-24 23:25:50 -07001478}
1479
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001480string Service::GetGuid(Error *error) {
1481 return guid_;
1482}
1483
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001484bool Service::SetGuid(const string &guid, Error */*error*/) {
1485 if (guid_ == guid) {
1486 return false;
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001487 }
1488 guid_ = guid;
Ben Chan923a5022013-09-20 11:23:23 -07001489 adaptor_->EmitStringChanged(kGuidProperty, guid_);
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001490 return true;
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001491}
1492
Paul Stewart2da34c02013-10-17 15:28:56 -07001493void Service::RetainAutoConnect() {
1494 retain_auto_connect_ = true;
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001495}
1496
mukesh agrawal43970a22013-02-15 16:00:07 -08001497void Service::SetSecurity(CryptoAlgorithm crypto_algorithm, bool key_rotation,
1498 bool endpoint_auth) {
1499 crypto_algorithm_ = crypto_algorithm;
1500 key_rotation_ = key_rotation;
1501 endpoint_auth_ = endpoint_auth;
1502}
1503
mukesh agrawald4dc0832013-03-25 14:38:26 -07001504string Service::GetNameProperty(Error */*error*/) {
Paul Stewart0c438332012-04-11 07:55:27 -07001505 return friendly_name_;
1506}
1507
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001508bool Service::SetNameProperty(const string &name, Error *error) {
Paul Stewart0c438332012-04-11 07:55:27 -07001509 if (name != friendly_name_) {
Paul Stewart34f424e2015-01-16 15:30:20 -08001510 Error::PopulateAndLog(FROM_HERE, error, Error::kInvalidArguments,
Paul Stewart2bf424f2012-04-11 18:59:39 -07001511 base::StringPrintf(
Darin Petkov457728b2013-01-09 09:49:08 +01001512 "Service %s Name property cannot be modified.",
1513 unique_name_.c_str()));
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001514 return false;
Paul Stewart0c438332012-04-11 07:55:27 -07001515 }
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001516 return false;
Paul Stewart0c438332012-04-11 07:55:27 -07001517}
1518
Rebecca Silbersteine99f6642014-07-09 14:04:31 -07001519void Service::SetHasEverConnected(bool has_ever_connected) {
1520 if (has_ever_connected_ == has_ever_connected)
1521 return;
1522 has_ever_connected_ = has_ever_connected;
Rebecca Silbersteine99f6642014-07-09 14:04:31 -07001523}
1524
Ben Chan7fab8972014-08-10 17:14:46 -07001525int32_t Service::GetPriority(Error *error) {
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001526 return priority_;
1527}
1528
Ben Chan7fab8972014-08-10 17:14:46 -07001529bool Service::SetPriority(const int32_t &priority, Error *error) {
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001530 if (priority_ == priority) {
1531 return false;
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001532 }
1533 priority_ = priority;
Ben Chan923a5022013-09-20 11:23:23 -07001534 adaptor_->EmitIntChanged(kPriorityProperty, priority_);
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001535 return true;
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001536}
1537
Paul Stewartd9c7cfc2015-01-06 14:26:22 -08001538int32_t Service::GetPriorityWithinTechnology(Error *error) {
1539 return priority_within_technology_;
1540}
1541
1542bool Service::SetPriorityWithinTechnology(const int32_t &priority,
1543 Error *error) {
1544 if (priority_within_technology_ == priority) {
1545 return false;
1546 }
1547 priority_within_technology_ = priority;
1548 adaptor_->EmitIntChanged(kPriorityWithinTechnologyProperty,
1549 priority_within_technology_);
1550 return true;
1551}
1552
Paul Stewart1b1a7f22012-01-06 16:24:06 -08001553string Service::GetProfileRpcId(Error *error) {
1554 if (!profile_) {
1555 // This happens in some unit tests where profile_ is not set.
1556 error->Populate(Error::kNotFound);
1557 return "";
1558 }
1559 return profile_->GetRpcIdentifier();
1560}
1561
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001562bool Service::SetProfileRpcId(const string &profile, Error *error) {
1563 if (profile_ && profile_->GetRpcIdentifier() == profile) {
1564 return false;
1565 }
1566 ProfileConstRefPtr old_profile = profile_;
1567 // No need to Emit afterwards, since SetProfileForService will call
1568 // into SetProfile (if the profile actually changes).
Paul Stewart1b1a7f22012-01-06 16:24:06 -08001569 manager_->SetProfileForService(this, profile, error);
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001570 // Can't just use error.IsSuccess(), because that also requires saving
1571 // the profile to succeed. (See Profile::AdoptService)
1572 return (profile_ != old_profile);
Paul Stewart1b1a7f22012-01-06 16:24:06 -08001573}
1574
Ben Chan7fab8972014-08-10 17:14:46 -07001575uint16_t Service::GetHTTPProxyPort(Error */*error*/) const {
Paul Stewartbe5f5b32011-12-07 17:11:11 -08001576 if (http_proxy_.get()) {
Ben Chan7fab8972014-08-10 17:14:46 -07001577 return static_cast<uint16_t>(http_proxy_->proxy_port());
Paul Stewartbe5f5b32011-12-07 17:11:11 -08001578 }
1579 return 0;
1580}
1581
Philipp Neubeck79173602012-11-13 21:10:09 +01001582string Service::GetProxyConfig(Error *error) {
1583 return proxy_config_;
1584}
1585
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001586bool Service::SetProxyConfig(const string &proxy_config, Error *error) {
1587 if (proxy_config_ == proxy_config)
1588 return false;
Philipp Neubeck79173602012-11-13 21:10:09 +01001589 proxy_config_ = proxy_config;
Ben Chan923a5022013-09-20 11:23:23 -07001590 adaptor_->EmitStringChanged(kProxyConfigProperty, proxy_config_);
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001591 return true;
Philipp Neubeck79173602012-11-13 21:10:09 +01001592}
1593
Paul Stewartfa11e282013-12-02 22:04:25 -08001594string Service::GetTethering(Error *error) const {
1595 // The "Tethering" property isn't supported by the Service base class, and
1596 // therefore should not be listed in the properties returned by
1597 // the GetProperties() RPC method.
1598 error->Populate(Error::kNotSupported);
1599 return "";
1600}
1601
Paul Stewart7cc90682014-05-30 17:01:56 -07001602
Paul Stewart45170bc2014-06-02 15:49:34 -07001603void Service::NotifyPropertyChanges() {
1604 property_change_notifier_->UpdatePropertyObservers();
Paul Stewart7cc90682014-05-30 17:01:56 -07001605}
1606
Paul Stewart1cf7eb82013-12-03 19:34:36 -08001607Strings Service::GetDisconnectsProperty(Error */*error*/) const {
Samuel Tan07dfabc2015-01-20 15:10:39 -08001608 return disconnects_.ExtractWallClockToStrings();
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001609}
1610
Paul Stewart1cf7eb82013-12-03 19:34:36 -08001611Strings Service::GetMisconnectsProperty(Error */*error*/) const {
Samuel Tan07dfabc2015-01-20 15:10:39 -08001612 return misconnects_.ExtractWallClockToStrings();
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001613}
1614
Paul Stewartcca85b12014-05-30 13:56:35 -07001615bool Service::GetVisibleProperty(Error */*error*/) {
1616 return IsVisible();
1617}
1618
mukesh agrawalcf24a242012-05-21 16:46:11 -07001619void Service::SaveToProfile() {
1620 if (profile_.get() && profile_->GetConstStorage()) {
1621 profile_->UpdateService(this);
1622 }
1623}
1624
Arman Uguray2717a102013-01-29 23:36:06 -08001625void Service::SetFriendlyName(const string &friendly_name) {
1626 if (friendly_name == friendly_name_)
1627 return;
1628 friendly_name_ = friendly_name;
Ben Chan923a5022013-09-20 11:23:23 -07001629 adaptor()->EmitStringChanged(kNameProperty, friendly_name_);
Arman Uguray2717a102013-01-29 23:36:06 -08001630}
1631
Ben Chan7fab8972014-08-10 17:14:46 -07001632void Service::SetStrength(uint8_t strength) {
Darin Petkovd78ee7e2012-01-12 11:21:10 +01001633 if (strength == strength_) {
1634 return;
1635 }
1636 strength_ = strength;
Ben Chan923a5022013-09-20 11:23:23 -07001637 adaptor_->EmitUint8Changed(kSignalStrengthProperty, strength);
Darin Petkovd78ee7e2012-01-12 11:21:10 +01001638}
1639
Darin Petkovaba89322013-03-11 14:48:22 +01001640void Service::SetErrorDetails(const string &details) {
1641 if (error_details_ == details) {
1642 return;
1643 }
1644 error_details_ = details;
Ben Chan39a7beb2013-09-21 11:28:00 -07001645 adaptor_->EmitStringChanged(kErrorDetailsProperty, error_details_);
Darin Petkovaba89322013-03-11 14:48:22 +01001646}
1647
Paul Stewartf2d60912012-07-15 08:37:30 -07001648void Service::UpdateErrorProperty() {
1649 const string error(ConnectFailureToString(failure_));
1650 if (error == error_) {
1651 return;
1652 }
1653 error_ = error;
Ben Chan923a5022013-09-20 11:23:23 -07001654 adaptor_->EmitStringChanged(kErrorProperty, error);
Paul Stewartf2d60912012-07-15 08:37:30 -07001655}
1656
Paul Stewart2eee6132014-05-09 13:33:26 -07001657void Service::ClearExplicitlyDisconnected() {
1658 if (explicitly_disconnected_) {
1659 explicitly_disconnected_ = false;
1660 manager_->UpdateService(this);
1661 }
1662}
1663
Paul Stewart75897df2011-04-27 09:05:53 -07001664} // namespace shill