blob: 3b109e2a59ff38bcce8d308c33d03cc28203825d [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
mukesh agrawal7a4e4002011-09-06 11:26:05 -070010#include <map>
Paul Stewart75897df2011-04-27 09:05:53 -070011#include <string>
Chris Masone52cd19b2011-06-29 17:23:04 -070012#include <vector>
Paul Stewart75897df2011-04-27 09:05:53 -070013
Paul Stewarte6132022011-08-16 09:11:02 -070014#include <base/file_util.h>
Chris Masoneee929b72011-05-10 10:02:18 -070015#include <base/logging.h>
Chris Masone9be4a9d2011-05-16 15:44:09 -070016#include <base/memory/ref_counted.h>
Chris Masone3bd3c8c2011-06-13 08:20:26 -070017#include <chromeos/dbus/service_constants.h>
Chris Masoneee929b72011-05-10 10:02:18 -070018
Chris Masoned0ceb8c2011-06-02 10:05:39 -070019#include "shill/adaptor_interfaces.h"
Paul Stewart75897df2011-04-27 09:05:53 -070020#include "shill/control_interface.h"
Chris Masoned0ceb8c2011-06-02 10:05:39 -070021#include "shill/dbus_adaptor.h"
Chris Masone7aa5f902011-07-11 11:13:35 -070022#include "shill/default_profile.h"
Chris Masone9be4a9d2011-05-16 15:44:09 -070023#include "shill/device.h"
24#include "shill/device_info.h"
Chris Masone6791a432011-07-12 13:23:19 -070025#include "shill/ephemeral_profile.h"
Chris Masone8fe2c7e2011-06-09 15:51:19 -070026#include "shill/error.h"
Chris Masone9d779932011-08-25 16:33:41 -070027#include "shill/key_file_store.h"
Chris Masone7aa5f902011-07-11 11:13:35 -070028#include "shill/profile.h"
Chris Masoneb925cc82011-06-22 15:39:57 -070029#include "shill/property_accessor.h"
Paul Stewarte6132022011-08-16 09:11:02 -070030#include "shill/resolver.h"
Chris Masone9be4a9d2011-05-16 15:44:09 -070031#include "shill/shill_event.h"
32#include "shill/service.h"
mukesh agrawal7a4e4002011-09-06 11:26:05 -070033#include "shill/wifi.h"
34#include "shill/wifi_service.h"
Paul Stewart75897df2011-04-27 09:05:53 -070035
36using std::string;
Chris Masone9be4a9d2011-05-16 15:44:09 -070037using std::vector;
Paul Stewart75897df2011-04-27 09:05:53 -070038
39namespace shill {
Paul Stewarte6132022011-08-16 09:11:02 -070040
mukesh agrawal7a4e4002011-09-06 11:26:05 -070041// static
42const char Manager::kManagerErrorNoDevice[] = "no wifi devices available";
43
Paul Stewart75897df2011-04-27 09:05:53 -070044Manager::Manager(ControlInterface *control_interface,
Darin Petkov887f2982011-07-14 16:10:17 -070045 EventDispatcher *dispatcher,
Chris Masone2ae797d2011-08-23 20:41:00 -070046 GLib *glib,
47 const string &run_directory,
48 const string &storage_directory,
49 const string &user_storage_format)
50 : run_path_(FilePath(run_directory)),
51 storage_path_(FilePath(storage_directory)),
52 user_storage_format_(user_storage_format),
Paul Stewarte6132022011-08-16 09:11:02 -070053 adaptor_(control_interface->CreateManagerAdaptor(this)),
Paul Stewartb50f0b92011-05-16 16:31:42 -070054 device_info_(control_interface, dispatcher, this),
Darin Petkov887f2982011-07-14 16:10:17 -070055 modem_info_(control_interface, dispatcher, this, glib),
Chris Masone6791a432011-07-12 13:23:19 -070056 running_(false),
Chris Masone9d779932011-08-25 16:33:41 -070057 ephemeral_profile_(new EphemeralProfile(control_interface, this)),
Chris Masone2ae797d2011-08-23 20:41:00 -070058 control_interface_(control_interface),
59 glib_(glib) {
Chris Masone7aa5f902011-07-11 11:13:35 -070060 HelpRegisterDerivedString(flimflam::kActiveProfileProperty,
61 &Manager::GetActiveProfileName,
62 NULL);
Chris Masone27c4aa52011-07-02 13:10:14 -070063 HelpRegisterDerivedStrings(flimflam::kAvailableTechnologiesProperty,
64 &Manager::AvailableTechnologies,
65 NULL);
Chris Masone88cbd5f2011-07-03 14:30:04 -070066 store_.RegisterString(flimflam::kCheckPortalListProperty,
67 &props_.check_portal_list);
Chris Masone27c4aa52011-07-02 13:10:14 -070068 HelpRegisterDerivedStrings(flimflam::kConnectedTechnologiesProperty,
69 &Manager::ConnectedTechnologies,
70 NULL);
Chris Masone88cbd5f2011-07-03 14:30:04 -070071 store_.RegisterString(flimflam::kCountryProperty, &props_.country);
Chris Masone27c4aa52011-07-02 13:10:14 -070072 HelpRegisterDerivedString(flimflam::kDefaultTechnologyProperty,
73 &Manager::DefaultTechnology,
74 NULL);
Chris Masone27c4aa52011-07-02 13:10:14 -070075 HelpRegisterDerivedStrings(flimflam::kDevicesProperty,
76 &Manager::EnumerateDevices,
77 NULL);
Chris Masone88cbd5f2011-07-03 14:30:04 -070078 HelpRegisterDerivedStrings(flimflam::kEnabledTechnologiesProperty,
79 &Manager::EnabledTechnologies,
80 NULL);
81 store_.RegisterBool(flimflam::kOfflineModeProperty, &props_.offline_mode);
82 store_.RegisterString(flimflam::kPortalURLProperty, &props_.portal_url);
83 HelpRegisterDerivedString(flimflam::kStateProperty,
84 &Manager::CalculateState,
85 NULL);
Chris Masone27c4aa52011-07-02 13:10:14 -070086 HelpRegisterDerivedStrings(flimflam::kServicesProperty,
87 &Manager::EnumerateAvailableServices,
88 NULL);
89 HelpRegisterDerivedStrings(flimflam::kServiceWatchListProperty,
90 &Manager::EnumerateWatchedServices,
91 NULL);
Chris Masone3c3f6a12011-07-01 10:01:41 -070092
Chris Masone4d42df82011-07-02 17:09:39 -070093 // TODO(cmasone): Wire these up once we actually put in profile support.
Chris Masoneb925cc82011-06-22 15:39:57 -070094 // known_properties_.push_back(flimflam::kProfilesProperty);
Chris Masone2ae797d2011-08-23 20:41:00 -070095 profiles_.push_back(new DefaultProfile(control_interface_,
Chris Masone6791a432011-07-12 13:23:19 -070096 this,
Chris Masone2ae797d2011-08-23 20:41:00 -070097 storage_path_,
Chris Masone6791a432011-07-12 13:23:19 -070098 props_));
Chris Masoneb07006b2011-05-14 16:10:04 -070099 VLOG(2) << "Manager initialized.";
Paul Stewart75897df2011-04-27 09:05:53 -0700100}
101
Chris Masone6791a432011-07-12 13:23:19 -0700102Manager::~Manager() {
Chris Masone9d779932011-08-25 16:33:41 -0700103 profiles_.clear();
Chris Masone6791a432011-07-12 13:23:19 -0700104}
Paul Stewart75897df2011-04-27 09:05:53 -0700105
mukesh agrawal8f317b62011-07-15 11:53:23 -0700106void Manager::AddDeviceToBlackList(const string &device_name) {
107 device_info_.AddDeviceToBlackList(device_name);
108}
109
Paul Stewart75897df2011-04-27 09:05:53 -0700110void Manager::Start() {
Paul Stewart0af98bf2011-05-10 17:38:08 -0700111 LOG(INFO) << "Manager started.";
Paul Stewarte6132022011-08-16 09:11:02 -0700112
Chris Masone2ae797d2011-08-23 20:41:00 -0700113 CHECK(file_util::CreateDirectory(run_path_)) << run_path_.value();
Paul Stewarte6132022011-08-16 09:11:02 -0700114 Resolver::GetInstance()->set_path(run_path_.Append("resolv.conf"));
Chris Masone2ae797d2011-08-23 20:41:00 -0700115
116 CHECK(file_util::CreateDirectory(storage_path_)) << storage_path_.value();
117
Paul Stewart75897df2011-04-27 09:05:53 -0700118 running_ = true;
Chris Masone413a3192011-05-09 17:10:05 -0700119 adaptor_->UpdateRunning();
Paul Stewart0af98bf2011-05-10 17:38:08 -0700120 device_info_.Start();
Darin Petkov887f2982011-07-14 16:10:17 -0700121 modem_info_.Start();
Paul Stewart75897df2011-04-27 09:05:53 -0700122}
123
124void Manager::Stop() {
125 running_ = false;
Chris Masone9d779932011-08-25 16:33:41 -0700126 // Persist profile, device, service information to disk.
127 vector<ProfileRefPtr>::iterator it;
128 for (it = profiles_.begin(); it != profiles_.end(); ++it) {
129 KeyFileStore storage(glib_);
130 FilePath profile_path;
131 CHECK((*it)->GetStoragePath(&profile_path));
132 storage.set_path(profile_path);
133 if (storage.Open()) {
134 (*it)->Finalize(&storage);
135 storage.Close();
136 } else {
137 LOG(ERROR) << "Could not open storage at " << profile_path.value();
138 }
139 }
140 ephemeral_profile_->Finalize(NULL);
141
Chris Masone413a3192011-05-09 17:10:05 -0700142 adaptor_->UpdateRunning();
Darin Petkov887f2982011-07-14 16:10:17 -0700143 modem_info_.Stop();
144 device_info_.Stop();
Paul Stewart75897df2011-04-27 09:05:53 -0700145}
146
Chris Masone7aa5f902011-07-11 11:13:35 -0700147const ProfileRefPtr &Manager::ActiveProfile() {
148 return profiles_.back();
149}
150
Chris Masone6791a432011-07-12 13:23:19 -0700151bool Manager::MoveToActiveProfile(const ProfileRefPtr &from,
152 const ServiceRefPtr &to_move) {
153 return ActiveProfile()->AdoptService(to_move) &&
154 from->AbandonService(to_move->UniqueName());
155}
156
Chris Masone2b105542011-06-22 10:58:09 -0700157void Manager::RegisterDevice(const DeviceRefPtr &to_manage) {
Chris Masonec1e50412011-06-07 13:04:53 -0700158 vector<DeviceRefPtr>::iterator it;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700159 for (it = devices_.begin(); it != devices_.end(); ++it) {
Chris Masonec1e50412011-06-07 13:04:53 -0700160 if (to_manage.get() == it->get())
Chris Masone9be4a9d2011-05-16 15:44:09 -0700161 return;
162 }
Chris Masonec1e50412011-06-07 13:04:53 -0700163 devices_.push_back(to_manage);
Paul Stewartf1ce5d22011-05-19 13:10:20 -0700164
165 // TODO(pstew): Should check configuration
166 if (running_)
167 to_manage->Start();
Chris Masone9be4a9d2011-05-16 15:44:09 -0700168}
169
mukesh agrawal5029c6c2011-08-25 11:12:40 -0700170void Manager::DeregisterDevice(const DeviceRefPtr &to_forget) {
Chris Masonec1e50412011-06-07 13:04:53 -0700171 vector<DeviceRefPtr>::iterator it;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700172 for (it = devices_.begin(); it != devices_.end(); ++it) {
Chris Masonec1e50412011-06-07 13:04:53 -0700173 if (to_forget.get() == it->get()) {
mukesh agrawal5029c6c2011-08-25 11:12:40 -0700174 VLOG(2) << "Deregistered device: " << to_forget->UniqueName();
175 to_forget->Stop();
Chris Masone9be4a9d2011-05-16 15:44:09 -0700176 devices_.erase(it);
177 return;
178 }
179 }
mukesh agrawal5029c6c2011-08-25 11:12:40 -0700180 VLOG(2) << __func__ << " unknown device: " << to_forget->UniqueName();
Chris Masone9be4a9d2011-05-16 15:44:09 -0700181}
182
Chris Masone2b105542011-06-22 10:58:09 -0700183void Manager::RegisterService(const ServiceRefPtr &to_manage) {
Chris Masone6791a432011-07-12 13:23:19 -0700184 // This should look for |to_manage| in the real profiles and, if found,
185 // do...something...to merge the meaningful state, I guess.
186
187 // If not found, add it to the ephemeral profile
188 ephemeral_profile_->AdoptService(to_manage);
189
190 // Now add to OUR list.
191 // TODO(cmasone): Keep this list sorted.
Chris Masonec1e50412011-06-07 13:04:53 -0700192 vector<ServiceRefPtr>::iterator it;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700193 for (it = services_.begin(); it != services_.end(); ++it) {
Chris Masone6791a432011-07-12 13:23:19 -0700194 if (to_manage->UniqueName() == (*it)->UniqueName())
Chris Masone9be4a9d2011-05-16 15:44:09 -0700195 return;
196 }
Chris Masonec1e50412011-06-07 13:04:53 -0700197 services_.push_back(to_manage);
mukesh agrawal32399322011-09-01 10:53:43 -0700198
199 vector<string> service_paths;
200 for (it = services_.begin(); it != services_.end(); ++it) {
201 service_paths.push_back((*it)->GetRpcIdentifier());
202 }
203 adaptor_->EmitRpcIdentifierArrayChanged(flimflam::kServicesProperty,
204 service_paths);
Chris Masone9be4a9d2011-05-16 15:44:09 -0700205}
206
Chris Masone2b105542011-06-22 10:58:09 -0700207void Manager::DeregisterService(const ServiceConstRefPtr &to_forget) {
Chris Masone6791a432011-07-12 13:23:19 -0700208 // If the service is in the ephemeral profile, destroy it.
209 if (!ephemeral_profile_->AbandonService(to_forget->UniqueName())) {
210 // if it's in one of the real profiles...um...I guess mark it unconnectable?
211 }
Chris Masonec1e50412011-06-07 13:04:53 -0700212 vector<ServiceRefPtr>::iterator it;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700213 for (it = services_.begin(); it != services_.end(); ++it) {
Chris Masone6791a432011-07-12 13:23:19 -0700214 if (to_forget->UniqueName() == (*it)->UniqueName()) {
Chris Masone9be4a9d2011-05-16 15:44:09 -0700215 services_.erase(it);
216 return;
217 }
218 }
219}
220
Paul Stewart03dba0b2011-08-22 16:32:45 -0700221void Manager::UpdateService(const ServiceConstRefPtr &to_update) {
222 LOG(INFO) << "Service " << to_update->UniqueName() << " updated;"
223 << " state: " << to_update->state() << " failure: "
224 << to_update->failure();
225 // TODO(pstew): This should trigger re-sorting of services, autoconnect, etc.
226}
227
Chris Masone9be4a9d2011-05-16 15:44:09 -0700228void Manager::FilterByTechnology(Device::Technology tech,
Chris Masonec1e50412011-06-07 13:04:53 -0700229 vector<DeviceRefPtr> *found) {
Chris Masone9be4a9d2011-05-16 15:44:09 -0700230 CHECK(found);
Chris Masonec1e50412011-06-07 13:04:53 -0700231 vector<DeviceRefPtr>::iterator it;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700232 for (it = devices_.begin(); it != devices_.end(); ++it) {
233 if ((*it)->TechnologyIs(tech))
234 found->push_back(*it);
235 }
236}
237
Chris Masonee0dea762011-06-09 09:06:03 -0700238ServiceRefPtr Manager::FindService(const std::string& name) {
Chris Masonec1e50412011-06-07 13:04:53 -0700239 vector<ServiceRefPtr>::iterator it;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700240 for (it = services_.begin(); it != services_.end(); ++it) {
Chris Masone6791a432011-07-12 13:23:19 -0700241 if (name == (*it)->UniqueName())
Chris Masonee0dea762011-06-09 09:06:03 -0700242 return *it;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700243 }
Chris Masonee0dea762011-06-09 09:06:03 -0700244 return NULL;
Chris Masone9be4a9d2011-05-16 15:44:09 -0700245}
246
Chris Masone27c4aa52011-07-02 13:10:14 -0700247void Manager::HelpRegisterDerivedString(const string &name,
Chris Masoneb925cc82011-06-22 15:39:57 -0700248 string(Manager::*get)(void),
249 bool(Manager::*set)(const string&)) {
Chris Masone27c4aa52011-07-02 13:10:14 -0700250 store_.RegisterDerivedString(
251 name,
252 StringAccessor(new CustomAccessor<Manager, string>(this, get, set)));
Chris Masoneb925cc82011-06-22 15:39:57 -0700253}
254
Chris Masone27c4aa52011-07-02 13:10:14 -0700255void Manager::HelpRegisterDerivedStrings(const string &name,
Chris Masonea8a2c252011-06-27 22:16:30 -0700256 Strings(Manager::*get)(void),
257 bool(Manager::*set)(const Strings&)) {
Chris Masone27c4aa52011-07-02 13:10:14 -0700258 store_.RegisterDerivedStrings(
259 name,
260 StringsAccessor(new CustomAccessor<Manager, Strings>(this, get, set)));
Chris Masoneb925cc82011-06-22 15:39:57 -0700261}
262
263string Manager::CalculateState() {
264 return flimflam::kStateOffline;
265}
266
267vector<string> Manager::AvailableTechnologies() {
268 return vector<string>();
269}
270
271vector<string> Manager::ConnectedTechnologies() {
272 return vector<string>();
273}
274
275string Manager::DefaultTechnology() {
276 return "";
277}
278
279vector<string> Manager::EnabledTechnologies() {
280 return vector<string>();
281}
282
Chris Masone3c3f6a12011-07-01 10:01:41 -0700283vector<string> Manager::EnumerateDevices() {
284 vector<string> device_rpc_ids;
285 for (vector<DeviceRefPtr>::const_iterator it = devices_.begin();
286 it != devices_.end();
287 ++it) {
288 device_rpc_ids.push_back((*it)->GetRpcIdentifier());
289 }
290 return device_rpc_ids;
291}
292
293vector<string> Manager::EnumerateAvailableServices() {
Chris Masone3c3f6a12011-07-01 10:01:41 -0700294 vector<string> service_rpc_ids;
295 for (vector<ServiceRefPtr>::const_iterator it = services_.begin();
296 it != services_.end();
297 ++it) {
298 service_rpc_ids.push_back((*it)->GetRpcIdentifier());
299 }
300 return service_rpc_ids;
301}
302
303vector<string> Manager::EnumerateWatchedServices() {
Chris Masone6791a432011-07-12 13:23:19 -0700304 // TODO(cmasone): Filter this list for services in appropriate states.
Chris Masone3c3f6a12011-07-01 10:01:41 -0700305 return EnumerateAvailableServices();
306}
307
Chris Masone7aa5f902011-07-11 11:13:35 -0700308string Manager::GetActiveProfileName() {
Chris Masone7df0c672011-07-15 10:24:54 -0700309 return ActiveProfile()->GetFriendlyName();
Chris Masone7aa5f902011-07-11 11:13:35 -0700310}
311
mukesh agrawal32399322011-09-01 10:53:43 -0700312// called via RPC (e.g., from ManagerDBusAdaptor)
mukesh agrawal7a4e4002011-09-06 11:26:05 -0700313WiFiServiceRefPtr Manager::GetWifiService(const KeyValueStore &args,
314 Error *error) {
315 std::vector<DeviceRefPtr> wifi_devices;
316 FilterByTechnology(Device::kWifi, &wifi_devices);
317 if (wifi_devices.empty()) {
318 error->Populate(Error::kInvalidArguments, kManagerErrorNoDevice);
319 return NULL;
320 } else {
321 WiFi *wifi = dynamic_cast<WiFi *>(wifi_devices.front().get());
322 CHECK(wifi);
323 return wifi->GetService(args, error);
324 }
325}
326
327// called via RPC (e.g., from ManagerDBusAdaptor)
mukesh agrawal32399322011-09-01 10:53:43 -0700328void Manager::RequestScan(const std::string &technology, Error *error) {
329 if (technology == flimflam::kTypeWifi || technology == "") {
330 vector<DeviceRefPtr> wifi_devices;
331 FilterByTechnology(Device::kWifi, &wifi_devices);
332
333 for (vector<DeviceRefPtr>::iterator it = wifi_devices.begin();
334 it != wifi_devices.end();
335 ++it) {
Darin Petkovc0865312011-09-16 15:31:20 -0700336 (*it)->Scan(error);
mukesh agrawal32399322011-09-01 10:53:43 -0700337 }
338 } else {
339 // TODO(quiche): support scanning for other technologies?
340 const string kMessage = "Unrecognized technology " + technology;
341 LOG(ERROR) << kMessage;
342 CHECK(error);
343 error->Populate(Error::kInvalidArguments, kMessage);
344 }
345}
346
Paul Stewart75897df2011-04-27 09:05:53 -0700347} // namespace shill