blob: 43d034189fcfaee4a4eea51536d13d4d106d0bbf [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>
Paul Stewart22aa71b2011-09-16 12:15:11 -070018#include <base/string_split.h>
19#include <base/string_util.h>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070020#include <chromeos/dbus/service_constants.h>
Chris Masoneee929b72011-05-10 10:02:18 -070021
Chris Masoned0ceb8c2011-06-02 10:05:39 -070022#include "shill/adaptor_interfaces.h"
Paul Stewart75897df2011-04-27 09:05:53 -070023#include "shill/control_interface.h"
Chris Masoned0ceb8c2011-06-02 10:05:39 -070024#include "shill/dbus_adaptor.h"
Chris Masone7aa5f902011-07-11 11:13:35 -070025#include "shill/default_profile.h"
Chris Masone9be4a9d2011-05-16 15:44:09 -070026#include "shill/device.h"
27#include "shill/device_info.h"
Chris Masone6791a432011-07-12 13:23:19 -070028#include "shill/ephemeral_profile.h"
Chris Masone8fe2c7e2011-06-09 15:51:19 -070029#include "shill/error.h"
Paul Stewart26b327e2011-10-19 11:38:09 -070030#include "shill/event_dispatcher.h"
Chris Masone9d779932011-08-25 16:33:41 -070031#include "shill/key_file_store.h"
Paul Stewart22aa71b2011-09-16 12:15:11 -070032#include "shill/service_sorter.h"
Chris Masone7aa5f902011-07-11 11:13:35 -070033#include "shill/profile.h"
Chris Masoneb925cc82011-06-22 15:39:57 -070034#include "shill/property_accessor.h"
Paul Stewarte6132022011-08-16 09:11:02 -070035#include "shill/resolver.h"
Chris Masone9be4a9d2011-05-16 15:44:09 -070036#include "shill/service.h"
mukesh agrawal7a4e4002011-09-06 11:26:05 -070037#include "shill/wifi.h"
38#include "shill/wifi_service.h"
Paul Stewart75897df2011-04-27 09:05:53 -070039
Paul Stewart22aa71b2011-09-16 12:15:11 -070040using std::map;
Paul Stewart75897df2011-04-27 09:05:53 -070041using std::string;
Chris Masone9be4a9d2011-05-16 15:44:09 -070042using std::vector;
Paul Stewart75897df2011-04-27 09:05:53 -070043
44namespace shill {
Paul Stewarte6132022011-08-16 09:11:02 -070045
mukesh agrawal7a4e4002011-09-06 11:26:05 -070046// static
47const char Manager::kManagerErrorNoDevice[] = "no wifi devices available";
48
Paul Stewart75897df2011-04-27 09:05:53 -070049Manager::Manager(ControlInterface *control_interface,
Darin Petkov887f2982011-07-14 16:10:17 -070050 EventDispatcher *dispatcher,
Chris Masone2ae797d2011-08-23 20:41:00 -070051 GLib *glib,
52 const string &run_directory,
53 const string &storage_directory,
54 const string &user_storage_format)
55 : run_path_(FilePath(run_directory)),
56 storage_path_(FilePath(storage_directory)),
57 user_storage_format_(user_storage_format),
Paul Stewarte6132022011-08-16 09:11:02 -070058 adaptor_(control_interface->CreateManagerAdaptor(this)),
Paul Stewartb50f0b92011-05-16 16:31:42 -070059 device_info_(control_interface, dispatcher, this),
Darin Petkov887f2982011-07-14 16:10:17 -070060 modem_info_(control_interface, dispatcher, this, glib),
Chris Masone6791a432011-07-12 13:23:19 -070061 running_(false),
Paul Stewart5dc40aa2011-10-28 19:43:43 -070062 connect_profiles_to_rpc_(true),
Chris Masone9d779932011-08-25 16:33:41 -070063 ephemeral_profile_(new EphemeralProfile(control_interface, this)),
Chris Masone2ae797d2011-08-23 20:41:00 -070064 control_interface_(control_interface),
65 glib_(glib) {
Chris Masone7aa5f902011-07-11 11:13:35 -070066 HelpRegisterDerivedString(flimflam::kActiveProfileProperty,
67 &Manager::GetActiveProfileName,
68 NULL);
Chris Masone27c4aa52011-07-02 13:10:14 -070069 HelpRegisterDerivedStrings(flimflam::kAvailableTechnologiesProperty,
70 &Manager::AvailableTechnologies,
71 NULL);
Chris Masone88cbd5f2011-07-03 14:30:04 -070072 store_.RegisterString(flimflam::kCheckPortalListProperty,
73 &props_.check_portal_list);
Chris Masone27c4aa52011-07-02 13:10:14 -070074 HelpRegisterDerivedStrings(flimflam::kConnectedTechnologiesProperty,
75 &Manager::ConnectedTechnologies,
76 NULL);
Chris Masone88cbd5f2011-07-03 14:30:04 -070077 store_.RegisterString(flimflam::kCountryProperty, &props_.country);
Chris Masone27c4aa52011-07-02 13:10:14 -070078 HelpRegisterDerivedString(flimflam::kDefaultTechnologyProperty,
79 &Manager::DefaultTechnology,
80 NULL);
Chris Masone27c4aa52011-07-02 13:10:14 -070081 HelpRegisterDerivedStrings(flimflam::kDevicesProperty,
82 &Manager::EnumerateDevices,
83 NULL);
Chris Masone88cbd5f2011-07-03 14:30:04 -070084 HelpRegisterDerivedStrings(flimflam::kEnabledTechnologiesProperty,
85 &Manager::EnabledTechnologies,
86 NULL);
87 store_.RegisterBool(flimflam::kOfflineModeProperty, &props_.offline_mode);
88 store_.RegisterString(flimflam::kPortalURLProperty, &props_.portal_url);
89 HelpRegisterDerivedString(flimflam::kStateProperty,
90 &Manager::CalculateState,
91 NULL);
Chris Masone27c4aa52011-07-02 13:10:14 -070092 HelpRegisterDerivedStrings(flimflam::kServicesProperty,
93 &Manager::EnumerateAvailableServices,
94 NULL);
95 HelpRegisterDerivedStrings(flimflam::kServiceWatchListProperty,
96 &Manager::EnumerateWatchedServices,
97 NULL);
Chris Masone3c3f6a12011-07-01 10:01:41 -070098
Chris Masone4d42df82011-07-02 17:09:39 -070099 // TODO(cmasone): Wire these up once we actually put in profile support.
Chris Masoneb925cc82011-06-22 15:39:57 -0700100 // known_properties_.push_back(flimflam::kProfilesProperty);
Chris Masoneb07006b2011-05-14 16:10:04 -0700101 VLOG(2) << "Manager initialized.";
Paul Stewart75897df2011-04-27 09:05:53 -0700102}
103
Chris Masone6791a432011-07-12 13:23:19 -0700104Manager::~Manager() {
Chris Masone9d779932011-08-25 16:33:41 -0700105 profiles_.clear();
Chris Masone6791a432011-07-12 13:23:19 -0700106}
Paul Stewart75897df2011-04-27 09:05:53 -0700107
mukesh agrawal8f317b62011-07-15 11:53:23 -0700108void Manager::AddDeviceToBlackList(const string &device_name) {
109 device_info_.AddDeviceToBlackList(device_name);
110}
111
Paul Stewart75897df2011-04-27 09:05:53 -0700112void Manager::Start() {
Paul Stewart0af98bf2011-05-10 17:38:08 -0700113 LOG(INFO) << "Manager started.";
Paul Stewarte6132022011-08-16 09:11:02 -0700114
Chris Masone2ae797d2011-08-23 20:41:00 -0700115 CHECK(file_util::CreateDirectory(run_path_)) << run_path_.value();
Paul Stewarte6132022011-08-16 09:11:02 -0700116 Resolver::GetInstance()->set_path(run_path_.Append("resolv.conf"));
Chris Masone2ae797d2011-08-23 20:41:00 -0700117
118 CHECK(file_util::CreateDirectory(storage_path_)) << storage_path_.value();
119
Chris Masoneb9c00592011-10-06 13:10:39 -0700120 profiles_.push_back(new DefaultProfile(control_interface_,
121 this,
122 storage_path_,
123 props_));
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700124 CHECK(profiles_[0]->InitStorage(glib_, Profile::kCreateOrOpenExisting, NULL));
Chris Masoneb9c00592011-10-06 13:10:39 -0700125
Paul Stewart75897df2011-04-27 09:05:53 -0700126 running_ = true;
Chris Masone413a3192011-05-09 17:10:05 -0700127 adaptor_->UpdateRunning();
Paul Stewart0af98bf2011-05-10 17:38:08 -0700128 device_info_.Start();
Darin Petkov887f2982011-07-14 16:10:17 -0700129 modem_info_.Start();
Paul Stewart75897df2011-04-27 09:05:53 -0700130}
131
132void Manager::Stop() {
133 running_ = false;
Chris Masone9d779932011-08-25 16:33:41 -0700134 // Persist profile, device, service information to disk.
135 vector<ProfileRefPtr>::iterator it;
136 for (it = profiles_.begin(); it != profiles_.end(); ++it) {
Chris Masone6515aab2011-10-12 16:19:09 -0700137 (*it)->Save();
Chris Masone9d779932011-08-25 16:33:41 -0700138 }
Chris Masone9d779932011-08-25 16:33:41 -0700139
Thieu Le1271d682011-11-02 22:48:19 +0000140 vector<ServiceRefPtr>::iterator services_it;
141 for (services_it = services_.begin(); services_it != services_.end();
142 ++services_it) {
143 (*services_it)->Disconnect();
144 }
145
Chris Masone413a3192011-05-09 17:10:05 -0700146 adaptor_->UpdateRunning();
Darin Petkov887f2982011-07-14 16:10:17 -0700147 modem_info_.Stop();
148 device_info_.Stop();
Paul Stewart75897df2011-04-27 09:05:53 -0700149}
150
Paul Stewarta41e38d2011-11-11 07:47:29 -0800151void Manager::CreateProfile(const string &name, Error *error) {
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700152 Profile::Identifier ident;
153 if (!Profile::ParseIdentifier(name, &ident)) {
Paul Stewartbe005172011-11-02 18:10:29 -0700154 Error::PopulateAndLog(error, Error::kInvalidArguments,
155 "Invalid profile name " + name);
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700156 return;
157 }
158 ProfileRefPtr profile(new Profile(control_interface_,
159 this,
160 ident,
161 user_storage_format_,
162 false));
163 if (!profile->InitStorage(glib_, Profile::kCreateNew, error)) {
164 return;
165 }
166
167 // Save profile data out, and then let the scoped pointer fall out of scope.
168 if (!profile->Save()) {
Paul Stewartbe005172011-11-02 18:10:29 -0700169 Error::PopulateAndLog(error, Error::kInternalError,
170 "Profile name " + name + " could not be saved");
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700171 return;
172 }
173}
174
175void Manager::PushProfile(const string &name, Error *error) {
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700176 Profile::Identifier ident;
177 if (!Profile::ParseIdentifier(name, &ident)) {
Paul Stewartbe005172011-11-02 18:10:29 -0700178 Error::PopulateAndLog(error, Error::kInvalidArguments,
179 "Invalid profile name " + name);
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700180 return;
181 }
182
183 for (vector<ProfileRefPtr>::const_iterator it = profiles_.begin();
184 it != profiles_.end();
185 ++it) {
186 if ((*it)->MatchesIdentifier(ident)) {
Paul Stewartbe005172011-11-02 18:10:29 -0700187 Error::PopulateAndLog(error, Error::kAlreadyExists,
188 "Profile name " + name + " is already on stack");
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700189 return;
190 }
191 }
192
193 if (ident.user.empty()) {
194 // The manager will have only one machine-wide profile, and this is the
195 // DefaultProfile. This means no other profiles can be loaded that do
196 // not have a user component.
197 // TODO(pstew): This is all well and good, but WiFi autotests try to
198 // creating a default profile (by a name other than "default") in order
199 // to avoid leaving permanent side effects to devices under test. This
200 // whole thing will need to be reworked in order to allow that to happen,
201 // or the autotests (or their expectations) will need to change.
Paul Stewartbe005172011-11-02 18:10:29 -0700202 Error::PopulateAndLog(error, Error::kInvalidArguments,
203 "Cannot load non-default global profile " + name);
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700204 return;
205 }
206
207 ProfileRefPtr profile(new Profile(control_interface_,
208 this,
209 ident,
210 user_storage_format_,
211 connect_profiles_to_rpc_));
212 if (!profile->InitStorage(glib_, Profile::kOpenExisting, error)) {
213 return;
214 }
215
Paul Stewarta849a3d2011-11-03 05:54:09 -0700216 profiles_.push_back(profile);
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700217
218 // Offer each registered Service the opportunity to join this new Profile.
Paul Stewarta41e38d2011-11-11 07:47:29 -0800219 for (vector<ServiceRefPtr>::iterator it = services_.begin();
220 it != services_.end(); ++it) {
Paul Stewartbba6a5b2011-11-02 18:45:59 -0700221 profile->ConfigureService(*it);
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700222 }
223
Paul Stewarta41e38d2011-11-11 07:47:29 -0800224 // Shop the Profile contents around to Devices which can create
225 // non-visible services.
226 for (vector<DeviceRefPtr>::iterator it = devices_.begin();
227 it != devices_.end(); ++it) {
228 profile->ConfigureDevice(*it);
229 }
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700230}
231
232void Manager::PopProfileInternal() {
233 CHECK(!profiles_.empty());
234 ProfileRefPtr active_profile = profiles_.back();
235 profiles_.pop_back();
236 vector<ServiceRefPtr>::iterator s_it;
237 for (s_it = services_.begin(); s_it != services_.end(); ++s_it) {
238 if ((*s_it)->profile().get() == active_profile.get()) {
239 vector<ProfileRefPtr>::reverse_iterator p_it;
240 for (p_it = profiles_.rbegin(); p_it != profiles_.rend(); ++p_it) {
Paul Stewartbba6a5b2011-11-02 18:45:59 -0700241 if ((*p_it)->ConfigureService(*s_it)) {
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700242 break;
243 }
244 }
245 if (p_it == profiles_.rend()) {
246 ephemeral_profile_->AdoptService(*s_it);
Paul Stewarta41e38d2011-11-11 07:47:29 -0800247 (*s_it)->Unload();
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700248 }
249 }
250 }
251}
252
Paul Stewarta41e38d2011-11-11 07:47:29 -0800253void Manager::PopProfile(const string &name, Error *error) {
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700254 Profile::Identifier ident;
255 if (profiles_.empty()) {
Paul Stewartbe005172011-11-02 18:10:29 -0700256 Error::PopulateAndLog(error, Error::kNotFound, "Profile stack is empty");
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700257 return;
258 }
259 ProfileRefPtr active_profile = profiles_.back();
260 if (!Profile::ParseIdentifier(name, &ident)) {
Paul Stewartbe005172011-11-02 18:10:29 -0700261 Error::PopulateAndLog(error, Error::kInvalidArguments,
262 "Invalid profile name " + name);
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700263 return;
264 }
265 if (!active_profile->MatchesIdentifier(ident)) {
Paul Stewartbe005172011-11-02 18:10:29 -0700266 Error::PopulateAndLog(error, Error::kNotSupported,
267 name + " is not the active profile");
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700268 return;
269 }
270 PopProfileInternal();
271}
272
273void Manager::PopAnyProfile(Error *error) {
274 Profile::Identifier ident;
275 if (profiles_.empty()) {
Paul Stewartbe005172011-11-02 18:10:29 -0700276 Error::PopulateAndLog(error, Error::kNotFound, "Profile stack is empty");
Paul Stewart5dc40aa2011-10-28 19:43:43 -0700277 return;
278 }
279 PopProfileInternal();
280}
281
Chris Masone7aa5f902011-07-11 11:13:35 -0700282const ProfileRefPtr &Manager::ActiveProfile() {
Chris Masoneb9c00592011-10-06 13:10:39 -0700283 DCHECK_NE(profiles_.size(), 0);
Chris Masone7aa5f902011-07-11 11:13:35 -0700284 return profiles_.back();
285}
286
Chris Masone6515aab2011-10-12 16:19:09 -0700287bool Manager::MoveServiceToProfile(const ServiceRefPtr &to_move,
288 const ProfileRefPtr &destination) {
289 const ProfileRefPtr from = to_move->profile();
290 return destination->AdoptService(to_move) &&
291 from->AbandonService(to_move);
Chris Masone6791a432011-07-12 13:23:19 -0700292}
293
Chris Masone2b105542011-06-22 10:58:09 -0700294void Manager::RegisterDevice(const DeviceRefPtr &to_manage) {
Chris Masonec1e50412011-06-07 13:04:53 -0700295 vector<DeviceRefPtr>::iterator it;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700296 for (it = devices_.begin(); it != devices_.end(); ++it) {
Chris Masonec1e50412011-06-07 13:04:53 -0700297 if (to_manage.get() == it->get())
Chris Masone9be4a9d2011-05-16 15:44:09 -0700298 return;
299 }
Chris Masonec1e50412011-06-07 13:04:53 -0700300 devices_.push_back(to_manage);
Paul Stewartf1ce5d22011-05-19 13:10:20 -0700301
Paul Stewarta41e38d2011-11-11 07:47:29 -0800302 // We are applying device properties from the DefaultProfile, and adding
303 // the union of hidden services in all loaded profiles to the device.
Chris Masone6515aab2011-10-12 16:19:09 -0700304 for (vector<ProfileRefPtr>::iterator it = profiles_.begin();
305 it != profiles_.end();
306 ++it) {
Paul Stewarta41e38d2011-11-11 07:47:29 -0800307 // Load device configuration, if any exists, as well as hidden services.
308 (*it)->ConfigureDevice(to_manage);
309
310 // Currently the only profile for which "Save" is implemented is the
311 // DefaultProfile. It iterates over all Devices and stores their state.
312 // We perform the Save now in case the device we have just registered
313 // is new and needs to be added to the stored DefaultProfile.
Chris Masone6515aab2011-10-12 16:19:09 -0700314 (*it)->Save();
315 }
Paul Stewarta41e38d2011-11-11 07:47:29 -0800316
317 // In normal usage, running_ will always be true when we are here, however
318 // unit tests sometimes do things in otherwise invalid states.
319 if (running_ && to_manage->powered())
320 to_manage->Start();
Chris Masone9be4a9d2011-05-16 15:44:09 -0700321}
322
mukesh agrawal5029c6c2011-08-25 11:12:40 -0700323void Manager::DeregisterDevice(const DeviceRefPtr &to_forget) {
Chris Masonec1e50412011-06-07 13:04:53 -0700324 vector<DeviceRefPtr>::iterator it;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700325 for (it = devices_.begin(); it != devices_.end(); ++it) {
Chris Masonec1e50412011-06-07 13:04:53 -0700326 if (to_forget.get() == it->get()) {
mukesh agrawal5029c6c2011-08-25 11:12:40 -0700327 VLOG(2) << "Deregistered device: " << to_forget->UniqueName();
328 to_forget->Stop();
Chris Masone9be4a9d2011-05-16 15:44:09 -0700329 devices_.erase(it);
330 return;
331 }
332 }
mukesh agrawal5029c6c2011-08-25 11:12:40 -0700333 VLOG(2) << __func__ << " unknown device: " << to_forget->UniqueName();
Chris Masone9be4a9d2011-05-16 15:44:09 -0700334}
335
Chris Masone2b105542011-06-22 10:58:09 -0700336void Manager::RegisterService(const ServiceRefPtr &to_manage) {
mukesh agrawald835b202011-10-07 15:26:47 -0700337 VLOG(2) << __func__ << to_manage->UniqueName();
338
Paul Stewartbba6a5b2011-11-02 18:45:59 -0700339 bool configured = false;
Paul Stewarta41e38d2011-11-11 07:47:29 -0800340 for (vector<ProfileRefPtr>::reverse_iterator it = profiles_.rbegin();
341 !configured && it != profiles_.rend();
Chris Masone157aa0c2011-10-03 09:24:31 -0700342 ++it) {
Paul Stewartbba6a5b2011-11-02 18:45:59 -0700343 configured = (*it)->ConfigureService(to_manage);
Chris Masone157aa0c2011-10-03 09:24:31 -0700344 }
Chris Masone6791a432011-07-12 13:23:19 -0700345
346 // If not found, add it to the ephemeral profile
Paul Stewartbba6a5b2011-11-02 18:45:59 -0700347 if (!configured)
Chris Masone6515aab2011-10-12 16:19:09 -0700348 ephemeral_profile_->AdoptService(to_manage);
Chris Masone6791a432011-07-12 13:23:19 -0700349
350 // Now add to OUR list.
Chris Masonec1e50412011-06-07 13:04:53 -0700351 vector<ServiceRefPtr>::iterator it;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700352 for (it = services_.begin(); it != services_.end(); ++it) {
mukesh agrawald835b202011-10-07 15:26:47 -0700353 CHECK(to_manage->UniqueName() != (*it)->UniqueName());
Chris Masone9be4a9d2011-05-16 15:44:09 -0700354 }
Chris Masonec1e50412011-06-07 13:04:53 -0700355 services_.push_back(to_manage);
Paul Stewart22aa71b2011-09-16 12:15:11 -0700356 SortServices();
Chris Masone9be4a9d2011-05-16 15:44:09 -0700357}
358
Chris Masone6515aab2011-10-12 16:19:09 -0700359void Manager::DeregisterService(const ServiceRefPtr &to_forget) {
Chris Masonec1e50412011-06-07 13:04:53 -0700360 vector<ServiceRefPtr>::iterator it;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700361 for (it = services_.begin(); it != services_.end(); ++it) {
Chris Masone6791a432011-07-12 13:23:19 -0700362 if (to_forget->UniqueName() == (*it)->UniqueName()) {
Chris Masone9be4a9d2011-05-16 15:44:09 -0700363 services_.erase(it);
Paul Stewart22aa71b2011-09-16 12:15:11 -0700364 SortServices();
Chris Masone9be4a9d2011-05-16 15:44:09 -0700365 return;
366 }
367 }
368}
369
Paul Stewart03dba0b2011-08-22 16:32:45 -0700370void Manager::UpdateService(const ServiceConstRefPtr &to_update) {
371 LOG(INFO) << "Service " << to_update->UniqueName() << " updated;"
372 << " state: " << to_update->state() << " failure: "
373 << to_update->failure();
Paul Stewart22aa71b2011-09-16 12:15:11 -0700374 SortServices();
Paul Stewart03dba0b2011-08-22 16:32:45 -0700375}
376
Paul Stewartfdd16072011-09-16 12:41:35 -0700377void Manager::FilterByTechnology(Technology::Identifier tech,
Chris Masonec1e50412011-06-07 13:04:53 -0700378 vector<DeviceRefPtr> *found) {
Chris Masone9be4a9d2011-05-16 15:44:09 -0700379 CHECK(found);
Chris Masonec1e50412011-06-07 13:04:53 -0700380 vector<DeviceRefPtr>::iterator it;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700381 for (it = devices_.begin(); it != devices_.end(); ++it) {
382 if ((*it)->TechnologyIs(tech))
383 found->push_back(*it);
384 }
385}
386
Paul Stewart22aa71b2011-09-16 12:15:11 -0700387ServiceRefPtr Manager::FindService(const string& name) {
Chris Masonec1e50412011-06-07 13:04:53 -0700388 vector<ServiceRefPtr>::iterator it;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700389 for (it = services_.begin(); it != services_.end(); ++it) {
Chris Masone6791a432011-07-12 13:23:19 -0700390 if (name == (*it)->UniqueName())
Chris Masonee0dea762011-06-09 09:06:03 -0700391 return *it;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700392 }
Chris Masonee0dea762011-06-09 09:06:03 -0700393 return NULL;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700394}
395
mukesh agrawalffa3d042011-10-06 15:26:10 -0700396void Manager::HelpRegisterDerivedString(
397 const string &name,
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800398 string(Manager::*get)(Error *),
mukesh agrawalffa3d042011-10-06 15:26:10 -0700399 void(Manager::*set)(const string&, Error *)) {
Chris Masone27c4aa52011-07-02 13:10:14 -0700400 store_.RegisterDerivedString(
401 name,
402 StringAccessor(new CustomAccessor<Manager, string>(this, get, set)));
Chris Masoneb925cc82011-06-22 15:39:57 -0700403}
404
mukesh agrawalffa3d042011-10-06 15:26:10 -0700405void Manager::HelpRegisterDerivedStrings(
406 const string &name,
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800407 Strings(Manager::*get)(Error *),
mukesh agrawalffa3d042011-10-06 15:26:10 -0700408 void(Manager::*set)(const Strings &, Error *)) {
Chris Masone27c4aa52011-07-02 13:10:14 -0700409 store_.RegisterDerivedStrings(
410 name,
411 StringsAccessor(new CustomAccessor<Manager, Strings>(this, get, set)));
Chris Masoneb925cc82011-06-22 15:39:57 -0700412}
413
Paul Stewart22aa71b2011-09-16 12:15:11 -0700414void Manager::SortServices() {
415 sort(services_.begin(), services_.end(), ServiceSorter(technology_order_));
Paul Stewarta41e38d2011-11-11 07:47:29 -0800416
417 vector<string> service_paths;
418 vector<ServiceRefPtr>::iterator it;
419 for (it = services_.begin(); it != services_.end(); ++it) {
420 if ((*it)->IsVisible()) {
421 service_paths.push_back((*it)->GetRpcIdentifier());
422 }
423 }
424 adaptor_->EmitRpcIdentifierArrayChanged(flimflam::kServicesProperty,
425 service_paths);
Paul Stewart22aa71b2011-09-16 12:15:11 -0700426}
427
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800428string Manager::CalculateState(Error */*error*/) {
Chris Masoneb925cc82011-06-22 15:39:57 -0700429 return flimflam::kStateOffline;
430}
431
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800432vector<string> Manager::AvailableTechnologies(Error */*error*/) {
Chris Masoneb925cc82011-06-22 15:39:57 -0700433 return vector<string>();
434}
435
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800436vector<string> Manager::ConnectedTechnologies(Error */*error*/) {
Chris Masoneb925cc82011-06-22 15:39:57 -0700437 return vector<string>();
438}
439
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800440string Manager::DefaultTechnology(Error */*error*/) {
Chris Masoneb925cc82011-06-22 15:39:57 -0700441 return "";
442}
443
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800444vector<string> Manager::EnabledTechnologies(Error */*error*/) {
Chris Masoneb925cc82011-06-22 15:39:57 -0700445 return vector<string>();
446}
447
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800448vector<string> Manager::EnumerateDevices(Error */*error*/) {
Chris Masone3c3f6a12011-07-01 10:01:41 -0700449 vector<string> device_rpc_ids;
450 for (vector<DeviceRefPtr>::const_iterator it = devices_.begin();
451 it != devices_.end();
452 ++it) {
453 device_rpc_ids.push_back((*it)->GetRpcIdentifier());
454 }
455 return device_rpc_ids;
456}
457
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800458vector<string> Manager::EnumerateAvailableServices(Error */*error*/) {
Chris Masone3c3f6a12011-07-01 10:01:41 -0700459 vector<string> service_rpc_ids;
460 for (vector<ServiceRefPtr>::const_iterator it = services_.begin();
461 it != services_.end();
462 ++it) {
463 service_rpc_ids.push_back((*it)->GetRpcIdentifier());
464 }
465 return service_rpc_ids;
466}
467
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800468vector<string> Manager::EnumerateWatchedServices(Error *error) {
Chris Masone6791a432011-07-12 13:23:19 -0700469 // TODO(cmasone): Filter this list for services in appropriate states.
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800470 return EnumerateAvailableServices(error);
Chris Masone3c3f6a12011-07-01 10:01:41 -0700471}
472
Gaurav Shah1b7a6162011-11-09 11:41:01 -0800473string Manager::GetActiveProfileName(Error */*error*/) {
Chris Masone7df0c672011-07-15 10:24:54 -0700474 return ActiveProfile()->GetFriendlyName();
Chris Masone7aa5f902011-07-11 11:13:35 -0700475}
476
mukesh agrawal32399322011-09-01 10:53:43 -0700477// called via RPC (e.g., from ManagerDBusAdaptor)
mukesh agrawal7a4e4002011-09-06 11:26:05 -0700478WiFiServiceRefPtr Manager::GetWifiService(const KeyValueStore &args,
479 Error *error) {
Paul Stewarta41e38d2011-11-11 07:47:29 -0800480 vector<DeviceRefPtr> wifi_devices;
Paul Stewart22aa71b2011-09-16 12:15:11 -0700481 FilterByTechnology(Technology::kWifi, &wifi_devices);
mukesh agrawal7a4e4002011-09-06 11:26:05 -0700482 if (wifi_devices.empty()) {
483 error->Populate(Error::kInvalidArguments, kManagerErrorNoDevice);
484 return NULL;
485 } else {
486 WiFi *wifi = dynamic_cast<WiFi *>(wifi_devices.front().get());
487 CHECK(wifi);
488 return wifi->GetService(args, error);
489 }
490}
491
492// called via RPC (e.g., from ManagerDBusAdaptor)
Paul Stewart22aa71b2011-09-16 12:15:11 -0700493void Manager::RequestScan(const string &technology, Error *error) {
mukesh agrawal32399322011-09-01 10:53:43 -0700494 if (technology == flimflam::kTypeWifi || technology == "") {
495 vector<DeviceRefPtr> wifi_devices;
Paul Stewartfdd16072011-09-16 12:41:35 -0700496 FilterByTechnology(Technology::kWifi, &wifi_devices);
mukesh agrawal32399322011-09-01 10:53:43 -0700497
498 for (vector<DeviceRefPtr>::iterator it = wifi_devices.begin();
499 it != wifi_devices.end();
500 ++it) {
Darin Petkovc0865312011-09-16 15:31:20 -0700501 (*it)->Scan(error);
mukesh agrawal32399322011-09-01 10:53:43 -0700502 }
503 } else {
504 // TODO(quiche): support scanning for other technologies?
Paul Stewartbe005172011-11-02 18:10:29 -0700505 Error::PopulateAndLog(error, Error::kInvalidArguments,
506 "Unrecognized technology " + technology);
mukesh agrawal32399322011-09-01 10:53:43 -0700507 }
508}
509
Paul Stewart22aa71b2011-09-16 12:15:11 -0700510string Manager::GetTechnologyOrder() {
511 vector<string> technology_names;
512 for (vector<Technology::Identifier>::iterator it = technology_order_.begin();
513 it != technology_order_.end();
514 ++it) {
515 technology_names.push_back(Technology::NameFromIdentifier(*it));
516 }
517
518 return JoinString(technology_names, ',');
519}
520
521void Manager::SetTechnologyOrder(const string &order, Error *error) {
522 vector<Technology::Identifier> new_order;
523 map<Technology::Identifier, bool> seen;
524
525 vector<string> order_parts;
526 base::SplitString(order, ',', &order_parts);
527
528 for (vector<string>::iterator it = order_parts.begin();
529 it != order_parts.end();
530 ++it) {
531 Technology::Identifier identifier = Technology::IdentifierFromName(*it);
532
533 if (identifier == Technology::kUnknown) {
Paul Stewartbe005172011-11-02 18:10:29 -0700534 Error::PopulateAndLog(error, Error::kInvalidArguments,
535 *it + " is an unknown technology name");
Paul Stewart22aa71b2011-09-16 12:15:11 -0700536 return;
537 }
538
539 if (ContainsKey(seen, identifier)) {
Paul Stewartbe005172011-11-02 18:10:29 -0700540 Error::PopulateAndLog(error, Error::kInvalidArguments,
541 *it + " is duplicated in the list");
Paul Stewart22aa71b2011-09-16 12:15:11 -0700542 return;
543 }
544 seen[identifier] = true;
545 new_order.push_back(identifier);
546 }
547
548 technology_order_ = new_order;
549 SortServices();
550}
551
Paul Stewart75897df2011-04-27 09:05:53 -0700552} // namespace shill