blob: 2472777718e1eea9bacd186b8060526ba2f3bf16 [file] [log] [blame]
Peter Qiu5dd242d2014-10-14 12:23:21 -07001// Copyright 2014 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
5#include "apmanager/manager.h"
6
Peter Qiu376e4042014-11-13 09:40:28 -08007#include <base/bind.h>
Peter Qiu5dd242d2014-10-14 12:23:21 -07008#include <chromeos/dbus/service_constants.h>
9
Peter Qiu376e4042014-11-13 09:40:28 -080010using chromeos::dbus_utils::AsyncEventSequencer;
11using chromeos::dbus_utils::ExportedObjectManager;
12using chromeos::dbus_utils::DBusMethodResponse;
Peter Qiufb39ba42014-11-21 09:09:59 -080013using std::string;
Peter Qiu376e4042014-11-13 09:40:28 -080014
Peter Qiu5dd242d2014-10-14 12:23:21 -070015namespace apmanager {
16
Peter Qiu376e4042014-11-13 09:40:28 -080017Manager::Manager()
18 : org::chromium::apmanager::ManagerAdaptor(this),
Peter Qiufb39ba42014-11-21 09:09:59 -080019 service_identifier_(0),
20 device_identifier_(0),
Peter Qiu1810c012015-02-05 14:35:41 -080021 device_info_(this) {}
Peter Qiu5dd242d2014-10-14 12:23:21 -070022
Peter Qiubf8e36c2014-12-03 22:59:45 -080023Manager::~Manager() {
24 // Terminate all services before cleanup other resources.
25 for (auto& service : services_) {
26 service.reset();
27 }
28}
Peter Qiu5dd242d2014-10-14 12:23:21 -070029
Peter Qiu376e4042014-11-13 09:40:28 -080030void Manager::RegisterAsync(ExportedObjectManager* object_manager,
Peter Qiuc9ce1f12014-12-05 11:14:29 -080031 const scoped_refptr<dbus::Bus>& bus,
Peter Qiu376e4042014-11-13 09:40:28 -080032 AsyncEventSequencer* sequencer) {
Peter Qiuf0731732014-11-11 09:46:41 -080033 CHECK(!dbus_object_) << "Already registered";
Peter Qiu376e4042014-11-13 09:40:28 -080034 dbus_object_.reset(
35 new chromeos::dbus_utils::DBusObject(
36 object_manager,
Peter Qiuc9ce1f12014-12-05 11:14:29 -080037 bus,
Vitaly Bukaa4630922014-12-11 18:46:46 -080038 org::chromium::apmanager::ManagerAdaptor::GetObjectPath()));
Peter Qiu376e4042014-11-13 09:40:28 -080039 RegisterWithDBusObject(dbus_object_.get());
Peter Qiuf0731732014-11-11 09:46:41 -080040 dbus_object_->RegisterAsync(
Peter Qiu376e4042014-11-13 09:40:28 -080041 sequencer->GetHandler("Manager.RegisterAsync() failed.", true));
Peter Qiuc9ce1f12014-12-05 11:14:29 -080042 bus_ = bus;
43
Peter Qiu1810c012015-02-05 14:35:41 -080044 shill_proxy_.Init(bus);
Peter Qiu943cf3a2015-02-24 10:59:17 -080045 firewall_manager_.Init(bus);
Peter Qiu5dd242d2014-10-14 12:23:21 -070046}
47
Peter Qiufb39ba42014-11-21 09:09:59 -080048void Manager::Start() {
49 device_info_.Start();
50}
51
52void Manager::Stop() {
53 device_info_.Stop();
54}
55
Peter Qiu376e4042014-11-13 09:40:28 -080056void Manager::CreateService(
Peter Qiufd02b6f2015-02-27 09:55:11 -080057 scoped_ptr<DBusMethodResponse<dbus::ObjectPath>> response,
58 dbus::Message* message) {
Peter Qiufb39ba42014-11-21 09:09:59 -080059 LOG(INFO) << "Manager::CreateService";
Peter Qiu376e4042014-11-13 09:40:28 -080060 scoped_refptr<AsyncEventSequencer> sequencer(new AsyncEventSequencer());
Peter Qiufd02b6f2015-02-27 09:55:11 -080061 scoped_ptr<Service> service(new Service(this, service_identifier_));
Peter Qiu376e4042014-11-13 09:40:28 -080062
Peter Qiuc9ce1f12014-12-05 11:14:29 -080063 service->RegisterAsync(
Alex Vakulenkoe7a8bc52014-12-10 12:52:31 -080064 dbus_object_->GetObjectManager().get(), bus_, sequencer.get());
Peter Qiu376e4042014-11-13 09:40:28 -080065 sequencer->OnAllTasksCompletedCall({
Peter Qiu1ff67a72014-11-22 07:06:10 -080066 base::Bind(&Manager::OnServiceRegistered,
Peter Qiu376e4042014-11-13 09:40:28 -080067 base::Unretained(this),
68 base::Passed(&response),
69 base::Passed(&service))
70 });
Peter Qiufd02b6f2015-02-27 09:55:11 -080071
72 base::Closure on_connection_vanish = base::Bind(
73 &Manager::OnAPServiceOwnerDisappeared,
74 base::Unretained(this),
75 service_identifier_);
76 service_watchers_[service_identifier_].reset(
77 new DBusServiceWatcher{bus_, message->GetSender(), on_connection_vanish});
78 service_identifier_++;
Peter Qiu5dd242d2014-10-14 12:23:21 -070079}
80
Peter Qiuf0731732014-11-11 09:46:41 -080081bool Manager::RemoveService(chromeos::ErrorPtr* error,
Peter Qiufd02b6f2015-02-27 09:55:11 -080082 dbus::Message* message,
Peter Qiuf0731732014-11-11 09:46:41 -080083 const dbus::ObjectPath& in_service) {
Peter Qiu376e4042014-11-13 09:40:28 -080084 for (auto it = services_.begin(); it != services_.end(); ++it) {
85 if ((*it)->dbus_path() == in_service) {
Peter Qiufd02b6f2015-02-27 09:55:11 -080086 // Verify the owner.
87 auto watcher = service_watchers_.find((*it)->identifier());
88 CHECK(watcher != service_watchers_.end())
89 << "DBus watcher not created for service: " << (*it)->identifier();
90 if (watcher->second->connection_name() != message->GetSender()) {
91 chromeos::Error::AddToPrintf(
92 error, FROM_HERE, chromeos::errors::dbus::kDomain, kManagerError,
93 "Service %d is owned by another local process.",
94 (*it)->identifier());
95 return false;
96 }
97 service_watchers_.erase(watcher);
98
Peter Qiu376e4042014-11-13 09:40:28 -080099 services_.erase(it);
100 return true;
101 }
102 }
103
104 chromeos::Error::AddTo(
105 error, FROM_HERE, chromeos::errors::dbus::kDomain, kManagerError,
106 "Service does not exist");
Peter Qiuf0731732014-11-11 09:46:41 -0800107 return false;
Peter Qiu5dd242d2014-10-14 12:23:21 -0700108}
109
Peter Qiufb39ba42014-11-21 09:09:59 -0800110scoped_refptr<Device> Manager::GetAvailableDevice() {
111 for (const auto& device : devices_) {
Peter Qiu8e785b92014-11-24 10:01:08 -0800112 // Look for an unused device with AP interface mode support.
113 if (!device->GetInUsed() && !device->GetPreferredApInterface().empty()) {
Peter Qiufb39ba42014-11-21 09:09:59 -0800114 return device;
115 }
116 }
117 return nullptr;
118}
119
120scoped_refptr<Device> Manager::GetDeviceFromInterfaceName(
121 const string& interface_name) {
122 for (const auto& device : devices_) {
123 if (device->InterfaceExists(interface_name)) {
124 return device;
125 }
126 }
127 return nullptr;
128}
129
130void Manager::RegisterDevice(scoped_refptr<Device> device) {
131 LOG(INFO) << "Manager::RegisterDevice: registering device "
132 << device->GetDeviceName();
133 // Register device DBbus interfaces.
134 scoped_refptr<AsyncEventSequencer> sequencer(new AsyncEventSequencer());
135 device->RegisterAsync(dbus_object_->GetObjectManager().get(),
Peter Qiuc9ce1f12014-12-05 11:14:29 -0800136 bus_,
Alex Vakulenkoe7a8bc52014-12-10 12:52:31 -0800137 sequencer.get(),
Peter Qiufb39ba42014-11-21 09:09:59 -0800138 device_identifier_++);
139 sequencer->OnAllTasksCompletedCall({
Peter Qiu1ff67a72014-11-22 07:06:10 -0800140 base::Bind(&Manager::OnDeviceRegistered,
Peter Qiufb39ba42014-11-21 09:09:59 -0800141 base::Unretained(this),
142 device)
143 });
144}
145
Peter Qiu7e0ffcf2014-12-02 12:53:27 -0800146void Manager::ClaimInterface(const string& interface_name) {
Peter Qiu1810c012015-02-05 14:35:41 -0800147 shill_proxy_.ClaimInterface(interface_name);
Peter Qiu7e0ffcf2014-12-02 12:53:27 -0800148}
149
150void Manager::ReleaseInterface(const string& interface_name) {
Peter Qiu1810c012015-02-05 14:35:41 -0800151 shill_proxy_.ReleaseInterface(interface_name);
Peter Qiu7e0ffcf2014-12-02 12:53:27 -0800152}
153
Peter Qiu943cf3a2015-02-24 10:59:17 -0800154void Manager::RequestDHCPPortAccess(const string& interface) {
155 firewall_manager_.RequestDHCPPortAccess(interface);
156}
157
158void Manager::ReleaseDHCPPortAccess(const string& interface) {
159 firewall_manager_.ReleaseDHCPPortAccess(interface);
160}
161
Peter Qiu1ff67a72014-11-22 07:06:10 -0800162void Manager::OnServiceRegistered(
Peter Qiu376e4042014-11-13 09:40:28 -0800163 scoped_ptr<DBusMethodResponse<dbus::ObjectPath>> response,
164 scoped_ptr<Service> service,
165 bool success) {
Peter Qiufb39ba42014-11-21 09:09:59 -0800166 LOG(INFO) << "ServiceRegistered";
Peter Qiu376e4042014-11-13 09:40:28 -0800167 // Success should always be true since we've said that failures are fatal.
168 CHECK(success) << "Init of one or more objects has failed.";
169
Peter Qiufd02b6f2015-02-27 09:55:11 -0800170 // Remove this service if the owner doesn't exist anymore. It is theoretically
171 // possible to have the owner disappear before the AP service complete its
172 // registration with DBus.
173 if (service_watchers_.find(service->identifier()) ==
174 service_watchers_.end()) {
175 LOG(INFO) << "Service " << service->identifier()
176 << ": owner doesn't exist anymore";
177 service.reset();
178 return;
179 }
180
Peter Qiu376e4042014-11-13 09:40:28 -0800181 // Add service to the service list and return the service dbus path for the
182 // CreateService call.
183 dbus::ObjectPath service_path = service->dbus_path();
184 services_.push_back(std::unique_ptr<Service>(service.release()));
185 response->Return(service_path);
186}
187
Peter Qiu1ff67a72014-11-22 07:06:10 -0800188void Manager::OnDeviceRegistered(scoped_refptr<Device> device, bool success) {
Peter Qiufb39ba42014-11-21 09:09:59 -0800189 // Success should always be true since we've said that failures are fatal.
190 CHECK(success) << "Init of one or more objects has failed.";
191
192 devices_.push_back(device);
193 // TODO(zqiu): Property update for available devices.
194}
195
Peter Qiufd02b6f2015-02-27 09:55:11 -0800196void Manager::OnAPServiceOwnerDisappeared(int service_identifier) {
197 LOG(INFO) << "Owner for service " << service_identifier << " disappeared";
198 // Remove service watcher.
199 auto watcher = service_watchers_.find(service_identifier);
200 CHECK(watcher != service_watchers_.end())
201 << "Owner disappeared without watcher setup";
202 service_watchers_.erase(watcher);
203
204 // Remove the service.
205 for (auto it = services_.begin(); it != services_.end(); ++it) {
206 if ((*it)->identifier() == service_identifier) {
207 services_.erase(it);
208 return;
209 }
210 }
211 LOG(INFO) << "Owner for service " << service_identifier
212 << " disappeared before it is registered";
213}
214
Peter Qiu5dd242d2014-10-14 12:23:21 -0700215} // namespace apmanager