blob: 49c704da93fd31b43ca05b8934cdb0f8b542557b [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;
Eric Shienbroodcc95c5d2012-03-30 15:25:49 -0400248 // clear any failure state from a previous connect attempt
249 SetState(kStateIdle);
mukesh agrawaladb68482012-01-17 16:31:51 -0800250}
251
252void Service::Disconnect(Error */*error*/) {
mukesh agrawaldc7b8442012-09-27 13:48:14 -0700253 LOG(INFO) << "Disconnecting from service " << unique_name_;
Christopher Wiley3e7635e2012-08-15 09:46:17 -0700254 MemoryLog::GetInstance()->FlushToDisk();
mukesh agrawaladb68482012-01-17 16:31:51 -0800255}
256
Christopher Wileyabd3b502012-09-26 13:08:52 -0700257void Service::DisconnectWithFailure(ConnectFailure failure, Error *error) {
258 Disconnect(error);
259 SetFailure(failure);
260}
261
262void Service::UserInitiatedDisconnect(Error *error) {
263 Disconnect(error);
264 explicitly_disconnected_ = true;
265}
266
Eric Shienbrood5de44ab2011-12-05 10:46:27 -0500267void Service::ActivateCellularModem(const string &/*carrier*/,
Eric Shienbrood9a245532012-03-07 14:20:39 -0500268 Error *error,
269 const ResultCallback &/*callback*/) {
270 Error::PopulateAndLog(error, Error::kNotSupported,
271 "Service doesn't support cellular modem activation.");
Darin Petkovc408e692011-08-17 13:47:15 -0700272}
273
Ben Chan5d924542013-02-14 17:49:08 -0800274void Service::CompleteCellularActivation(Error *error) {
275 Error::PopulateAndLog(
276 error, Error::kNotSupported,
277 "Service doesn't support cellular activation completion.");
278}
279
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800280bool Service::IsActive(Error */*error*/) {
Paul Stewartbfb82552012-10-24 16:48:48 -0700281 return state() != kStateUnknown &&
282 state() != kStateIdle &&
283 state() != kStateFailure;
Paul Stewart03dba0b2011-08-22 16:32:45 -0700284}
285
Darin Petkovc8d91e52013-01-21 11:43:47 +0100286// static
287bool Service::IsConnectedState(ConnectState state) {
288 return (state == kStateConnected ||
289 state == kStatePortal ||
290 state == kStateOnline);
291}
292
293// static
294bool Service::IsConnectingState(ConnectState state) {
295 return (state == kStateAssociating ||
296 state == kStateConfiguring);
297}
298
299bool Service::IsConnected() const {
300 return IsConnectedState(state());
301}
302
303bool Service::IsConnecting() const {
304 return IsConnectingState(state());
305}
306
Paul Stewart03dba0b2011-08-22 16:32:45 -0700307void Service::SetState(ConnectState state) {
308 if (state == state_) {
309 return;
310 }
311
Darin Petkov457728b2013-01-09 09:49:08 +0100312 LOG(INFO) << "Service " << unique_name_ << ": state "
313 << ConnectStateToString(state_) << " -> "
314 << ConnectStateToString(state);
315
Darin Petkov0857f8e2012-12-21 10:49:17 +0100316 if (state == kStateFailure) {
Darin Petkov385b9bc2012-12-03 15:25:05 +0100317 NoteDisconnectEvent();
318 }
319
Darin Petkovc8d91e52013-01-21 11:43:47 +0100320 previous_state_ = state_;
Paul Stewart03dba0b2011-08-22 16:32:45 -0700321 state_ = state;
322 if (state != kStateFailure) {
323 failure_ = kFailureUnknown;
Darin Petkovaba89322013-03-11 14:48:22 +0100324 SetErrorDetails(kErrorDetailsNone);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700325 }
mukesh agrawalcf24a242012-05-21 16:46:11 -0700326 if (state == kStateConnected) {
Christopher Wiley0801d192012-09-24 11:57:15 -0700327 failed_time_ = 0;
mukesh agrawalcf24a242012-05-21 16:46:11 -0700328 has_ever_connected_ = true;
329 SaveToProfile();
Christopher Wiley0801d192012-09-24 11:57:15 -0700330 // When we succeed in connecting, forget that connects failed in the past.
331 // Give services one chance at a fast autoconnect retry by resetting the
332 // cooldown to 0 to indicate that the last connect was successful.
333 auto_connect_cooldown_milliseconds_ = 0;
334 reenable_auto_connect_task_.Cancel();
mukesh agrawalcf24a242012-05-21 16:46:11 -0700335 }
Paul Stewartf2d60912012-07-15 08:37:30 -0700336 UpdateErrorProperty();
Paul Stewart03dba0b2011-08-22 16:32:45 -0700337 manager_->UpdateService(this);
Thieu Le48e6d6d2011-12-06 00:40:27 +0000338 metrics_->NotifyServiceStateChanged(this, state);
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200339 adaptor_->EmitStringChanged(flimflam::kStateProperty, GetStateString());
Paul Stewart03dba0b2011-08-22 16:32:45 -0700340}
341
Christopher Wiley0801d192012-09-24 11:57:15 -0700342void Service::ReEnableAutoConnectTask() {
343 // Kill the thing blocking AutoConnect().
344 reenable_auto_connect_task_.Cancel();
345 // Post to the manager, giving it an opportunity to AutoConnect again.
346 manager_->UpdateService(this);
347}
348
349void Service::ThrottleFutureAutoConnects() {
350 if (auto_connect_cooldown_milliseconds_ > 0) {
mukesh agrawaldc7b8442012-09-27 13:48:14 -0700351 LOG(INFO) << "Throttling future autoconnects to service " << unique_name_
352 << ". Next autoconnect in "
Christopher Wiley0801d192012-09-24 11:57:15 -0700353 << auto_connect_cooldown_milliseconds_ << " milliseconds.";
354 reenable_auto_connect_task_.Reset(Bind(&Service::ReEnableAutoConnectTask,
355 weak_ptr_factory_.GetWeakPtr()));
356 dispatcher_->PostDelayedTask(reenable_auto_connect_task_.callback(),
357 auto_connect_cooldown_milliseconds_);
358 }
359 auto_connect_cooldown_milliseconds_ =
360 std::min(kMaxAutoConnectCooldownTimeMilliseconds,
361 std::max(kMinAutoConnectCooldownTimeMilliseconds,
362 auto_connect_cooldown_milliseconds_ *
363 kAutoConnectCooldownBackoffFactor));
364}
365
Paul Stewart03dba0b2011-08-22 16:32:45 -0700366void Service::SetFailure(ConnectFailure failure) {
367 failure_ = failure;
mukesh agrawal568b5c62012-02-28 14:44:47 -0800368 failed_time_ = time(NULL);
Paul Stewartf2d60912012-07-15 08:37:30 -0700369 UpdateErrorProperty();
Paul Stewart03dba0b2011-08-22 16:32:45 -0700370 SetState(kStateFailure);
371}
372
mukesh agrawal568b5c62012-02-28 14:44:47 -0800373void Service::SetFailureSilent(ConnectFailure failure) {
Darin Petkov0857f8e2012-12-21 10:49:17 +0100374 NoteDisconnectEvent();
mukesh agrawal568b5c62012-02-28 14:44:47 -0800375 // Note that order matters here, since SetState modifies |failure_| and
376 // |failed_time_|.
377 SetState(kStateIdle);
378 failure_ = failure;
Paul Stewartf2d60912012-07-15 08:37:30 -0700379 UpdateErrorProperty();
mukesh agrawal568b5c62012-02-28 14:44:47 -0800380 failed_time_ = time(NULL);
381}
382
Chris Masone6791a432011-07-12 13:23:19 -0700383string Service::GetRpcIdentifier() const {
Chris Masone3c3f6a12011-07-01 10:01:41 -0700384 return adaptor_->GetRpcIdentifier();
385}
386
Paul Stewarte7de2942013-04-25 17:07:31 -0700387string Service::GetLoadableStorageIdentifier(
388 const StoreInterface &storage) const {
389 return IsLoadableFrom(storage) ? GetStorageIdentifier() : "";
390}
391
392bool Service::IsLoadableFrom(const StoreInterface &storage) const {
393 return storage.ContainsGroup(GetStorageIdentifier());
Paul Stewartbba6a5b2011-11-02 18:45:59 -0700394}
395
Chris Masone9d779932011-08-25 16:33:41 -0700396bool Service::Load(StoreInterface *storage) {
397 const string id = GetStorageIdentifier();
Chris Masone34af2182011-08-22 11:59:36 -0700398 if (!storage->ContainsGroup(id)) {
399 LOG(WARNING) << "Service is not available in the persistent store: " << id;
400 return false;
401 }
402 storage->GetBool(id, kStorageAutoConnect, &auto_connect_);
403 storage->GetString(id, kStorageCheckPortal, &check_portal_);
404 storage->GetBool(id, kStorageFavorite, &favorite_);
mukesh agrawalcf24a242012-05-21 16:46:11 -0700405 storage->GetString(id, kStorageGUID, &guid_);
406 storage->GetBool(id, kStorageHasEverConnected, &has_ever_connected_);
Chris Masone34af2182011-08-22 11:59:36 -0700407 storage->GetInt(id, kStoragePriority, &priority_);
408 storage->GetString(id, kStorageProxyConfig, &proxy_config_);
409 storage->GetBool(id, kStorageSaveCredentials, &save_credentials_);
Paul Stewart987e71e2011-12-05 09:45:06 -0800410 storage->GetString(id, kStorageUIData, &ui_data_);
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700411
Paul Stewart1062d9d2012-04-27 10:42:27 -0700412 static_ip_parameters_.Load(storage, id);
Chris Masone34af2182011-08-22 11:59:36 -0700413
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700414 if (mutable_eap()) {
415 mutable_eap()->Load(storage, id);
416 OnEapCredentialsChanged();
417 }
418
mukesh agrawaladb68482012-01-17 16:31:51 -0800419 explicitly_disconnected_ = false;
Paul Stewarta41e38d2011-11-11 07:47:29 -0800420 favorite_ = true;
421
Chris Masone34af2182011-08-22 11:59:36 -0700422 return true;
Darin Petkovba40dd32011-07-11 20:06:39 -0700423}
424
Paul Stewart65512e12012-03-26 18:01:08 -0700425bool Service::Unload() {
Paul Stewart7fb09382012-07-18 17:32:27 -0700426 auto_connect_ = IsAutoConnectByDefault();
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800427 check_portal_ = kCheckPortalAuto;
Christopher Wileyabd3b502012-09-26 13:08:52 -0700428 explicitly_disconnected_ = false;
Paul Stewarta41e38d2011-11-11 07:47:29 -0800429 favorite_ = false;
Paul Stewarte7cce8f2012-09-11 10:56:38 -0700430 guid_ = "";
Paul Stewart88769de2012-09-21 13:14:36 -0700431 has_ever_connected_ = false;
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800432 priority_ = kPriorityNone;
433 proxy_config_ = "";
434 save_credentials_ = true;
435 ui_data_ = "";
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700436 if (mutable_eap()) {
437 mutable_eap()->Reset();
438 }
439 ClearEAPCertification();
Paul Stewartd8ad3c42012-01-09 12:39:38 -0800440
Wade Guthrie9e0c2502012-04-19 15:26:40 -0700441 Error error; // Ignored.
442 Disconnect(&error);
Paul Stewart65512e12012-03-26 18:01:08 -0700443 return false;
Paul Stewarta41e38d2011-11-11 07:47:29 -0800444}
445
Albert Chaulk0e1cdea2013-02-27 15:32:55 -0800446void Service::Remove(Error */*error*/) {
447 Unload();
448}
449
Chris Masone9d779932011-08-25 16:33:41 -0700450bool Service::Save(StoreInterface *storage) {
451 const string id = GetStorageIdentifier();
Chris Masone34af2182011-08-22 11:59:36 -0700452
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200453 storage->SetString(id, kStorageType, GetTechnologyString());
Paul Stewart2706aaf2011-12-14 16:44:04 -0800454
Wade Guthrie4f28e8b2012-04-11 10:52:07 -0700455 storage->SetBool(id, kStorageAutoConnect, auto_connect_);
Chris Masone34af2182011-08-22 11:59:36 -0700456 if (check_portal_ == kCheckPortalAuto) {
457 storage->DeleteKey(id, kStorageCheckPortal);
458 } else {
459 storage->SetString(id, kStorageCheckPortal, check_portal_);
460 }
461 storage->SetBool(id, kStorageFavorite, favorite_);
mukesh agrawalcf24a242012-05-21 16:46:11 -0700462 SaveString(storage, id, kStorageGUID, guid_, false, true);
463 storage->SetBool(id, kStorageHasEverConnected, has_ever_connected_);
mukesh agrawald835b202011-10-07 15:26:47 -0700464 storage->SetString(id, kStorageName, friendly_name_);
Chris Masone34af2182011-08-22 11:59:36 -0700465 if (priority_ != kPriorityNone) {
466 storage->SetInt(id, kStoragePriority, priority_);
467 } else {
468 storage->DeleteKey(id, kStoragePriority);
469 }
Paul Stewart987e71e2011-12-05 09:45:06 -0800470 SaveString(storage, id, kStorageProxyConfig, proxy_config_, false, true);
Darin Petkov0debec02013-01-22 10:40:05 +0100471 storage->SetBool(id, kStorageSaveCredentials, save_credentials_);
Paul Stewart987e71e2011-12-05 09:45:06 -0800472 SaveString(storage, id, kStorageUIData, ui_data_, false, true);
Chris Masone34af2182011-08-22 11:59:36 -0700473
Paul Stewart1062d9d2012-04-27 10:42:27 -0700474 static_ip_parameters_.Save(storage, id);
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700475 if (eap()) {
476 eap()->Save(storage, id, save_credentials_);
477 }
Chris Masone34af2182011-08-22 11:59:36 -0700478 return true;
479}
480
Gary Moraind93615e2012-04-27 11:50:03 -0700481void Service::SaveToCurrentProfile() {
482 // Some unittests do not specify a manager.
483 if (manager()) {
484 manager()->SaveServiceToProfile(this);
485 }
Thieu Led4e9e552012-02-16 16:26:07 -0800486}
487
Paul Stewartcb59fed2012-03-21 21:14:46 -0700488void Service::Configure(const KeyValueStore &args, Error *error) {
489 map<string, bool>::const_iterator bool_it;
Ben Chanfad4a0b2012-04-18 15:49:59 -0700490 SLOG(Service, 5) << "Configuring bool properties:";
Paul Stewartcb59fed2012-03-21 21:14:46 -0700491 for (bool_it = args.bool_properties().begin();
492 bool_it != args.bool_properties().end();
493 ++bool_it) {
494 if (ContainsKey(parameters_ignored_for_configure_, bool_it->first)) {
495 continue;
496 }
Ben Chanfad4a0b2012-04-18 15:49:59 -0700497 SLOG(Service, 5) << " " << bool_it->first;
Paul Stewartcb59fed2012-03-21 21:14:46 -0700498 Error set_error;
499 store_.SetBoolProperty(bool_it->first, bool_it->second, &set_error);
Christopher Wiley27b47232012-11-02 13:13:00 -0700500 OnPropertyChanged(bool_it->first);
Paul Stewartcb59fed2012-03-21 21:14:46 -0700501 if (error->IsSuccess() && set_error.IsFailure()) {
502 error->CopyFrom(set_error);
503 }
504 }
Ben Chanfad4a0b2012-04-18 15:49:59 -0700505 SLOG(Service, 5) << "Configuring string properties:";
Paul Stewartcb59fed2012-03-21 21:14:46 -0700506 map<string, string>::const_iterator string_it;
507 for (string_it = args.string_properties().begin();
508 string_it != args.string_properties().end();
509 ++string_it) {
510 if (ContainsKey(parameters_ignored_for_configure_, string_it->first)) {
511 continue;
512 }
Ben Chanfad4a0b2012-04-18 15:49:59 -0700513 SLOG(Service, 5) << " " << string_it->first;
Paul Stewartcb59fed2012-03-21 21:14:46 -0700514 Error set_error;
515 store_.SetStringProperty(string_it->first, string_it->second, &set_error);
Christopher Wiley27b47232012-11-02 13:13:00 -0700516 OnPropertyChanged(string_it->first);
Paul Stewartcb59fed2012-03-21 21:14:46 -0700517 if (error->IsSuccess() && set_error.IsFailure()) {
518 error->CopyFrom(set_error);
519 }
520 }
Paul Stewart7a20aa42013-01-17 12:21:41 -0800521 SLOG(Service, 5) << "Configuring int32 properties:";
522 map<string, int32>::const_iterator int_it;
523 for (int_it = args.int_properties().begin();
524 int_it != args.int_properties().end();
Paul Stewartcb59fed2012-03-21 21:14:46 -0700525 ++int_it) {
526 if (ContainsKey(parameters_ignored_for_configure_, int_it->first)) {
527 continue;
528 }
Ben Chanfad4a0b2012-04-18 15:49:59 -0700529 SLOG(Service, 5) << " " << int_it->first;
Paul Stewartcb59fed2012-03-21 21:14:46 -0700530 Error set_error;
Paul Stewart7a20aa42013-01-17 12:21:41 -0800531 store_.SetInt32Property(int_it->first, int_it->second, &set_error);
Christopher Wiley27b47232012-11-02 13:13:00 -0700532 OnPropertyChanged(int_it->first);
Paul Stewartcb59fed2012-03-21 21:14:46 -0700533 if (error->IsSuccess() && set_error.IsFailure()) {
534 error->CopyFrom(set_error);
535 }
536 }
537}
538
Paul Stewart7a20aa42013-01-17 12:21:41 -0800539bool Service::DoPropertiesMatch(const KeyValueStore &args) const {
540 map<string, bool>::const_iterator bool_it;
541 SLOG(Service, 5) << "Checking bool properties:";
542 for (bool_it = args.bool_properties().begin();
543 bool_it != args.bool_properties().end();
544 ++bool_it) {
545 SLOG(Service, 5) << " " << bool_it->first;
546 Error get_error;
547 bool value;
548 if (!store_.GetBoolProperty(bool_it->first, &value, &get_error) ||
549 value != bool_it->second) {
550 return false;
551 }
552 }
553 SLOG(Service, 5) << "Checking string properties:";
554 map<string, string>::const_iterator string_it;
555 for (string_it = args.string_properties().begin();
556 string_it != args.string_properties().end();
557 ++string_it) {
558 SLOG(Service, 5) << " " << string_it->first;
559 Error get_error;
560 string value;
561 if (!store_.GetStringProperty(string_it->first, &value, &get_error) ||
562 value != string_it->second) {
563 return false;
564 }
565 }
566 SLOG(Service, 5) << "Checking int32 properties:";
567 map<string, int32>::const_iterator int_it;
568 for (int_it = args.int_properties().begin();
569 int_it != args.int_properties().end();
570 ++int_it) {
571 SLOG(Service, 5) << " " << int_it->first;
572 Error get_error;
573 int32 value;
574 if (!store_.GetInt32Property(int_it->first, &value, &get_error) ||
575 value != int_it->second) {
576 return false;
577 }
578 }
579 return true;
580}
581
Paul Stewart10ccbb32012-04-26 15:59:30 -0700582bool Service::IsRemembered() const {
583 return profile_ && !manager_->IsServiceEphemeral(this);
584}
585
Paul Stewartdf3c0a82012-11-09 15:54:33 -0800586bool Service::IsDependentOn(const ServiceRefPtr &b) const {
Paul Stewartcd7f5852013-03-27 13:54:23 -0700587 if (!connection_ || !b || !b->connection()) {
Paul Stewartdf3c0a82012-11-09 15:54:33 -0800588 return false;
589 }
590 return connection_->GetLowerConnection() == b->connection();
591}
592
mukesh agrawal00917ce2011-11-22 23:56:55 +0000593void Service::MakeFavorite() {
594 if (favorite_) {
595 // We do not want to clobber the value of auto_connect_ (it may
596 // be user-set). So return early.
597 return;
598 }
599
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700600 MarkAsFavorite();
601 SetAutoConnect(true);
mukesh agrawal00917ce2011-11-22 23:56:55 +0000602}
603
Darin Petkov5eb05422012-05-11 15:45:25 +0200604void Service::SetConnection(const ConnectionRefPtr &connection) {
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800605 if (connection.get()) {
Paul Stewart1e3bc4962012-09-14 12:20:22 -0700606 // TODO(pstew): Make this function testable by using a factory here.
607 // http://crosbug.com/34528
Paul Stewartc8f4bef2011-12-13 09:45:51 -0800608 http_proxy_.reset(new HTTPProxy(connection));
Darin Petkov5eb05422012-05-11 15:45:25 +0200609 http_proxy_->Start(dispatcher_, sockets_.get());
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800610 } else {
611 http_proxy_.reset();
Paul Stewartdef189e2012-08-02 20:12:09 -0700612 static_ip_parameters_.ClearSavedParameters();
Paul Stewartc1dec4d2011-12-08 15:25:28 -0800613 }
614 connection_ = connection;
Paul Stewart1e3bc4962012-09-14 12:20:22 -0700615 Error error;
616 string ipconfig = GetIPConfigRpcIdentifier(&error);
617 if (error.IsSuccess()) {
618 adaptor_->EmitRpcIdentifierChanged(shill::kIPConfigProperty, ipconfig);
619 }
Paul Stewartbe5f5b32011-12-07 17:11:11 -0800620}
621
Gaurav Shah10109f22011-11-11 20:16:22 -0800622bool Service::Is8021xConnectable() const {
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700623 return eap() && eap()->IsConnectable();
Gaurav Shah10109f22011-11-11 20:16:22 -0800624}
625
Paul Stewartbc6e7392012-05-24 07:07:48 -0700626bool Service::AddEAPCertification(const string &name, size_t depth) {
627 if (depth >= kEAPMaxCertificationElements) {
628 LOG(WARNING) << "Ignoring certification " << name
629 << " because depth " << depth
630 << " exceeds our maximum of "
631 << kEAPMaxCertificationElements;
632 return false;
633 }
634
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700635 if (depth >= remote_certification_.size()) {
636 remote_certification_.resize(depth + 1);
637 } else if (name == remote_certification_[depth]) {
Paul Stewartbc6e7392012-05-24 07:07:48 -0700638 return true;
639 }
640
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700641 remote_certification_[depth] = name;
Paul Stewartbc6e7392012-05-24 07:07:48 -0700642 LOG(INFO) << "Received certification for "
643 << name
644 << " at depth "
645 << depth;
646 return true;
647}
648
649void Service::ClearEAPCertification() {
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700650 remote_certification_.clear();
Paul Stewartbc6e7392012-05-24 07:07:48 -0700651}
652
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700653void Service::SetAutoConnect(bool connect) {
654 if (auto_connect() == connect) {
655 return;
656 }
657 auto_connect_ = connect;
658 adaptor_->EmitBoolChanged(flimflam::kAutoConnectProperty, auto_connect());
659}
660
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700661void Service::SetEapCredentials(EapCredentials *eap) {
662 // This operation must be done at most once for the lifetime of the service.
663 CHECK(eap && !eap_);
664
665 eap_.reset(eap);
666 eap_->InitPropertyStore(mutable_store());
Gaurav Shah10109f22011-11-11 20:16:22 -0800667}
668
mukesh agrawal00917ce2011-11-22 23:56:55 +0000669// static
Gaurav Shahc6d6c722011-11-17 18:59:39 -0800670const char *Service::ConnectFailureToString(const ConnectFailure &state) {
671 switch (state) {
672 case kFailureUnknown:
673 return "Unknown";
Paul Stewartf2d60912012-07-15 08:37:30 -0700674 case kFailureAAA:
675 return flimflam::kErrorAaaFailed;
676 case kFailureActivation:
677 return flimflam::kErrorActivationFailed;
678 case kFailureBadPassphrase:
679 return flimflam::kErrorBadPassphrase;
680 case kFailureBadWEPKey:
681 return flimflam::kErrorBadWEPKey;
682 case kFailureConnect:
683 return flimflam::kErrorConnectFailed;
684 case kFailureDNSLookup:
685 return flimflam::kErrorDNSLookupFailed;
686 case kFailureDHCP:
687 return flimflam::kErrorDhcpFailed;
Darin Petkov1c049c72013-03-21 13:15:45 +0100688 case kFailureEAPAuthentication:
689 return shill::kErrorEapAuthenticationFailed;
690 case kFailureEAPLocalTLS:
691 return shill::kErrorEapLocalTlsFailed;
692 case kFailureEAPRemoteTLS:
693 return shill::kErrorEapRemoteTlsFailed;
Paul Stewartf2d60912012-07-15 08:37:30 -0700694 case kFailureHTTPGet:
695 return flimflam::kErrorHTTPGetFailed;
Darin Petkov1c049c72013-03-21 13:15:45 +0100696 case kFailureInternal:
697 return flimflam::kErrorInternal;
698 case kFailureIPSecCertAuth:
699 return flimflam::kErrorIpsecCertAuthFailed;
700 case kFailureIPSecPSKAuth:
701 return flimflam::kErrorIpsecPskAuthFailed;
Gaurav Shahc6d6c722011-11-17 18:59:39 -0800702 case kFailureNeedEVDO:
Paul Stewartf2d60912012-07-15 08:37:30 -0700703 return flimflam::kErrorNeedEvdo;
Gaurav Shahc6d6c722011-11-17 18:59:39 -0800704 case kFailureNeedHomeNetwork:
Paul Stewartf2d60912012-07-15 08:37:30 -0700705 return flimflam::kErrorNeedHomeNetwork;
706 case kFailureOTASP:
707 return flimflam::kErrorOtaspFailed;
708 case kFailureOutOfRange:
709 return flimflam::kErrorOutOfRange;
710 case kFailurePinMissing:
711 return flimflam::kErrorPinMissing;
712 case kFailurePPPAuth:
713 return flimflam::kErrorPppAuthFailed;
Thieu Le48e6d6d2011-12-06 00:40:27 +0000714 case kFailureMax:
Darin Petkov1c049c72013-03-21 13:15:45 +0100715 NOTREACHED();
Gaurav Shahc6d6c722011-11-17 18:59:39 -0800716 }
717 return "Invalid";
718}
719
720// static
721const char *Service::ConnectStateToString(const ConnectState &state) {
722 switch (state) {
723 case kStateUnknown:
724 return "Unknown";
725 case kStateIdle:
726 return "Idle";
727 case kStateAssociating:
728 return "Associating";
729 case kStateConfiguring:
730 return "Configuring";
731 case kStateConnected:
732 return "Connected";
Thieu Le48e6d6d2011-12-06 00:40:27 +0000733 case kStatePortal:
734 return "Portal";
Gaurav Shahc6d6c722011-11-17 18:59:39 -0800735 case kStateFailure:
736 return "Failure";
737 case kStateOnline:
738 return "Online";
739 }
740 return "Invalid";
741}
742
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200743string Service::GetTechnologyString() const {
Gaurav Shah435de2c2011-11-17 19:01:07 -0800744 return Technology::NameFromIdentifier(technology());
745}
746
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200747string Service::CalculateTechnology(Error */*error*/) {
748 return GetTechnologyString();
749}
750
Paul Stewart483e4722012-12-18 10:23:17 -0800751// static
752void Service::ExpireEventsBefore(
753 int seconds_ago, const Timestamp &now, std::deque<Timestamp> *events) {
754 struct timeval period = (const struct timeval){ seconds_ago };
755 while (!events->empty()) {
756 if (events->size() < static_cast<size_t>(kMaxDisconnectEventHistory)) {
757 struct timeval elapsed = (const struct timeval){ 0 };
758 timersub(&now.monotonic, &events->front().monotonic, &elapsed);
759 if (timercmp(&elapsed, &period, <)) {
760 break;
761 }
762 }
763 events->pop_front();
764 }
765}
766
Darin Petkov385b9bc2012-12-03 15:25:05 +0100767void Service::NoteDisconnectEvent() {
768 SLOG(Service, 2) << __func__;
Darin Petkovcb0b5662012-12-13 09:59:44 +0100769 // Ignore the event if it's user-initiated explicit disconnect.
Darin Petkov385b9bc2012-12-03 15:25:05 +0100770 if (explicitly_disconnected_) {
Darin Petkovcb0b5662012-12-13 09:59:44 +0100771 SLOG(Service, 2) << "Explicit disconnect ignored.";
772 return;
773 }
774 // Ignore the event if manager is not running (e.g., service disconnects on
775 // shutdown).
776 if (!manager_->running()) {
777 SLOG(Service, 2) << "Disconnect while manager stopped ignored.";
778 return;
779 }
780 // Ignore the event if the power state is not on (e.g., when suspending).
781 PowerManager *power_manager = manager_->power_manager();
782 if (!power_manager ||
783 (power_manager->power_state() != PowerManager::kOn &&
784 power_manager->power_state() != PowerManager::kUnknown)) {
785 SLOG(Service, 2) << "Disconnect in transitional power state ignored.";
Darin Petkov385b9bc2012-12-03 15:25:05 +0100786 return;
787 }
Paul Stewart483e4722012-12-18 10:23:17 -0800788 int period = 0;
Darin Petkov385b9bc2012-12-03 15:25:05 +0100789 size_t threshold = 0;
Darin Petkov0c65bdd2012-12-05 13:42:41 +0100790 deque<Timestamp> *events = NULL;
Darin Petkovc8d91e52013-01-21 11:43:47 +0100791 // Sometimes services transition to Idle before going into a failed state so
792 // take into account the last non-idle state.
793 ConnectState state = state_ == kStateIdle ? previous_state_ : state_;
794 if (IsConnectedState(state)) {
Darin Petkovcb0b5662012-12-13 09:59:44 +0100795 LOG(INFO) << "Noting an unexpected connection drop.";
Paul Stewart483e4722012-12-18 10:23:17 -0800796 period = kDisconnectsMonitorSeconds;
Darin Petkov385b9bc2012-12-03 15:25:05 +0100797 threshold = kReportDisconnectsThreshold;
798 events = &disconnects_;
Darin Petkovc8d91e52013-01-21 11:43:47 +0100799 } else if (IsConnectingState(state)) {
Darin Petkovcb0b5662012-12-13 09:59:44 +0100800 LOG(INFO) << "Noting an unexpected failure to connect.";
Paul Stewart483e4722012-12-18 10:23:17 -0800801 period = kMisconnectsMonitorSeconds;
Darin Petkov385b9bc2012-12-03 15:25:05 +0100802 threshold = kReportMisconnectsThreshold;
803 events = &misconnects_;
804 } else {
Darin Petkovcb0b5662012-12-13 09:59:44 +0100805 SLOG(Service, 2)
806 << "Not connected or connecting, state transition ignored.";
Darin Petkov385b9bc2012-12-03 15:25:05 +0100807 return;
808 }
Darin Petkov0c65bdd2012-12-05 13:42:41 +0100809 Timestamp now = time_->GetNow();
Paul Stewart483e4722012-12-18 10:23:17 -0800810 // Discard old events first.
811 ExpireEventsBefore(period, now, events);
Darin Petkov385b9bc2012-12-03 15:25:05 +0100812 events->push_back(now);
813 if (events->size() >= threshold) {
814 diagnostics_reporter_->OnConnectivityEvent();
815 }
816}
817
Paul Stewart483e4722012-12-18 10:23:17 -0800818bool Service::HasRecentConnectionIssues() {
819 Timestamp now = time_->GetNow();
820 ExpireEventsBefore(kDisconnectsMonitorSeconds, now, &disconnects_);
821 ExpireEventsBefore(kMisconnectsMonitorSeconds, now, &misconnects_);
822 return !disconnects_.empty() || !misconnects_.empty();
823}
824
Jason Glasgowb5790052012-01-27 01:03:52 -0500825// static
Paul Stewart22aa71b2011-09-16 12:15:11 -0700826bool Service::DecideBetween(int a, int b, bool *decision) {
827 if (a == b)
828 return false;
829 *decision = (a > b);
830 return true;
831}
832
mukesh agrawal43970a22013-02-15 16:00:07 -0800833uint16 Service::SecurityLevel() {
834 return (crypto_algorithm_ << 2) | (key_rotation_ << 1) | endpoint_auth_;
835}
836
mukesh agrawal00917ce2011-11-22 23:56:55 +0000837// static
Paul Stewart22aa71b2011-09-16 12:15:11 -0700838bool Service::Compare(ServiceRefPtr a,
839 ServiceRefPtr b,
Paul Stewart39db5ca2013-03-18 14:15:17 -0700840 bool compare_connectivity_state,
mukesh agrawalddc378f2012-02-17 18:26:20 -0800841 const vector<Technology::Identifier> &tech_order,
842 const char **reason) {
Paul Stewart22aa71b2011-09-16 12:15:11 -0700843 bool ret;
844
Paul Stewart39db5ca2013-03-18 14:15:17 -0700845 if (compare_connectivity_state && a->state() != b->state()) {
Paul Stewart22aa71b2011-09-16 12:15:11 -0700846 if (DecideBetween(a->IsConnected(), b->IsConnected(), &ret)) {
mukesh agrawalddc378f2012-02-17 18:26:20 -0800847 *reason = kServiceSortIsConnected;
Paul Stewart22aa71b2011-09-16 12:15:11 -0700848 return ret;
849 }
850
Paul Stewarta121c442012-06-09 14:12:58 -0700851 if (DecideBetween(!a->IsPortalled(), !b->IsPortalled(), &ret)) {
852 *reason = kServiceSortIsPortalled;
853 return ret;
854 }
Paul Stewart22aa71b2011-09-16 12:15:11 -0700855
856 if (DecideBetween(a->IsConnecting(), b->IsConnecting(), &ret)) {
mukesh agrawalddc378f2012-02-17 18:26:20 -0800857 *reason = kServiceSortIsConnecting;
Paul Stewart22aa71b2011-09-16 12:15:11 -0700858 return ret;
859 }
mukesh agrawal8a3188d2011-12-01 20:56:44 +0000860
861 if (DecideBetween(!a->IsFailed(), !b->IsFailed(), &ret)) {
mukesh agrawalddc378f2012-02-17 18:26:20 -0800862 *reason = kServiceSortIsFailed;
mukesh agrawal8a3188d2011-12-01 20:56:44 +0000863 return ret;
864 }
Paul Stewart22aa71b2011-09-16 12:15:11 -0700865 }
866
Darin Petkov2f903b32012-04-18 12:56:43 +0200867 if (DecideBetween(a->connectable(), b->connectable(), &ret)) {
868 *reason = kServiceSortConnectable;
869 return ret;
870 }
871
Paul Stewartdf3c0a82012-11-09 15:54:33 -0800872 if (DecideBetween(a->IsDependentOn(b), b->IsDependentOn(a), &ret)) {
873 *reason = kServiceSortDependency;
874 return ret;
875 }
876
Darin Petkov2f903b32012-04-18 12:56:43 +0200877 // Ignore the auto-connect property if both services are connected
878 // already. This allows connected non-autoconnectable VPN services to be
879 // sorted higher than other connected services based on technology order.
880 if (!a->IsConnected() &&
881 DecideBetween(a->auto_connect(), b->auto_connect(), &ret)) {
882 *reason = kServiceSortAutoConnect;
883 return ret;
884 }
885
886 if (DecideBetween(a->favorite(), b->favorite(), &ret)) {
887 *reason = kServiceSortFavorite;
888 return ret;
889 }
890
891 if (DecideBetween(a->priority(), b->priority(), &ret)) {
892 *reason = kServiceSortPriority;
Paul Stewart22aa71b2011-09-16 12:15:11 -0700893 return ret;
894 }
895
896 // TODO(pstew): Below this point we are making value judgements on
897 // services that are not related to anything intrinsic or
898 // user-specified. These heuristics should be richer (contain
899 // historical information, for example) and be subject to user
900 // customization.
Paul Stewart22aa71b2011-09-16 12:15:11 -0700901 for (vector<Technology::Identifier>::const_iterator it = tech_order.begin();
902 it != tech_order.end();
903 ++it) {
Joshua Kroll053fa822012-06-05 09:50:43 -0700904 if (DecideBetween(a->technology() == *it, b->technology() == *it, &ret)) {
mukesh agrawalddc378f2012-02-17 18:26:20 -0800905 *reason = kServiceSortTechnology;
Paul Stewart22aa71b2011-09-16 12:15:11 -0700906 return ret;
mukesh agrawalddc378f2012-02-17 18:26:20 -0800907 }
Paul Stewart22aa71b2011-09-16 12:15:11 -0700908 }
909
mukesh agrawal43970a22013-02-15 16:00:07 -0800910 if (DecideBetween(a->SecurityLevel(), b->SecurityLevel(), &ret) ||
Paul Stewart22aa71b2011-09-16 12:15:11 -0700911 DecideBetween(a->strength(), b->strength(), &ret)) {
mukesh agrawalddc378f2012-02-17 18:26:20 -0800912 *reason = kServiceSortSecurityEtc;
Paul Stewart22aa71b2011-09-16 12:15:11 -0700913 return ret;
914 }
915
mukesh agrawalddc378f2012-02-17 18:26:20 -0800916 *reason = kServiceSortUniqueName;
Darin Petkov457728b2013-01-09 09:49:08 +0100917 return a->unique_name() < b->unique_name();
Paul Stewart22aa71b2011-09-16 12:15:11 -0700918}
919
Chris Masone34af2182011-08-22 11:59:36 -0700920const ProfileRefPtr &Service::profile() const { return profile_; }
921
922void Service::set_profile(const ProfileRefPtr &p) { profile_ = p; }
923
Philipp Neubeck79173602012-11-13 21:10:09 +0100924void Service::SetProfile(const ProfileRefPtr &p) {
925 SLOG(Service, 2) << "SetProfile from "
926 << (profile_ ? profile_->GetFriendlyName() : "")
927 << " to " << (p ? p->GetFriendlyName() : "");
mukesh agrawalbebf1b82013-04-23 15:06:33 -0700928 if (profile_ == p) {
929 return;
930 }
Philipp Neubeck79173602012-11-13 21:10:09 +0100931 profile_ = p;
932 Error error;
933 string profile_rpc_id = GetProfileRpcId(&error);
934 if (!error.IsSuccess()) {
935 return;
936 }
937 adaptor_->EmitStringChanged(flimflam::kProfileProperty, profile_rpc_id);
938}
939
Paul Stewartff14b022012-04-24 20:06:23 -0700940void Service::OnPropertyChanged(const string &property) {
Paul Stewartc43cbbe2013-04-11 06:29:30 -0700941 if (Is8021x() && EapCredentials::IsEapAuthenticationProperty(property)) {
942 OnEapCredentialsChanged();
Paul Stewart81426132012-05-16 10:05:10 -0700943 }
mukesh agrawalcf24a242012-05-21 16:46:11 -0700944 SaveToProfile();
Paul Stewartd215af62012-04-24 23:25:50 -0700945 if ((property == flimflam::kCheckPortalProperty ||
946 property == flimflam::kProxyConfigProperty) &&
947 (state_ == kStateConnected ||
948 state_ == kStatePortal ||
949 state_ == kStateOnline)) {
950 manager_->RecheckPortalOnService(this);
951 }
Paul Stewartff14b022012-04-24 20:06:23 -0700952}
953
Christopher Wiley0801d192012-09-24 11:57:15 -0700954void Service::OnAfterResume() {
955 // Forget old autoconnect failures across suspend/resume.
956 auto_connect_cooldown_milliseconds_ = 0;
957 reenable_auto_connect_task_.Cancel();
Christopher Wileya4c61ae2012-10-01 11:04:30 -0700958 // Forget if the user disconnected us, we might be able to connect now.
959 explicitly_disconnected_ = false;
Christopher Wiley0801d192012-09-24 11:57:15 -0700960}
961
Paul Stewart10241e32012-04-23 18:15:06 -0700962string Service::GetIPConfigRpcIdentifier(Error *error) {
963 if (!connection_) {
964 error->Populate(Error::kNotFound);
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700965 return DBusAdaptor::kNullPath;
Paul Stewart10241e32012-04-23 18:15:06 -0700966 }
967
968 string id = connection_->ipconfig_rpc_identifier();
969
970 if (id.empty()) {
971 // Do not return an empty IPConfig.
972 error->Populate(Error::kNotFound);
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700973 return DBusAdaptor::kNullPath;
Paul Stewart10241e32012-04-23 18:15:06 -0700974 }
975
976 return id;
977}
978
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700979void Service::SetConnectable(bool connectable) {
980 if (connectable_ == connectable)
981 return;
mukesh agrawal29c13a12011-11-24 00:09:19 +0000982 connectable_ = connectable;
983 adaptor_->EmitBoolChanged(flimflam::kConnectableProperty, connectable_);
984}
985
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700986void Service::SetConnectableFull(bool connectable) {
Darin Petkovb2ba39f2012-06-06 10:33:43 +0200987 if (connectable_ == connectable) {
988 return;
989 }
mukesh agrawalcbfb34e2013-04-17 19:33:25 -0700990 SetConnectable(connectable);
Darin Petkovb2ba39f2012-06-06 10:33:43 +0200991 if (manager_->HasService(this)) {
992 manager_->UpdateService(this);
993 }
994}
995
Darin Petkov58f0b6d2012-06-12 12:52:30 +0200996string Service::GetStateString() const {
mukesh agrawalf2f68a52011-09-01 12:15:48 -0700997 switch (state_) {
Gaurav Shahc6d6c722011-11-17 18:59:39 -0800998 case kStateIdle:
999 return flimflam::kStateIdle;
1000 case kStateAssociating:
1001 return flimflam::kStateAssociation;
1002 case kStateConfiguring:
1003 return flimflam::kStateConfiguration;
mukesh agrawalf2f68a52011-09-01 12:15:48 -07001004 case kStateConnected:
Paul Stewart20088d82012-02-16 06:58:55 -08001005 return flimflam::kStateReady;
Gaurav Shahc6d6c722011-11-17 18:59:39 -08001006 case kStateFailure:
1007 return flimflam::kStateFailure;
Paul Stewart20088d82012-02-16 06:58:55 -08001008 case kStatePortal:
1009 return flimflam::kStatePortal;
Gaurav Shahc6d6c722011-11-17 18:59:39 -08001010 case kStateOnline:
1011 return flimflam::kStateOnline;
1012 case kStateUnknown:
mukesh agrawalf2f68a52011-09-01 12:15:48 -07001013 default:
Gaurav Shahc6d6c722011-11-17 18:59:39 -08001014 return "";
mukesh agrawalf2f68a52011-09-01 12:15:48 -07001015 }
1016}
1017
Darin Petkov58f0b6d2012-06-12 12:52:30 +02001018string Service::CalculateState(Error */*error*/) {
1019 return GetStateString();
1020}
1021
mukesh agrawalbf14e942012-03-02 14:36:34 -08001022bool Service::IsAutoConnectable(const char **reason) const {
1023 if (!connectable()) {
1024 *reason = kAutoConnNotConnectable;
1025 return false;
1026 }
1027
1028 if (IsConnected()) {
1029 *reason = kAutoConnConnected;
1030 return false;
1031 }
1032
1033 if (IsConnecting()) {
1034 *reason = kAutoConnConnecting;
1035 return false;
1036 }
1037
1038 if (explicitly_disconnected_) {
1039 *reason = kAutoConnExplicitDisconnect;
1040 return false;
1041 }
1042
Christopher Wiley0801d192012-09-24 11:57:15 -07001043 if (!reenable_auto_connect_task_.IsCancelled()) {
1044 *reason = kAutoConnThrottled;
1045 return false;
1046 }
1047
Darin Petkov4cbff5b2013-01-29 16:29:05 +01001048 if (!Technology::IsPrimaryConnectivityTechnology(technology_) &&
1049 !manager_->IsOnline()) {
1050 *reason = kAutoConnOffline;
1051 return false;
1052 }
1053
mukesh agrawalbf14e942012-03-02 14:36:34 -08001054 return true;
mukesh agrawal76d13882012-01-12 15:23:11 -08001055}
1056
Paul Stewartd215af62012-04-24 23:25:50 -07001057bool Service::IsPortalDetectionDisabled() const {
1058 return check_portal_ == kCheckPortalFalse;
1059}
1060
1061bool Service::IsPortalDetectionAuto() const {
1062 return check_portal_ == kCheckPortalAuto;
1063}
1064
mukesh agrawalffa3d042011-10-06 15:26:10 -07001065void Service::HelpRegisterDerivedBool(
1066 const string &name,
Gaurav Shah1b7a6162011-11-09 11:41:01 -08001067 bool(Service::*get)(Error *),
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001068 bool(Service::*set)(const bool&, Error *)) {
Chris Masone27c4aa52011-07-02 13:10:14 -07001069 store_.RegisterDerivedBool(
1070 name,
1071 BoolAccessor(new CustomAccessor<Service, bool>(this, get, set)));
Chris Masone3bd3c8c2011-06-13 08:20:26 -07001072}
1073
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001074void Service::HelpRegisterDerivedInt32(
1075 const string &name,
1076 int32(Service::*get)(Error *),
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001077 bool(Service::*set)(const int32&, Error *)) {
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001078 store_.RegisterDerivedInt32(
1079 name,
1080 Int32Accessor(new CustomAccessor<Service, int32>(this, get, set)));
1081}
1082
mukesh agrawalffa3d042011-10-06 15:26:10 -07001083void Service::HelpRegisterDerivedString(
1084 const string &name,
Gaurav Shah1b7a6162011-11-09 11:41:01 -08001085 string(Service::*get)(Error *),
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001086 bool(Service::*set)(const string&, Error *)) {
Chris Masone27c4aa52011-07-02 13:10:14 -07001087 store_.RegisterDerivedString(
1088 name,
1089 StringAccessor(new CustomAccessor<Service, string>(this, get, set)));
Chris Masone3bd3c8c2011-06-13 08:20:26 -07001090}
1091
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001092void Service::HelpRegisterConstDerivedRpcIdentifier(
Jason Glasgowacdc11f2012-03-30 14:12:22 -04001093 const string &name,
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001094 RpcIdentifier(Service::*get)(Error *)) {
Jason Glasgowacdc11f2012-03-30 14:12:22 -04001095 store_.RegisterDerivedRpcIdentifier(
1096 name,
1097 RpcIdentifierAccessor(new CustomAccessor<Service, RpcIdentifier>(
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001098 this, get, NULL)));
Jason Glasgowacdc11f2012-03-30 14:12:22 -04001099}
1100
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001101void Service::HelpRegisterConstDerivedUint16(
Paul Stewartbe5f5b32011-12-07 17:11:11 -08001102 const string &name,
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001103 uint16(Service::*get)(Error *)) {
Paul Stewartbe5f5b32011-12-07 17:11:11 -08001104 store_.RegisterDerivedUint16(
1105 name,
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001106 Uint16Accessor(new CustomAccessor<Service, uint16>(this, get, NULL)));
Paul Stewartbe5f5b32011-12-07 17:11:11 -08001107}
1108
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001109void Service::HelpRegisterConstDerivedStrings(
1110 const string &name, Strings(Service::*get)(Error *error)) {
1111 store_.RegisterDerivedStrings(
1112 name,
1113 StringsAccessor(new CustomAccessor<Service, Strings>(this, get, NULL)));
1114}
1115
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001116// static
Darin Petkovba40dd32011-07-11 20:06:39 -07001117void Service::SaveString(StoreInterface *storage,
Chris Masone34af2182011-08-22 11:59:36 -07001118 const string &id,
Darin Petkovba40dd32011-07-11 20:06:39 -07001119 const string &key,
1120 const string &value,
1121 bool crypted,
1122 bool save) {
1123 if (value.empty() || !save) {
Chris Masone34af2182011-08-22 11:59:36 -07001124 storage->DeleteKey(id, key);
Darin Petkovba40dd32011-07-11 20:06:39 -07001125 return;
1126 }
1127 if (crypted) {
Chris Masone34af2182011-08-22 11:59:36 -07001128 storage->SetCryptedString(id, key, value);
Darin Petkovba40dd32011-07-11 20:06:39 -07001129 return;
1130 }
Chris Masone34af2182011-08-22 11:59:36 -07001131 storage->SetString(id, key, value);
Darin Petkovba40dd32011-07-11 20:06:39 -07001132}
1133
Paul Stewart967eaeb2013-04-25 19:53:07 -07001134map<string, string> Service::GetLoadableProfileEntries() {
1135 return manager_->GetLoadableProfileEntriesForService(this);
1136}
1137
Paul Stewartcb59fed2012-03-21 21:14:46 -07001138void Service::IgnoreParameterForConfigure(const string &parameter) {
1139 parameters_ignored_for_configure_.insert(parameter);
1140}
1141
Paul Stewartac4ac002011-08-26 12:04:26 -07001142const string &Service::GetEAPKeyManagement() const {
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001143 CHECK(eap());
1144 return eap()->key_management();
Paul Stewartac4ac002011-08-26 12:04:26 -07001145}
1146
1147void Service::SetEAPKeyManagement(const string &key_management) {
Paul Stewartc43cbbe2013-04-11 06:29:30 -07001148 CHECK(mutable_eap());
1149 mutable_eap()->SetKeyManagement(key_management, NULL);
Paul Stewartac4ac002011-08-26 12:04:26 -07001150}
1151
Thieu Le284fe792012-01-31 17:53:19 -08001152bool Service::GetAutoConnect(Error */*error*/) {
1153 return auto_connect();
1154}
1155
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001156bool Service::SetAutoConnectFull(const bool &connect, Error */*error*/) {
Darin Petkov36d962d2013-03-25 13:03:14 +01001157 LOG(INFO) << "Service " << unique_name() << ": AutoConnect="
1158 << auto_connect() << "->" << connect;
1159 if (auto_connect() == connect) {
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001160 return false;
Darin Petkov36d962d2013-03-25 13:03:14 +01001161 }
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001162 SetAutoConnect(connect);
Darin Petkov36d962d2013-03-25 13:03:14 +01001163 manager_->UpdateService(this);
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001164 return true;
Thieu Le284fe792012-01-31 17:53:19 -08001165}
1166
Paul Stewartd215af62012-04-24 23:25:50 -07001167string Service::GetCheckPortal(Error *error) {
1168 return check_portal_;
1169}
1170
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001171bool Service::SetCheckPortal(const string &check_portal, Error *error) {
Paul Stewartd215af62012-04-24 23:25:50 -07001172 if (check_portal != kCheckPortalFalse &&
1173 check_portal != kCheckPortalTrue &&
1174 check_portal != kCheckPortalAuto) {
1175 Error::PopulateAndLog(error, Error::kInvalidArguments,
1176 base::StringPrintf(
1177 "Invalid Service CheckPortal property value: %s",
1178 check_portal.c_str()));
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001179 return false;
1180 }
1181 if (check_portal == check_portal_) {
1182 return false;
Paul Stewartd215af62012-04-24 23:25:50 -07001183 }
1184 check_portal_ = check_portal;
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001185 return true;
Paul Stewartd215af62012-04-24 23:25:50 -07001186}
1187
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001188string Service::GetGuid(Error *error) {
1189 return guid_;
1190}
1191
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001192bool Service::SetGuid(const string &guid, Error */*error*/) {
1193 if (guid_ == guid) {
1194 return false;
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001195 }
1196 guid_ = guid;
1197 adaptor_->EmitStringChanged(flimflam::kGuidProperty, guid_);
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001198 return true;
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001199}
1200
1201void Service::MarkAsFavorite() {
1202 favorite_ = true;
1203 adaptor_->EmitBoolChanged(flimflam::kFavoriteProperty, favorite_);
1204}
1205
mukesh agrawal43970a22013-02-15 16:00:07 -08001206void Service::SetSecurity(CryptoAlgorithm crypto_algorithm, bool key_rotation,
1207 bool endpoint_auth) {
1208 crypto_algorithm_ = crypto_algorithm;
1209 key_rotation_ = key_rotation;
1210 endpoint_auth_ = endpoint_auth;
1211}
1212
mukesh agrawald4dc0832013-03-25 14:38:26 -07001213string Service::GetNameProperty(Error */*error*/) {
Paul Stewart0c438332012-04-11 07:55:27 -07001214 return friendly_name_;
1215}
1216
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001217bool Service::SetNameProperty(const string &name, Error *error) {
Paul Stewart0c438332012-04-11 07:55:27 -07001218 if (name != friendly_name_) {
1219 Error::PopulateAndLog(error, Error::kInvalidArguments,
Paul Stewart2bf424f2012-04-11 18:59:39 -07001220 base::StringPrintf(
Darin Petkov457728b2013-01-09 09:49:08 +01001221 "Service %s Name property cannot be modified.",
1222 unique_name_.c_str()));
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001223 return false;
Paul Stewart0c438332012-04-11 07:55:27 -07001224 }
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001225 return false;
Paul Stewart0c438332012-04-11 07:55:27 -07001226}
1227
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001228int32 Service::GetPriority(Error *error) {
1229 return priority_;
1230}
1231
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001232bool Service::SetPriority(const int32 &priority, Error *error) {
1233 if (priority_ == priority) {
1234 return false;
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001235 }
1236 priority_ = priority;
1237 adaptor_->EmitIntChanged(flimflam::kPriorityProperty, priority_);
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001238 return true;
mukesh agrawalcbfb34e2013-04-17 19:33:25 -07001239}
1240
Paul Stewart1b1a7f22012-01-06 16:24:06 -08001241string Service::GetProfileRpcId(Error *error) {
1242 if (!profile_) {
1243 // This happens in some unit tests where profile_ is not set.
1244 error->Populate(Error::kNotFound);
1245 return "";
1246 }
1247 return profile_->GetRpcIdentifier();
1248}
1249
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001250bool Service::SetProfileRpcId(const string &profile, Error *error) {
1251 if (profile_ && profile_->GetRpcIdentifier() == profile) {
1252 return false;
1253 }
1254 ProfileConstRefPtr old_profile = profile_;
1255 // No need to Emit afterwards, since SetProfileForService will call
1256 // into SetProfile (if the profile actually changes).
Paul Stewart1b1a7f22012-01-06 16:24:06 -08001257 manager_->SetProfileForService(this, profile, error);
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001258 // Can't just use error.IsSuccess(), because that also requires saving
1259 // the profile to succeed. (See Profile::AdoptService)
1260 return (profile_ != old_profile);
Paul Stewart1b1a7f22012-01-06 16:24:06 -08001261}
1262
Paul Stewartbe5f5b32011-12-07 17:11:11 -08001263uint16 Service::GetHTTPProxyPort(Error */*error*/) {
1264 if (http_proxy_.get()) {
1265 return static_cast<uint16>(http_proxy_->proxy_port());
1266 }
1267 return 0;
1268}
1269
Philipp Neubeck79173602012-11-13 21:10:09 +01001270string Service::GetProxyConfig(Error *error) {
1271 return proxy_config_;
1272}
1273
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001274bool Service::SetProxyConfig(const string &proxy_config, Error *error) {
1275 if (proxy_config_ == proxy_config)
1276 return false;
Philipp Neubeck79173602012-11-13 21:10:09 +01001277 proxy_config_ = proxy_config;
1278 adaptor_->EmitStringChanged(flimflam::kProxyConfigProperty, proxy_config_);
mukesh agrawalbebf1b82013-04-23 15:06:33 -07001279 return true;
Philipp Neubeck79173602012-11-13 21:10:09 +01001280}
1281
Darin Petkov0c65bdd2012-12-05 13:42:41 +01001282// static
1283Strings Service::ExtractWallClockToStrings(
1284 const deque<Timestamp> &timestamps) {
1285 Strings strings;
1286 for (deque<Timestamp>::const_iterator it = timestamps.begin();
1287 it != timestamps.end(); ++it) {
1288 strings.push_back(it->wall_clock);
1289 }
1290 return strings;
1291}
1292
1293Strings Service::GetDisconnectsProperty(Error */*error*/) {
1294 return ExtractWallClockToStrings(disconnects_);
1295}
1296
1297Strings Service::GetMisconnectsProperty(Error */*error*/) {
1298 return ExtractWallClockToStrings(misconnects_);
1299}
1300
mukesh agrawalcf24a242012-05-21 16:46:11 -07001301void Service::SaveToProfile() {
1302 if (profile_.get() && profile_->GetConstStorage()) {
1303 profile_->UpdateService(this);
1304 }
1305}
1306
Arman Uguray2717a102013-01-29 23:36:06 -08001307void Service::SetFriendlyName(const string &friendly_name) {
1308 if (friendly_name == friendly_name_)
1309 return;
1310 friendly_name_ = friendly_name;
1311 adaptor()->EmitStringChanged(flimflam::kNameProperty, friendly_name_);
1312}
1313
Darin Petkovd78ee7e2012-01-12 11:21:10 +01001314void Service::SetStrength(uint8 strength) {
1315 if (strength == strength_) {
1316 return;
1317 }
1318 strength_ = strength;
1319 adaptor_->EmitUint8Changed(flimflam::kSignalStrengthProperty, strength);
1320}
1321
Darin Petkovaba89322013-03-11 14:48:22 +01001322void Service::SetErrorDetails(const string &details) {
1323 if (error_details_ == details) {
1324 return;
1325 }
1326 error_details_ = details;
1327 adaptor_->EmitStringChanged(shill::kErrorDetailsProperty, error_details_);
1328}
1329
Paul Stewartf2d60912012-07-15 08:37:30 -07001330void Service::UpdateErrorProperty() {
1331 const string error(ConnectFailureToString(failure_));
1332 if (error == error_) {
1333 return;
1334 }
1335 error_ = error;
1336 adaptor_->EmitStringChanged(flimflam::kErrorProperty, error);
1337}
1338
Paul Stewart75897df2011-04-27 09:05:53 -07001339} // namespace shill