blob: d7824ace7c0ae77046167a45e23bb754ad16f642 [file] [log] [blame]
Paul Stewart75897df2011-04-27 09:05:53 -07001// Copyright (c) 2011 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Chris Masone8fe2c7e2011-06-09 15:51:19 -07005#include "shill/manager.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
Paul Stewart22aa71b2011-09-16 12:15:11 -070010#include <algorithm>
mukesh agrawal7a4e4002011-09-06 11:26:05 -070011#include <map>
Paul Stewart75897df2011-04-27 09:05:53 -070012#include <string>
Chris Masone52cd19b2011-06-29 17:23:04 -070013#include <vector>
Paul Stewart75897df2011-04-27 09:05:53 -070014
Paul Stewarte6132022011-08-16 09:11:02 -070015#include <base/file_util.h>
Chris Masoneee929b72011-05-10 10:02:18 -070016#include <base/logging.h>
Chris Masone9be4a9d2011-05-16 15:44:09 -070017#include <base/memory/ref_counted.h>
Gaurav Shah435de2c2011-11-17 19:01:07 -080018#include <base/stl_util-inl.h>
Paul Stewart22aa71b2011-09-16 12:15:11 -070019#include <base/string_split.h>
20#include <base/string_util.h>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070021#include <chromeos/dbus/service_constants.h>
Chris Masoneee929b72011-05-10 10:02:18 -070022
Chris Masoned0ceb8c2011-06-02 10:05:39 -070023#include "shill/adaptor_interfaces.h"
Paul Stewart75897df2011-04-27 09:05:53 -070024#include "shill/control_interface.h"
Chris Masoned0ceb8c2011-06-02 10:05:39 -070025#include "shill/dbus_adaptor.h"
Chris Masone7aa5f902011-07-11 11:13:35 -070026#include "shill/default_profile.h"
Chris Masone9be4a9d2011-05-16 15:44:09 -070027#include "shill/device.h"
28#include "shill/device_info.h"
Chris Masone6791a432011-07-12 13:23:19 -070029#include "shill/ephemeral_profile.h"
Chris Masone8fe2c7e2011-06-09 15:51:19 -070030#include "shill/error.h"
Paul Stewart26b327e2011-10-19 11:38:09 -070031#include "shill/event_dispatcher.h"
Chris Masone9d779932011-08-25 16:33:41 -070032#include "shill/key_file_store.h"
Paul Stewart22aa71b2011-09-16 12:15:11 -070033#include "shill/service_sorter.h"
Chris Masone7aa5f902011-07-11 11:13:35 -070034#include "shill/profile.h"
Chris Masoneb925cc82011-06-22 15:39:57 -070035#include "shill/property_accessor.h"
Paul Stewarte6132022011-08-16 09:11:02 -070036#include "shill/resolver.h"
Chris Masone9be4a9d2011-05-16 15:44:09 -070037#include "shill/service.h"
mukesh agrawal7a4e4002011-09-06 11:26:05 -070038#include "shill/wifi.h"
39#include "shill/wifi_service.h"
Paul Stewart75897df2011-04-27 09:05:53 -070040
Paul Stewart22aa71b2011-09-16 12:15:11 -070041using std::map;
Gaurav Shah435de2c2011-11-17 19:01:07 -080042using std::set;
Paul Stewart75897df2011-04-27 09:05:53 -070043using std::string;
Chris Masone9be4a9d2011-05-16 15:44:09 -070044using std::vector;
Paul Stewart75897df2011-04-27 09:05:53 -070045
46namespace shill {
Paul Stewarte6132022011-08-16 09:11:02 -070047
mukesh agrawal7a4e4002011-09-06 11:26:05 -070048// static
49const char Manager::kManagerErrorNoDevice[] = "no wifi devices available";
50
Paul Stewart75897df2011-04-27 09:05:53 -070051Manager::Manager(ControlInterface *control_interface,
Darin Petkov887f2982011-07-14 16:10:17 -070052 EventDispatcher *dispatcher,
Chris Masone2ae797d2011-08-23 20:41:00 -070053 GLib *glib,
54 const string &run_directory,
55 const string &storage_directory,
56 const string &user_storage_format)
57 : run_path_(FilePath(run_directory)),
58 storage_path_(FilePath(storage_directory)),
59 user_storage_format_(user_storage_format),
Paul Stewarte6132022011-08-16 09:11:02 -070060 adaptor_(control_interface->CreateManagerAdaptor(this)),
Paul Stewartb50f0b92011-05-16 16:31:42 -070061 device_info_(control_interface, dispatcher, this),
Darin Petkov887f2982011-07-14 16:10:17 -070062 modem_info_(control_interface, dispatcher, this, glib),
Chris Masone6791a432011-07-12 13:23:19 -070063 running_(false),
Paul Stewart5dc40aa2011-10-28 19:43:43 -070064 connect_profiles_to_rpc_(true),
Chris Masone9d779932011-08-25 16:33:41 -070065 ephemeral_profile_(new EphemeralProfile(control_interface, this)),
Chris Masone2ae797d2011-08-23 20:41:00 -070066 control_interface_(control_interface),
67 glib_(glib) {
Chris Masone7aa5f902011-07-11 11:13:35 -070068 HelpRegisterDerivedString(flimflam::kActiveProfileProperty,
69 &Manager::GetActiveProfileName,
70 NULL);
Chris Masone27c4aa52011-07-02 13:10:14 -070071 HelpRegisterDerivedStrings(flimflam::kAvailableTechnologiesProperty,
72 &Manager::AvailableTechnologies,
73 NULL);
Chris Masone88cbd5f2011-07-03 14:30:04 -070074 store_.RegisterString(flimflam::kCheckPortalListProperty,
75 &props_.check_portal_list);
Chris Masone27c4aa52011-07-02 13:10:14 -070076 HelpRegisterDerivedStrings(flimflam::kConnectedTechnologiesProperty,
77 &Manager::ConnectedTechnologies,
78 NULL);
Chris Masone88cbd5f2011-07-03 14:30:04 -070079 store_.RegisterString(flimflam::kCountryProperty, &props_.country);
Chris Masone27c4aa52011-07-02 13:10:14 -070080 HelpRegisterDerivedString(flimflam::kDefaultTechnologyProperty,
81 &Manager::DefaultTechnology,
82 NULL);
Chris Masone27c4aa52011-07-02 13:10:14 -070083 HelpRegisterDerivedStrings(flimflam::kDevicesProperty,
84 &Manager::EnumerateDevices,
85 NULL);
Chris Masone88cbd5f2011-07-03 14:30:04 -070086 HelpRegisterDerivedStrings(flimflam::kEnabledTechnologiesProperty,
87 &Manager::EnabledTechnologies,
88 NULL);
89 store_.RegisterBool(flimflam::kOfflineModeProperty, &props_.offline_mode);
90 store_.RegisterString(flimflam::kPortalURLProperty, &props_.portal_url);
91 HelpRegisterDerivedString(flimflam::kStateProperty,
92 &Manager::CalculateState,
93 NULL);
Chris Masone27c4aa52011-07-02 13:10:14 -070094 HelpRegisterDerivedStrings(flimflam::kServicesProperty,
95 &Manager::EnumerateAvailableServices,
96 NULL);
97 HelpRegisterDerivedStrings(flimflam::kServiceWatchListProperty,
98 &Manager::EnumerateWatchedServices,
99 NULL);
Chris Masone3c3f6a12011-07-01 10:01:41 -0700100
Chris Masone4d42df82011-07-02 17:09:39 -0700101 // TODO(cmasone): Wire these up once we actually put in profile support.
Chris Masoneb925cc82011-06-22 15:39:57 -0700102 // known_properties_.push_back(flimflam::kProfilesProperty);
Chris Masoneb07006b2011-05-14 16:10:04 -0700103 VLOG(2) << "Manager initialized.";
Paul Stewart75897df2011-04-27 09:05:53 -0700104}
105
Chris Masone6791a432011-07-12 13:23:19 -0700106Manager::~Manager() {
Chris Masone9d779932011-08-25 16:33:41 -0700107 profiles_.clear();
Chris Masone6791a432011-07-12 13:23:19 -0700108}
Paul Stewart75897df2011-04-27 09:05:53 -0700109
mukesh agrawal8f317b62011-07-15 11:53:23 -0700110void Manager::AddDeviceToBlackList(const string &device_name) {
111 device_info_.AddDeviceToBlackList(device_name);
112}
113
Paul Stewart75897df2011-04-27 09:05:53 -0700114void Manager::Start() {
Paul Stewart0af98bf2011-05-10 17:38:08 -0700115 LOG(INFO) << "Manager started.";
Paul Stewarte6132022011-08-16 09:11:02 -0700116
Chris Masone2ae797d2011-08-23 20:41:00 -0700117 CHECK(file_util::CreateDirectory(run_path_)) << run_path_.value();
Paul Stewarte6132022011-08-16 09:11:02 -0700118 Resolver::GetInstance()->set_path(run_path_.Append("resolv.conf"));
Chris Masone2ae797d2011-08-23 20:41:00 -0700119
120 CHECK(file_util::CreateDirectory(storage_path_)) << storage_path_.value();
121
Chris Masoneb9c00592011-10-06 13:10:39 -0700122 profiles_.push_back(new DefaultProfile(control_interface_,
123 this,
124 storage_path_,
125 props_));
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700126 CHECK(profiles_[0]->InitStorage(glib_, Profile::kCreateOrOpenExisting, NULL));
Chris Masoneb9c00592011-10-06 13:10:39 -0700127
Paul Stewart75897df2011-04-27 09:05:53 -0700128 running_ = true;
Chris Masone413a3192011-05-09 17:10:05 -0700129 adaptor_->UpdateRunning();
Paul Stewart0af98bf2011-05-10 17:38:08 -0700130 device_info_.Start();
Darin Petkov887f2982011-07-14 16:10:17 -0700131 modem_info_.Start();
Paul Stewart75897df2011-04-27 09:05:53 -0700132}
133
134void Manager::Stop() {
135 running_ = false;
Chris Masone9d779932011-08-25 16:33:41 -0700136 // Persist profile, device, service information to disk.
137 vector<ProfileRefPtr>::iterator it;
138 for (it = profiles_.begin(); it != profiles_.end(); ++it) {
Chris Masone6515aab2011-10-12 16:19:09 -0700139 (*it)->Save();
Chris Masone9d779932011-08-25 16:33:41 -0700140 }
Chris Masone9d779932011-08-25 16:33:41 -0700141
Thieu Le1271d682011-11-02 22:48:19 +0000142 vector<ServiceRefPtr>::iterator services_it;
143 for (services_it = services_.begin(); services_it != services_.end();
144 ++services_it) {
145 (*services_it)->Disconnect();
146 }
147
Chris Masone413a3192011-05-09 17:10:05 -0700148 adaptor_->UpdateRunning();
Darin Petkov887f2982011-07-14 16:10:17 -0700149 modem_info_.Stop();
150 device_info_.Stop();
Paul Stewart75897df2011-04-27 09:05:53 -0700151}
152
Paul Stewarta41e38d2011-11-11 07:47:29 -0800153void Manager::CreateProfile(const string &name, Error *error) {
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700154 Profile::Identifier ident;
155 if (!Profile::ParseIdentifier(name, &ident)) {
Paul Stewartbe005172011-11-02 18:10:29 -0700156 Error::PopulateAndLog(error, Error::kInvalidArguments,
157 "Invalid profile name " + name);
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700158 return;
159 }
160 ProfileRefPtr profile(new Profile(control_interface_,
161 this,
162 ident,
163 user_storage_format_,
164 false));
165 if (!profile->InitStorage(glib_, Profile::kCreateNew, error)) {
166 return;
167 }
168
169 // Save profile data out, and then let the scoped pointer fall out of scope.
170 if (!profile->Save()) {
Paul Stewartbe005172011-11-02 18:10:29 -0700171 Error::PopulateAndLog(error, Error::kInternalError,
172 "Profile name " + name + " could not be saved");
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700173 return;
174 }
175}
176
177void Manager::PushProfile(const string &name, Error *error) {
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700178 Profile::Identifier ident;
179 if (!Profile::ParseIdentifier(name, &ident)) {
Paul Stewartbe005172011-11-02 18:10:29 -0700180 Error::PopulateAndLog(error, Error::kInvalidArguments,
181 "Invalid profile name " + name);
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700182 return;
183 }
184
185 for (vector<ProfileRefPtr>::const_iterator it = profiles_.begin();
186 it != profiles_.end();
187 ++it) {
188 if ((*it)->MatchesIdentifier(ident)) {
Paul Stewartbe005172011-11-02 18:10:29 -0700189 Error::PopulateAndLog(error, Error::kAlreadyExists,
190 "Profile name " + name + " is already on stack");
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700191 return;
192 }
193 }
194
195 if (ident.user.empty()) {
196 // The manager will have only one machine-wide profile, and this is the
197 // DefaultProfile. This means no other profiles can be loaded that do
198 // not have a user component.
199 // TODO(pstew): This is all well and good, but WiFi autotests try to
200 // creating a default profile (by a name other than "default") in order
201 // to avoid leaving permanent side effects to devices under test. This
202 // whole thing will need to be reworked in order to allow that to happen,
203 // or the autotests (or their expectations) will need to change.
Paul Stewartbe005172011-11-02 18:10:29 -0700204 Error::PopulateAndLog(error, Error::kInvalidArguments,
205 "Cannot load non-default global profile " + name);
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700206 return;
207 }
208
209 ProfileRefPtr profile(new Profile(control_interface_,
210 this,
211 ident,
212 user_storage_format_,
213 connect_profiles_to_rpc_));
214 if (!profile->InitStorage(glib_, Profile::kOpenExisting, error)) {
215 return;
216 }
217
Paul Stewarta849a3d2011-11-03 05:54:09 -0700218 profiles_.push_back(profile);
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700219
220 // Offer each registered Service the opportunity to join this new Profile.
Paul Stewarta41e38d2011-11-11 07:47:29 -0800221 for (vector<ServiceRefPtr>::iterator it = services_.begin();
222 it != services_.end(); ++it) {
Paul Stewartbba6a5b2011-11-02 18:45:59 -0700223 profile->ConfigureService(*it);
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700224 }
225
Paul Stewarta41e38d2011-11-11 07:47:29 -0800226 // Shop the Profile contents around to Devices which can create
227 // non-visible services.
228 for (vector<DeviceRefPtr>::iterator it = devices_.begin();
229 it != devices_.end(); ++it) {
230 profile->ConfigureDevice(*it);
231 }
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700232}
233
234void Manager::PopProfileInternal() {
235 CHECK(!profiles_.empty());
236 ProfileRefPtr active_profile = profiles_.back();
237 profiles_.pop_back();
238 vector<ServiceRefPtr>::iterator s_it;
239 for (s_it = services_.begin(); s_it != services_.end(); ++s_it) {
240 if ((*s_it)->profile().get() == active_profile.get()) {
241 vector<ProfileRefPtr>::reverse_iterator p_it;
242 for (p_it = profiles_.rbegin(); p_it != profiles_.rend(); ++p_it) {
Paul Stewartbba6a5b2011-11-02 18:45:59 -0700243 if ((*p_it)->ConfigureService(*s_it)) {
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700244 break;
245 }
246 }
247 if (p_it == profiles_.rend()) {
248 ephemeral_profile_->AdoptService(*s_it);
Paul Stewarta41e38d2011-11-11 07:47:29 -0800249 (*s_it)->Unload();
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700250 }
251 }
252 }
253}
254
Paul Stewarta41e38d2011-11-11 07:47:29 -0800255void Manager::PopProfile(const string &name, Error *error) {
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700256 Profile::Identifier ident;
257 if (profiles_.empty()) {
Paul Stewartbe005172011-11-02 18:10:29 -0700258 Error::PopulateAndLog(error, Error::kNotFound, "Profile stack is empty");
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700259 return;
260 }
261 ProfileRefPtr active_profile = profiles_.back();
262 if (!Profile::ParseIdentifier(name, &ident)) {
Paul Stewartbe005172011-11-02 18:10:29 -0700263 Error::PopulateAndLog(error, Error::kInvalidArguments,
264 "Invalid profile name " + name);
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700265 return;
266 }
267 if (!active_profile->MatchesIdentifier(ident)) {
Paul Stewartbe005172011-11-02 18:10:29 -0700268 Error::PopulateAndLog(error, Error::kNotSupported,
269 name + " is not the active profile");
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700270 return;
271 }
272 PopProfileInternal();
273}
274
275void Manager::PopAnyProfile(Error *error) {
276 Profile::Identifier ident;
277 if (profiles_.empty()) {
Paul Stewartbe005172011-11-02 18:10:29 -0700278 Error::PopulateAndLog(error, Error::kNotFound, "Profile stack is empty");
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700279 return;
280 }
281 PopProfileInternal();
282}
283
Chris Masone7aa5f902011-07-11 11:13:35 -0700284const ProfileRefPtr &Manager::ActiveProfile() {
Chris Masoneb9c00592011-10-06 13:10:39 -0700285 DCHECK_NE(profiles_.size(), 0);
Chris Masone7aa5f902011-07-11 11:13:35 -0700286 return profiles_.back();
287}
288
Chris Masone6515aab2011-10-12 16:19:09 -0700289bool Manager::MoveServiceToProfile(const ServiceRefPtr &to_move,
290 const ProfileRefPtr &destination) {
291 const ProfileRefPtr from = to_move->profile();
292 return destination->AdoptService(to_move) &&
293 from->AbandonService(to_move);
Chris Masone6791a432011-07-12 13:23:19 -0700294}
295
Chris Masone2b105542011-06-22 10:58:09 -0700296void Manager::RegisterDevice(const DeviceRefPtr &to_manage) {
Chris Masonec1e50412011-06-07 13:04:53 -0700297 vector<DeviceRefPtr>::iterator it;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700298 for (it = devices_.begin(); it != devices_.end(); ++it) {
Chris Masonec1e50412011-06-07 13:04:53 -0700299 if (to_manage.get() == it->get())
Chris Masone9be4a9d2011-05-16 15:44:09 -0700300 return;
301 }
Chris Masonec1e50412011-06-07 13:04:53 -0700302 devices_.push_back(to_manage);
Paul Stewartf1ce5d22011-05-19 13:10:20 -0700303
Paul Stewarta41e38d2011-11-11 07:47:29 -0800304 // We are applying device properties from the DefaultProfile, and adding
305 // the union of hidden services in all loaded profiles to the device.
Chris Masone6515aab2011-10-12 16:19:09 -0700306 for (vector<ProfileRefPtr>::iterator it = profiles_.begin();
307 it != profiles_.end();
308 ++it) {
Paul Stewarta41e38d2011-11-11 07:47:29 -0800309 // Load device configuration, if any exists, as well as hidden services.
310 (*it)->ConfigureDevice(to_manage);
311
312 // Currently the only profile for which "Save" is implemented is the
313 // DefaultProfile. It iterates over all Devices and stores their state.
314 // We perform the Save now in case the device we have just registered
315 // is new and needs to be added to the stored DefaultProfile.
Chris Masone6515aab2011-10-12 16:19:09 -0700316 (*it)->Save();
317 }
Paul Stewarta41e38d2011-11-11 07:47:29 -0800318
319 // In normal usage, running_ will always be true when we are here, however
320 // unit tests sometimes do things in otherwise invalid states.
321 if (running_ && to_manage->powered())
322 to_manage->Start();
Gaurav Shah435de2c2011-11-17 19:01:07 -0800323
324 Error error;
325 adaptor_->EmitStringsChanged(flimflam::kAvailableTechnologiesProperty,
326 AvailableTechnologies(&error));
327 adaptor_->EmitStringsChanged(flimflam::kEnabledTechnologiesProperty,
328 EnabledTechnologies(&error));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700329}
330
mukesh agrawal5029c6c2011-08-25 11:12:40 -0700331void Manager::DeregisterDevice(const DeviceRefPtr &to_forget) {
Chris Masonec1e50412011-06-07 13:04:53 -0700332 vector<DeviceRefPtr>::iterator it;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700333 for (it = devices_.begin(); it != devices_.end(); ++it) {
Chris Masonec1e50412011-06-07 13:04:53 -0700334 if (to_forget.get() == it->get()) {
mukesh agrawal5029c6c2011-08-25 11:12:40 -0700335 VLOG(2) << "Deregistered device: " << to_forget->UniqueName();
336 to_forget->Stop();
Chris Masone9be4a9d2011-05-16 15:44:09 -0700337 devices_.erase(it);
Gaurav Shah435de2c2011-11-17 19:01:07 -0800338 Error error;
339 adaptor_->EmitStringsChanged(flimflam::kAvailableTechnologiesProperty,
340 AvailableTechnologies(&error));
341 adaptor_->EmitStringsChanged(flimflam::kEnabledTechnologiesProperty,
342 EnabledTechnologies(&error));
Chris Masone9be4a9d2011-05-16 15:44:09 -0700343 return;
344 }
345 }
mukesh agrawal5029c6c2011-08-25 11:12:40 -0700346 VLOG(2) << __func__ << " unknown device: " << to_forget->UniqueName();
Chris Masone9be4a9d2011-05-16 15:44:09 -0700347}
348
Chris Masone2b105542011-06-22 10:58:09 -0700349void Manager::RegisterService(const ServiceRefPtr &to_manage) {
Gaurav Shahc6d6c722011-11-17 18:59:39 -0800350 VLOG(2) << "In " << __func__ << "(): Registering service "
351 << to_manage->UniqueName();
mukesh agrawald835b202011-10-07 15:26:47 -0700352
Paul Stewartbba6a5b2011-11-02 18:45:59 -0700353 bool configured = false;
Paul Stewarta41e38d2011-11-11 07:47:29 -0800354 for (vector<ProfileRefPtr>::reverse_iterator it = profiles_.rbegin();
355 !configured && it != profiles_.rend();
Chris Masone157aa0c2011-10-03 09:24:31 -0700356 ++it) {
Paul Stewartbba6a5b2011-11-02 18:45:59 -0700357 configured = (*it)->ConfigureService(to_manage);
Chris Masone157aa0c2011-10-03 09:24:31 -0700358 }
Chris Masone6791a432011-07-12 13:23:19 -0700359
360 // If not found, add it to the ephemeral profile
Paul Stewartbba6a5b2011-11-02 18:45:59 -0700361 if (!configured)
Chris Masone6515aab2011-10-12 16:19:09 -0700362 ephemeral_profile_->AdoptService(to_manage);
Chris Masone6791a432011-07-12 13:23:19 -0700363
364 // Now add to OUR list.
Chris Masonec1e50412011-06-07 13:04:53 -0700365 vector<ServiceRefPtr>::iterator it;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700366 for (it = services_.begin(); it != services_.end(); ++it) {
mukesh agrawald835b202011-10-07 15:26:47 -0700367 CHECK(to_manage->UniqueName() != (*it)->UniqueName());
Chris Masone9be4a9d2011-05-16 15:44:09 -0700368 }
Chris Masonec1e50412011-06-07 13:04:53 -0700369 services_.push_back(to_manage);
Paul Stewart22aa71b2011-09-16 12:15:11 -0700370 SortServices();
Chris Masone9be4a9d2011-05-16 15:44:09 -0700371}
372
Chris Masone6515aab2011-10-12 16:19:09 -0700373void Manager::DeregisterService(const ServiceRefPtr &to_forget) {
Chris Masonec1e50412011-06-07 13:04:53 -0700374 vector<ServiceRefPtr>::iterator it;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700375 for (it = services_.begin(); it != services_.end(); ++it) {
Chris Masone6791a432011-07-12 13:23:19 -0700376 if (to_forget->UniqueName() == (*it)->UniqueName()) {
Chris Masone9be4a9d2011-05-16 15:44:09 -0700377 services_.erase(it);
Paul Stewart22aa71b2011-09-16 12:15:11 -0700378 SortServices();
Chris Masone9be4a9d2011-05-16 15:44:09 -0700379 return;
380 }
381 }
382}
383
mukesh agrawal00917ce2011-11-22 23:56:55 +0000384void Manager::UpdateService(const ServiceRefPtr &to_update) {
385 CHECK(to_update);
Paul Stewart03dba0b2011-08-22 16:32:45 -0700386 LOG(INFO) << "Service " << to_update->UniqueName() << " updated;"
Gaurav Shahc6d6c722011-11-17 18:59:39 -0800387 << " state: " << Service::ConnectStateToString(to_update->state())
388 << " failure: "
389 << Service::ConnectFailureToString(to_update->failure());
mukesh agrawal00917ce2011-11-22 23:56:55 +0000390 LOG(INFO) << "IsConnected(): " << to_update->IsConnected();
391 if (to_update->IsConnected())
392 to_update->MakeFavorite();
Paul Stewart22aa71b2011-09-16 12:15:11 -0700393 SortServices();
Paul Stewart03dba0b2011-08-22 16:32:45 -0700394}
395
Paul Stewartfdd16072011-09-16 12:41:35 -0700396void Manager::FilterByTechnology(Technology::Identifier tech,
Chris Masonec1e50412011-06-07 13:04:53 -0700397 vector<DeviceRefPtr> *found) {
Chris Masone9be4a9d2011-05-16 15:44:09 -0700398 CHECK(found);
Chris Masonec1e50412011-06-07 13:04:53 -0700399 vector<DeviceRefPtr>::iterator it;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700400 for (it = devices_.begin(); it != devices_.end(); ++it) {
401 if ((*it)->TechnologyIs(tech))
402 found->push_back(*it);
403 }
404}
405
Paul Stewart22aa71b2011-09-16 12:15:11 -0700406ServiceRefPtr Manager::FindService(const string& name) {
Chris Masonec1e50412011-06-07 13:04:53 -0700407 vector<ServiceRefPtr>::iterator it;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700408 for (it = services_.begin(); it != services_.end(); ++it) {
Chris Masone6791a432011-07-12 13:23:19 -0700409 if (name == (*it)->UniqueName())
Chris Masonee0dea762011-06-09 09:06:03 -0700410 return *it;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700411 }
Chris Masonee0dea762011-06-09 09:06:03 -0700412 return NULL;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700413}
414
mukesh agrawalffa3d042011-10-06 15:26:10 -0700415void Manager::HelpRegisterDerivedString(
416 const string &name,
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800417 string(Manager::*get)(Error *),
mukesh agrawalffa3d042011-10-06 15:26:10 -0700418 void(Manager::*set)(const string&, Error *)) {
Chris Masone27c4aa52011-07-02 13:10:14 -0700419 store_.RegisterDerivedString(
420 name,
421 StringAccessor(new CustomAccessor<Manager, string>(this, get, set)));
Chris Masoneb925cc82011-06-22 15:39:57 -0700422}
423
mukesh agrawalffa3d042011-10-06 15:26:10 -0700424void Manager::HelpRegisterDerivedStrings(
425 const string &name,
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800426 Strings(Manager::*get)(Error *),
mukesh agrawalffa3d042011-10-06 15:26:10 -0700427 void(Manager::*set)(const Strings &, Error *)) {
Chris Masone27c4aa52011-07-02 13:10:14 -0700428 store_.RegisterDerivedStrings(
429 name,
430 StringsAccessor(new CustomAccessor<Manager, Strings>(this, get, set)));
Chris Masoneb925cc82011-06-22 15:39:57 -0700431}
432
Paul Stewart22aa71b2011-09-16 12:15:11 -0700433void Manager::SortServices() {
434 sort(services_.begin(), services_.end(), ServiceSorter(technology_order_));
Paul Stewarta41e38d2011-11-11 07:47:29 -0800435
436 vector<string> service_paths;
437 vector<ServiceRefPtr>::iterator it;
438 for (it = services_.begin(); it != services_.end(); ++it) {
439 if ((*it)->IsVisible()) {
440 service_paths.push_back((*it)->GetRpcIdentifier());
441 }
442 }
443 adaptor_->EmitRpcIdentifierArrayChanged(flimflam::kServicesProperty,
444 service_paths);
Gaurav Shah435de2c2011-11-17 19:01:07 -0800445
446 Error error;
447 adaptor_->EmitStringsChanged(flimflam::kConnectedTechnologiesProperty,
448 ConnectedTechnologies(&error));
449 adaptor_->EmitStringChanged(flimflam::kDefaultTechnologyProperty,
450 DefaultTechnology(&error));
Paul Stewart22aa71b2011-09-16 12:15:11 -0700451}
452
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800453string Manager::CalculateState(Error */*error*/) {
Chris Masoneb925cc82011-06-22 15:39:57 -0700454 return flimflam::kStateOffline;
455}
456
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800457vector<string> Manager::AvailableTechnologies(Error */*error*/) {
Gaurav Shah435de2c2011-11-17 19:01:07 -0800458 set<string> unique_technologies;
459 for (vector<DeviceRefPtr>::iterator it = devices_.begin();
460 it != devices_.end(); ++it) {
461 unique_technologies.insert(
462 Technology::NameFromIdentifier((*it)->technology()));
463 }
464 return vector<string>(unique_technologies.begin(), unique_technologies.end());
Chris Masoneb925cc82011-06-22 15:39:57 -0700465}
466
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800467vector<string> Manager::ConnectedTechnologies(Error */*error*/) {
Gaurav Shah435de2c2011-11-17 19:01:07 -0800468 set<string> unique_technologies;
469 for (vector<DeviceRefPtr>::iterator it = devices_.begin();
470 it != devices_.end(); ++it) {
471 if ((*it)->IsConnected())
472 unique_technologies.insert(
473 Technology::NameFromIdentifier((*it)->technology()));
474 }
475 return vector<string>(unique_technologies.begin(), unique_technologies.end());
Chris Masoneb925cc82011-06-22 15:39:57 -0700476}
477
Gaurav Shah435de2c2011-11-17 19:01:07 -0800478string Manager::DefaultTechnology(Error *error) {
479 return (!services_.empty() && services_[0]->IsConnected()) ?
480 services_[0]->GetTechnologyString(error) : "";
Chris Masoneb925cc82011-06-22 15:39:57 -0700481}
482
Gaurav Shah435de2c2011-11-17 19:01:07 -0800483vector<string> Manager::EnabledTechnologies(Error *error) {
484 // TODO(gauravsh): This must be wired up to the RPC interface to handle
485 // enabled/disabled devices as set by the user. crosbug.com/23319
486 return AvailableTechnologies(error);
Chris Masoneb925cc82011-06-22 15:39:57 -0700487}
488
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800489vector<string> Manager::EnumerateDevices(Error */*error*/) {
Chris Masone3c3f6a12011-07-01 10:01:41 -0700490 vector<string> device_rpc_ids;
491 for (vector<DeviceRefPtr>::const_iterator it = devices_.begin();
492 it != devices_.end();
493 ++it) {
494 device_rpc_ids.push_back((*it)->GetRpcIdentifier());
495 }
496 return device_rpc_ids;
497}
498
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800499vector<string> Manager::EnumerateAvailableServices(Error */*error*/) {
Chris Masone3c3f6a12011-07-01 10:01:41 -0700500 vector<string> service_rpc_ids;
501 for (vector<ServiceRefPtr>::const_iterator it = services_.begin();
502 it != services_.end();
503 ++it) {
504 service_rpc_ids.push_back((*it)->GetRpcIdentifier());
505 }
506 return service_rpc_ids;
507}
508
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800509vector<string> Manager::EnumerateWatchedServices(Error *error) {
Chris Masone6791a432011-07-12 13:23:19 -0700510 // TODO(cmasone): Filter this list for services in appropriate states.
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800511 return EnumerateAvailableServices(error);
Chris Masone3c3f6a12011-07-01 10:01:41 -0700512}
513
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800514string Manager::GetActiveProfileName(Error */*error*/) {
Chris Masone7df0c672011-07-15 10:24:54 -0700515 return ActiveProfile()->GetFriendlyName();
Chris Masone7aa5f902011-07-11 11:13:35 -0700516}
517
mukesh agrawal32399322011-09-01 10:53:43 -0700518// called via RPC (e.g., from ManagerDBusAdaptor)
mukesh agrawal7a4e4002011-09-06 11:26:05 -0700519WiFiServiceRefPtr Manager::GetWifiService(const KeyValueStore &args,
520 Error *error) {
Paul Stewarta41e38d2011-11-11 07:47:29 -0800521 vector<DeviceRefPtr> wifi_devices;
Paul Stewart22aa71b2011-09-16 12:15:11 -0700522 FilterByTechnology(Technology::kWifi, &wifi_devices);
mukesh agrawal7a4e4002011-09-06 11:26:05 -0700523 if (wifi_devices.empty()) {
524 error->Populate(Error::kInvalidArguments, kManagerErrorNoDevice);
525 return NULL;
526 } else {
527 WiFi *wifi = dynamic_cast<WiFi *>(wifi_devices.front().get());
528 CHECK(wifi);
529 return wifi->GetService(args, error);
530 }
531}
532
533// called via RPC (e.g., from ManagerDBusAdaptor)
Paul Stewart22aa71b2011-09-16 12:15:11 -0700534void Manager::RequestScan(const string &technology, Error *error) {
mukesh agrawal32399322011-09-01 10:53:43 -0700535 if (technology == flimflam::kTypeWifi || technology == "") {
536 vector<DeviceRefPtr> wifi_devices;
Paul Stewartfdd16072011-09-16 12:41:35 -0700537 FilterByTechnology(Technology::kWifi, &wifi_devices);
mukesh agrawal32399322011-09-01 10:53:43 -0700538
539 for (vector<DeviceRefPtr>::iterator it = wifi_devices.begin();
540 it != wifi_devices.end();
541 ++it) {
Darin Petkovc0865312011-09-16 15:31:20 -0700542 (*it)->Scan(error);
mukesh agrawal32399322011-09-01 10:53:43 -0700543 }
544 } else {
545 // TODO(quiche): support scanning for other technologies?
Paul Stewartbe005172011-11-02 18:10:29 -0700546 Error::PopulateAndLog(error, Error::kInvalidArguments,
547 "Unrecognized technology " + technology);
mukesh agrawal32399322011-09-01 10:53:43 -0700548 }
549}
550
Paul Stewart22aa71b2011-09-16 12:15:11 -0700551string Manager::GetTechnologyOrder() {
552 vector<string> technology_names;
553 for (vector<Technology::Identifier>::iterator it = technology_order_.begin();
554 it != technology_order_.end();
555 ++it) {
556 technology_names.push_back(Technology::NameFromIdentifier(*it));
557 }
558
559 return JoinString(technology_names, ',');
560}
561
562void Manager::SetTechnologyOrder(const string &order, Error *error) {
563 vector<Technology::Identifier> new_order;
564 map<Technology::Identifier, bool> seen;
565
566 vector<string> order_parts;
567 base::SplitString(order, ',', &order_parts);
568
569 for (vector<string>::iterator it = order_parts.begin();
570 it != order_parts.end();
571 ++it) {
572 Technology::Identifier identifier = Technology::IdentifierFromName(*it);
573
574 if (identifier == Technology::kUnknown) {
Paul Stewartbe005172011-11-02 18:10:29 -0700575 Error::PopulateAndLog(error, Error::kInvalidArguments,
576 *it + " is an unknown technology name");
Paul Stewart22aa71b2011-09-16 12:15:11 -0700577 return;
578 }
579
580 if (ContainsKey(seen, identifier)) {
Paul Stewartbe005172011-11-02 18:10:29 -0700581 Error::PopulateAndLog(error, Error::kInvalidArguments,
582 *it + " is duplicated in the list");
Paul Stewart22aa71b2011-09-16 12:15:11 -0700583 return;
584 }
585 seen[identifier] = true;
586 new_order.push_back(identifier);
587 }
588
589 technology_order_ = new_order;
590 SortServices();
591}
592
Paul Stewart75897df2011-04-27 09:05:53 -0700593} // namespace shill