1 // 2 // Copyright (C) 2015 The Android Open Source Project 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 // 16 17 #include "shill/dbus/chromeos_supplicant_process_proxy.h" 18 19 #include <string> 20 21 #include "shill/event_dispatcher.h" 22 #include "shill/logging.h" 23 #include "shill/supplicant/wpa_supplicant.h" 24 25 using std::string; 26 27 namespace shill { 28 29 namespace Logging { 30 static auto kModuleLogScope = ScopeLogger::kDBus; 31 static string ObjectID(const dbus::ObjectPath* p) { return p->value(); } 32 } 33 34 const char ChromeosSupplicantProcessProxy::kInterfaceName[] = 35 "fi.w1.wpa_supplicant1"; 36 const char ChromeosSupplicantProcessProxy::kPropertyDebugLevel[] = 37 "DebugLevel"; 38 const char ChromeosSupplicantProcessProxy::kPropertyDebugTimestamp[] = 39 "DebugTimestamp"; 40 const char ChromeosSupplicantProcessProxy::kPropertyDebugShowKeys[] = 41 "DebugShowKeys"; 42 const char ChromeosSupplicantProcessProxy::kPropertyInterfaces[] = 43 "Interfaces"; 44 const char ChromeosSupplicantProcessProxy::kPropertyEapMethods[] = 45 "EapMethods"; 46 47 ChromeosSupplicantProcessProxy::PropertySet::PropertySet( 48 dbus::ObjectProxy* object_proxy, 49 const std::string& interface_name, 50 const PropertyChangedCallback& callback) 51 : dbus::PropertySet(object_proxy, interface_name, callback) { 52 RegisterProperty(kPropertyDebugLevel, &debug_level); 53 RegisterProperty(kPropertyDebugTimestamp, &debug_timestamp); 54 RegisterProperty(kPropertyDebugShowKeys, &debug_show_keys); 55 RegisterProperty(kPropertyInterfaces, &interfaces); 56 RegisterProperty(kPropertyEapMethods, &eap_methods); 57 } 58 59 ChromeosSupplicantProcessProxy::ChromeosSupplicantProcessProxy( 60 EventDispatcher* dispatcher, 61 const scoped_refptr<dbus::Bus>& bus, 62 const base::Closure& service_appeared_callback, 63 const base::Closure& service_vanished_callback) 64 : supplicant_proxy_( 65 new fi::w1::wpa_supplicant1Proxy( 66 bus, 67 WPASupplicant::kDBusAddr, 68 dbus::ObjectPath(WPASupplicant::kDBusPath))), 69 dispatcher_(dispatcher), 70 service_appeared_callback_(service_appeared_callback), 71 service_vanished_callback_(service_vanished_callback), 72 service_available_(false) { 73 // Register properties. 74 properties_.reset( 75 new PropertySet( 76 supplicant_proxy_->GetObjectProxy(), 77 kInterfaceName, 78 base::Bind(&ChromeosSupplicantProcessProxy::OnPropertyChanged, 79 weak_factory_.GetWeakPtr()))); 80 81 // Register signal handlers. 82 dbus::ObjectProxy::OnConnectedCallback on_connected_callback = 83 base::Bind(&ChromeosSupplicantProcessProxy::OnSignalConnected, 84 weak_factory_.GetWeakPtr()); 85 supplicant_proxy_->RegisterInterfaceAddedSignalHandler( 86 base::Bind(&ChromeosSupplicantProcessProxy::InterfaceAdded, 87 weak_factory_.GetWeakPtr()), 88 on_connected_callback); 89 supplicant_proxy_->RegisterInterfaceRemovedSignalHandler( 90 base::Bind(&ChromeosSupplicantProcessProxy::InterfaceRemoved, 91 weak_factory_.GetWeakPtr()), 92 on_connected_callback); 93 supplicant_proxy_->RegisterPropertiesChangedSignalHandler( 94 base::Bind(&ChromeosSupplicantProcessProxy::PropertiesChanged, 95 weak_factory_.GetWeakPtr()), 96 on_connected_callback); 97 98 // Connect property signals and initialize cached values. Based on 99 // recommendations from src/dbus/property.h. 100 properties_->ConnectSignals(); 101 properties_->GetAll(); 102 103 // Monitor service owner changes. This callback lives for the lifetime of 104 // the ObjectProxy. 105 supplicant_proxy_->GetObjectProxy()->SetNameOwnerChangedCallback( 106 base::Bind(&ChromeosSupplicantProcessProxy::OnServiceOwnerChanged, 107 weak_factory_.GetWeakPtr())); 108 109 // One time callback when service becomes available. 110 supplicant_proxy_->GetObjectProxy()->WaitForServiceToBeAvailable( 111 base::Bind(&ChromeosSupplicantProcessProxy::OnServiceAvailable, 112 weak_factory_.GetWeakPtr())); 113 } 114 115 ChromeosSupplicantProcessProxy::~ChromeosSupplicantProcessProxy() {} 116 117 bool ChromeosSupplicantProcessProxy::CreateInterface( 118 const KeyValueStore& args, string* rpc_identifier) { 119 SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__; 120 if (!service_available_) { 121 LOG(ERROR) << "Supplicant process not present"; 122 return false; 123 } 124 brillo::VariantDictionary dict; 125 KeyValueStore::ConvertToVariantDictionary(args, &dict); 126 dbus::ObjectPath path; 127 brillo::ErrorPtr error; 128 if (!supplicant_proxy_->CreateInterface(dict, &path, &error)) { 129 // Interface might already been created by wpasupplicant. 130 LOG(ERROR) << "Failed to create interface: " 131 << error->GetCode() << " " << error->GetMessage(); 132 return false; 133 } 134 *rpc_identifier = path.value(); 135 return true; 136 } 137 138 bool ChromeosSupplicantProcessProxy::RemoveInterface( 139 const string& rpc_identifier) { 140 SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__ << ": " 141 << rpc_identifier; 142 if (!service_available_) { 143 LOG(ERROR) << "Supplicant process not present"; 144 return false; 145 } 146 147 brillo::ErrorPtr error; 148 if (!supplicant_proxy_->RemoveInterface(dbus::ObjectPath(rpc_identifier), 149 &error)) { 150 LOG(FATAL) << "Failed to remove interface " << rpc_identifier << ": " 151 << error->GetCode() << " " << error->GetMessage(); 152 return false; // Make the compiler happy. 153 } 154 return true; 155 } 156 157 bool ChromeosSupplicantProcessProxy::GetInterface( 158 const std::string& ifname, string* rpc_identifier) { 159 SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__ << ": " << ifname; 160 if (!service_available_) { 161 LOG(ERROR) << "Supplicant process not present"; 162 return false; 163 } 164 165 dbus::ObjectPath path; 166 brillo::ErrorPtr error; 167 if (!supplicant_proxy_->GetInterface(ifname, &path, &error)) { 168 LOG(FATAL) << "Failed to get interface " << ifname << ": " 169 << error->GetCode() << " " << error->GetMessage(); 170 return false; // Make the compiler happy. 171 } 172 *rpc_identifier = path.value(); 173 return rpc_identifier; 174 } 175 176 bool ChromeosSupplicantProcessProxy::SetDebugLevel(const std::string& level) { 177 SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__ << ": " << level; 178 if (!service_available_) { 179 LOG(ERROR) << "Supplicant process not present"; 180 return false; 181 } 182 183 if (!properties_->debug_level.SetAndBlock(level)) { 184 LOG(ERROR) << __func__ << " failed: " << level; 185 return false; 186 } 187 return true; 188 } 189 190 bool ChromeosSupplicantProcessProxy::GetDebugLevel(string* level) { 191 SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__; 192 if (!service_available_) { 193 LOG(ERROR) << "Supplicant process not present"; 194 return false; 195 } 196 if (!properties_->debug_level.GetAndBlock()) { 197 LOG(ERROR) << "Failed to get DebugLevel"; 198 return false; 199 } 200 *level = properties_->debug_level.value(); 201 return true; 202 } 203 204 bool ChromeosSupplicantProcessProxy::ExpectDisconnect() { 205 SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__; 206 if (!service_available_) { 207 LOG(ERROR) << "Supplicant process not present"; 208 return false; 209 } 210 brillo::ErrorPtr error; 211 supplicant_proxy_->ExpectDisconnect(&error); 212 return true; 213 } 214 215 void ChromeosSupplicantProcessProxy::InterfaceAdded( 216 const dbus::ObjectPath& /*path*/, 217 const brillo::VariantDictionary& /*properties*/) { 218 SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__; 219 } 220 221 void ChromeosSupplicantProcessProxy::InterfaceRemoved( 222 const dbus::ObjectPath& /*path*/) { 223 SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__; 224 } 225 226 void ChromeosSupplicantProcessProxy::PropertiesChanged( 227 const brillo::VariantDictionary& /*properties*/) { 228 SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__; 229 } 230 231 void ChromeosSupplicantProcessProxy::OnServiceAvailable(bool available) { 232 SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__ << ": " << available; 233 234 // The callback might invoke calls to the ObjectProxy, so defer the callback 235 // to event loop. 236 if (available && !service_appeared_callback_.is_null()) { 237 dispatcher_->PostTask(service_appeared_callback_); 238 } else if (!available && !service_vanished_callback_.is_null()) { 239 dispatcher_->PostTask(service_vanished_callback_); 240 } 241 service_available_ = available; 242 } 243 244 void ChromeosSupplicantProcessProxy::OnServiceOwnerChanged( 245 const string& old_owner, const string& new_owner) { 246 SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__ 247 << "old: " << old_owner << " new: " << new_owner; 248 if (new_owner.empty()) { 249 OnServiceAvailable(false); 250 } else { 251 OnServiceAvailable(true); 252 } 253 } 254 255 void ChromeosSupplicantProcessProxy::OnPropertyChanged( 256 const std::string& property_name) { 257 SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__ << ": " 258 << property_name; 259 } 260 261 void ChromeosSupplicantProcessProxy::OnSignalConnected( 262 const string& interface_name, const string& signal_name, bool success) { 263 SLOG(&supplicant_proxy_->GetObjectPath(), 2) << __func__ 264 << "interface: " << interface_name << " signal: " << signal_name 265 << "success: " << success; 266 if (!success) { 267 LOG(ERROR) << "Failed to connect signal " << signal_name 268 << " to interface " << interface_name; 269 } 270 } 271 272 } // namespace shill 273