| // |
| // Copyright (C) 2015 The Android Open Source Project |
| // |
| // Licensed under the Apache License, Version 2.0 (the "License"); |
| // you may not use this file except in compliance with the License. |
| // You may obtain a copy of the License at |
| // |
| // http://www.apache.org/licenses/LICENSE-2.0 |
| // |
| // Unless required by applicable law or agreed to in writing, software |
| // distributed under the License is distributed on an "AS IS" BASIS, |
| // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| // See the License for the specific language governing permissions and |
| // limitations under the License. |
| // |
| |
| #include "shill/dbus/chromeos_supplicant_process_proxy.h" |
| |
| #include <string> |
| |
| #include "shill/event_dispatcher.h" |
| #include "shill/logging.h" |
| #include "shill/supplicant/wpa_supplicant.h" |
| |
| using std::string; |
| |
| namespace shill { |
| |
| namespace Logging { |
| static auto kModuleLogScope = ScopeLogger::kDBus; |
| static string ObjectID(const dbus::ObjectPath* p) { return p->value(); } |
| } |
| |
| const char ChromeosSupplicantProcessProxy::kInterfaceName[] = |
| "fi.w1.wpa_supplicant1"; |
| const char ChromeosSupplicantProcessProxy::kPropertyDebugLevel[] = |
| "DebugLevel"; |
| const char ChromeosSupplicantProcessProxy::kPropertyDebugTimestamp[] = |
| "DebugTimestamp"; |
| const char ChromeosSupplicantProcessProxy::kPropertyDebugShowKeys[] = |
| "DebugShowKeys"; |
| const char ChromeosSupplicantProcessProxy::kPropertyInterfaces[] = |
| "Interfaces"; |
| const char ChromeosSupplicantProcessProxy::kPropertyEapMethods[] = |
| "EapMethods"; |
| |
| ChromeosSupplicantProcessProxy::PropertySet::PropertySet( |
| dbus::ObjectProxy* object_proxy, |
| const std::string& interface_name, |
| const PropertyChangedCallback& callback) |
| : dbus::PropertySet(object_proxy, interface_name, callback) { |
| RegisterProperty(kPropertyDebugLevel, &debug_level); |
| RegisterProperty(kPropertyDebugTimestamp, &debug_timestamp); |
| RegisterProperty(kPropertyDebugShowKeys, &debug_show_keys); |
| RegisterProperty(kPropertyInterfaces, &interfaces); |
| RegisterProperty(kPropertyEapMethods, &eap_methods); |
| } |
| |
| ChromeosSupplicantProcessProxy::ChromeosSupplicantProcessProxy( |
| EventDispatcher* dispatcher, |
| const scoped_refptr<dbus::Bus>& bus, |
| const base::Closure& service_appeared_callback, |
| const base::Closure& service_vanished_callback) |
| : supplicant_proxy_( |
| new fi::w1::wpa_supplicant1Proxy( |
| bus, |
| WPASupplicant::kDBusAddr, |
| dbus::ObjectPath(WPASupplicant::kDBusPath))), |
| dispatcher_(dispatcher), |
| service_appeared_callback_(service_appeared_callback), |
| service_vanished_callback_(service_vanished_callback), |
| service_available_(false) { |
| // Register properties. |
| properties_.reset( |
| new PropertySet( |
| supplicant_proxy_->GetObjectProxy(), |
| kInterfaceName, |
| base::Bind(&ChromeosSupplicantProcessProxy::OnPropertyChanged, |
| weak_factory_.GetWeakPtr()))); |
| |
| // Register signal handlers. |
| dbus::ObjectProxy::OnConnectedCallback on_connected_callback = |
| base::Bind(&ChromeosSupplicantProcessProxy::OnSignalConnected, |
| weak_factory_.GetWeakPtr()); |
| supplicant_proxy_->RegisterInterfaceAddedSignalHandler( |
| base::Bind(&ChromeosSupplicantProcessProxy::InterfaceAdded, |
| weak_factory_.GetWeakPtr()), |
| on_connected_callback); |
| supplicant_proxy_->RegisterInterfaceRemovedSignalHandler( |
| base::Bind(&ChromeosSupplicantProcessProxy::InterfaceRemoved, |
| weak_factory_.GetWeakPtr()), |
| on_connected_callback); |
| supplicant_proxy_->RegisterPropertiesChangedSignalHandler( |
| base::Bind(&ChromeosSupplicantProcessProxy::PropertiesChanged, |
| weak_factory_.GetWeakPtr()), |
| on_connected_callback); |
| |
| // Connect property signals and initialize cached values. Based on |
| // recommendations from src/dbus/property.h. |
| properties_->ConnectSignals(); |
| properties_->GetAll(); |
| |
| // Monitor service owner changes. This callback lives for the lifetime of |
| // the ObjectProxy. |
| supplicant_proxy_->GetObjectProxy()->SetNameOwnerChangedCallback( |
| base::Bind(&ChromeosSupplicantProcessProxy::OnServiceOwnerChanged, |
| weak_factory_.GetWeakPtr())); |
| |
| // One time callback when service becomes available. |
| supplicant_proxy_->GetObjectProxy()->WaitForServiceToBeAvailable( |
| base::Bind(&ChromeosSupplicantProcessProxy::OnServiceAvailable, |
| weak_factory_.GetWeakPtr())); |
| } |
| |
| ChromeosSupplicantProcessProxy::~ChromeosSupplicantProcessProxy() {} |
| |
| bool ChromeosSupplicantProcessProxy::CreateInterface( |
| const KeyValueStore& args, string* rpc_identifier) { |
| SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__; |
| if (!service_available_) { |
| LOG(ERROR) << "Supplicant process not present"; |
| return false; |
| } |
| brillo::VariantDictionary dict; |
| KeyValueStore::ConvertToVariantDictionary(args, &dict); |
| dbus::ObjectPath path; |
| brillo::ErrorPtr error; |
| if (!supplicant_proxy_->CreateInterface(dict, &path, &error)) { |
| // Interface might already been created by wpasupplicant. |
| LOG(ERROR) << "Failed to create interface: " |
| << error->GetCode() << " " << error->GetMessage(); |
| return false; |
| } |
| *rpc_identifier = path.value(); |
| return true; |
| } |
| |
| bool ChromeosSupplicantProcessProxy::RemoveInterface( |
| const string& rpc_identifier) { |
| SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__ << ": " |
| << rpc_identifier; |
| if (!service_available_) { |
| LOG(ERROR) << "Supplicant process not present"; |
| return false; |
| } |
| |
| brillo::ErrorPtr error; |
| if (!supplicant_proxy_->RemoveInterface(dbus::ObjectPath(rpc_identifier), |
| &error)) { |
| LOG(FATAL) << "Failed to remove interface " << rpc_identifier << ": " |
| << error->GetCode() << " " << error->GetMessage(); |
| return false; // Make the compiler happy. |
| } |
| return true; |
| } |
| |
| bool ChromeosSupplicantProcessProxy::GetInterface( |
| const std::string& ifname, string* rpc_identifier) { |
| SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__ << ": " << ifname; |
| if (!service_available_) { |
| LOG(ERROR) << "Supplicant process not present"; |
| return false; |
| } |
| |
| dbus::ObjectPath path; |
| brillo::ErrorPtr error; |
| if (!supplicant_proxy_->GetInterface(ifname, &path, &error)) { |
| LOG(FATAL) << "Failed to get interface " << ifname << ": " |
| << error->GetCode() << " " << error->GetMessage(); |
| return false; // Make the compiler happy. |
| } |
| *rpc_identifier = path.value(); |
| return rpc_identifier; |
| } |
| |
| bool ChromeosSupplicantProcessProxy::SetDebugLevel(const std::string& level) { |
| SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__ << ": " << level; |
| if (!service_available_) { |
| LOG(ERROR) << "Supplicant process not present"; |
| return false; |
| } |
| |
| if (!properties_->debug_level.SetAndBlock(level)) { |
| LOG(ERROR) << __func__ << " failed: " << level; |
| return false; |
| } |
| return true; |
| } |
| |
| bool ChromeosSupplicantProcessProxy::GetDebugLevel(string* level) { |
| SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__; |
| if (!service_available_) { |
| LOG(ERROR) << "Supplicant process not present"; |
| return false; |
| } |
| if (!properties_->debug_level.GetAndBlock()) { |
| LOG(ERROR) << "Failed to get DebugLevel"; |
| return false; |
| } |
| *level = properties_->debug_level.value(); |
| return true; |
| } |
| |
| bool ChromeosSupplicantProcessProxy::ExpectDisconnect() { |
| SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__; |
| if (!service_available_) { |
| LOG(ERROR) << "Supplicant process not present"; |
| return false; |
| } |
| brillo::ErrorPtr error; |
| supplicant_proxy_->ExpectDisconnect(&error); |
| return true; |
| } |
| |
| void ChromeosSupplicantProcessProxy::InterfaceAdded( |
| const dbus::ObjectPath& /*path*/, |
| const brillo::VariantDictionary& /*properties*/) { |
| SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__; |
| } |
| |
| void ChromeosSupplicantProcessProxy::InterfaceRemoved( |
| const dbus::ObjectPath& /*path*/) { |
| SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__; |
| } |
| |
| void ChromeosSupplicantProcessProxy::PropertiesChanged( |
| const brillo::VariantDictionary& /*properties*/) { |
| SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__; |
| } |
| |
| void ChromeosSupplicantProcessProxy::OnServiceAvailable(bool available) { |
| SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__ << ": " << available; |
| |
| // The callback might invoke calls to the ObjectProxy, so defer the callback |
| // to event loop. |
| if (available && !service_appeared_callback_.is_null()) { |
| dispatcher_->PostTask(FROM_HERE, service_appeared_callback_); |
| } else if (!available && !service_vanished_callback_.is_null()) { |
| dispatcher_->PostTask(FROM_HERE, service_vanished_callback_); |
| } |
| service_available_ = available; |
| } |
| |
| void ChromeosSupplicantProcessProxy::OnServiceOwnerChanged( |
| const string& old_owner, const string& new_owner) { |
| SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__ |
| << "old: " << old_owner << " new: " << new_owner; |
| if (new_owner.empty()) { |
| OnServiceAvailable(false); |
| } else { |
| OnServiceAvailable(true); |
| } |
| } |
| |
| void ChromeosSupplicantProcessProxy::OnPropertyChanged( |
| const std::string& property_name) { |
| SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__ << ": " |
| << property_name; |
| } |
| |
| void ChromeosSupplicantProcessProxy::OnSignalConnected( |
| const string& interface_name, const string& signal_name, bool success) { |
| SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__ |
| << "interface: " << interface_name << " signal: " << signal_name |
| << "success: " << success; |
| if (!success) { |
| LOG(ERROR) << "Failed to connect signal " << signal_name |
| << " to interface " << interface_name; |
| } |
| } |
| |
| } // namespace shill |