Home | History | Annotate | Download | only in dbus
      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