blob: ffd851c4e3badefec560143bbf1383a1edf27cb8 [file] [log] [blame]
Gilad Arnold55f39b72014-01-28 12:51:45 -08001// Copyright (c) 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
Gilad Arnold55f39b72014-01-28 12:51:45 -08005#include "update_engine/policy_manager/real_shill_provider.h"
6
Gilad Arnold5ef9c482014-03-03 13:51:02 -08007#include <string>
8
9#include <base/logging.h>
Alex Vakulenko75039d72014-03-25 12:36:28 -070010#include <base/strings/stringprintf.h>
Gilad Arnold5ef9c482014-03-03 13:51:02 -080011#include <chromeos/dbus/service_constants.h>
12
Gilad Arnold5ef9c482014-03-03 13:51:02 -080013#include "update_engine/utils.h"
14
15using std::string;
16
17namespace {
18
Gilad Arnoldef120fa2014-04-09 12:52:10 -070019// Looks up a |key| in a GLib |hash_table| and returns the unboxed string from
20// the corresponding GValue, if found.
Gilad Arnold5ef9c482014-03-03 13:51:02 -080021const char* GetStrProperty(GHashTable* hash_table, const char* key) {
22 auto gval = reinterpret_cast<GValue*>(g_hash_table_lookup(hash_table, key));
23 return (gval ? g_value_get_string(gval) : NULL);
24}
25
26}; // namespace
27
28
Gilad Arnold55f39b72014-01-28 12:51:45 -080029namespace chromeos_policy_manager {
30
Gilad Arnoldef120fa2014-04-09 12:52:10 -070031RealShillProvider::~RealShillProvider() {
Gilad Arnoldbeb39e92014-03-11 11:34:50 -070032 // Detach signal handler, free manager proxy.
33 dbus_->ProxyDisconnectSignal(manager_proxy_, shill::kMonitorPropertyChanged,
Gilad Arnoldef120fa2014-04-09 12:52:10 -070034 G_CALLBACK(HandlePropertyChangedStatic),
35 this);
Gilad Arnoldbeb39e92014-03-11 11:34:50 -070036 dbus_->ProxyUnref(manager_proxy_);
37}
38
Gilad Arnoldef120fa2014-04-09 12:52:10 -070039ConnectionType RealShillProvider::ParseConnectionType(const char* type_str) {
40 if (!strcmp(type_str, shill::kTypeEthernet))
41 return ConnectionType::kEthernet;
42 if (!strcmp(type_str, shill::kTypeWifi))
43 return ConnectionType::kWifi;
44 if (!strcmp(type_str, shill::kTypeWimax))
45 return ConnectionType::kWimax;
46 if (!strcmp(type_str, shill::kTypeBluetooth))
47 return ConnectionType::kBluetooth;
48 if (!strcmp(type_str, shill::kTypeCellular))
49 return ConnectionType::kCellular;
Gilad Arnoldbeb39e92014-03-11 11:34:50 -070050
Gilad Arnoldef120fa2014-04-09 12:52:10 -070051 return ConnectionType::kUnknown;
52}
53
54ConnectionTethering RealShillProvider::ParseConnectionTethering(
55 const char* tethering_str) {
56 if (!strcmp(tethering_str, shill::kTetheringNotDetectedState))
57 return ConnectionTethering::kNotDetected;
58 if (!strcmp(tethering_str, shill::kTetheringSuspectedState))
59 return ConnectionTethering::kSuspected;
60 if (!strcmp(tethering_str, shill::kTetheringConfirmedState))
61 return ConnectionTethering::kConfirmed;
62
63 return ConnectionTethering::kUnknown;
64}
65
66bool RealShillProvider::DoInit() {
Gilad Arnoldbeb39e92014-03-11 11:34:50 -070067 // Obtain a DBus connection.
Gilad Arnold5ef9c482014-03-03 13:51:02 -080068 GError* error = NULL;
69 connection_ = dbus_->BusGet(DBUS_BUS_SYSTEM, &error);
70 if (!connection_) {
71 LOG(ERROR) << "Failed to initialize DBus connection: "
72 << chromeos_update_engine::utils::GetAndFreeGError(&error);
73 return false;
74 }
Gilad Arnoldbeb39e92014-03-11 11:34:50 -070075
76 // Allocate a shill manager proxy.
Gilad Arnold5ef9c482014-03-03 13:51:02 -080077 manager_proxy_ = GetProxy(shill::kFlimflamServicePath,
78 shill::kFlimflamManagerInterface);
Gilad Arnold55f39b72014-01-28 12:51:45 -080079
Gilad Arnoldbeb39e92014-03-11 11:34:50 -070080 // Subscribe to the manager's PropertyChanged signal.
81 dbus_->ProxyAddSignal_2(manager_proxy_, shill::kMonitorPropertyChanged,
82 G_TYPE_STRING, G_TYPE_VALUE);
83 dbus_->ProxyConnectSignal(manager_proxy_, shill::kMonitorPropertyChanged,
Gilad Arnoldef120fa2014-04-09 12:52:10 -070084 G_CALLBACK(HandlePropertyChangedStatic),
85 this, NULL);
Gilad Arnold5ef9c482014-03-03 13:51:02 -080086
Gilad Arnoldef120fa2014-04-09 12:52:10 -070087 // Attempt to read initial connection status. Even if this fails because shill
88 // is not responding (e.g. it is down) we'll be notified via "PropertyChanged"
89 // signal as soon as it comes up, so this is not a critical step.
Gilad Arnold5ef9c482014-03-03 13:51:02 -080090 GHashTable* hash_table = NULL;
Gilad Arnoldef120fa2014-04-09 12:52:10 -070091 if (GetProperties(manager_proxy_, &hash_table)) {
92 GValue* value = reinterpret_cast<GValue*>(
93 g_hash_table_lookup(hash_table, shill::kDefaultServiceProperty));
94 ProcessDefaultService(value);
Gilad Arnold5ef9c482014-03-03 13:51:02 -080095 g_hash_table_unref(hash_table);
96 }
97
Gilad Arnoldef120fa2014-04-09 12:52:10 -070098 return true;
Gilad Arnold5ef9c482014-03-03 13:51:02 -080099}
100
Gilad Arnoldef120fa2014-04-09 12:52:10 -0700101DBusGProxy* RealShillProvider::GetProxy(const char* path,
102 const char* interface) {
Gilad Arnold5ef9c482014-03-03 13:51:02 -0800103 return dbus_->ProxyNewForName(connection_, shill::kFlimflamServiceName,
104 path, interface);
105}
106
Gilad Arnoldef120fa2014-04-09 12:52:10 -0700107bool RealShillProvider::GetProperties(DBusGProxy* proxy,
108 GHashTable** result_p) {
Gilad Arnold5ef9c482014-03-03 13:51:02 -0800109 GError* error = NULL;
110 if (!dbus_->ProxyCall_0_1(proxy, shill::kGetPropertiesFunction, &error,
111 result_p)) {
112 LOG(ERROR) << "Calling shill via DBus proxy failed: "
113 << chromeos_update_engine::utils::GetAndFreeGError(&error);
114 return false;
115 }
116 return true;
117}
118
Gilad Arnoldbeb39e92014-03-11 11:34:50 -0700119bool RealShillProvider::ProcessDefaultService(GValue* value) {
120 // Decode the string from the boxed value.
121 const char* default_service_path_str = NULL;
122 if (!(value && (default_service_path_str = g_value_get_string(value))))
123 return false;
124
Gilad Arnoldef120fa2014-04-09 12:52:10 -0700125 // Anything changed?
126 if (default_service_path_ == default_service_path_str)
127 return true;
128
Gilad Arnoldd3df25f2014-04-22 08:39:48 -0700129 // Update the connection status.
Gilad Arnoldbeb39e92014-03-11 11:34:50 -0700130 default_service_path_ = default_service_path_str;
Gilad Arnoldd3df25f2014-04-22 08:39:48 -0700131 bool is_connected = (default_service_path_ != "/");
132 var_is_connected_.SetValue(is_connected);
133 var_conn_last_changed_.SetValue(clock_->GetWallclockTime());
Gilad Arnoldef120fa2014-04-09 12:52:10 -0700134
Gilad Arnoldd3df25f2014-04-22 08:39:48 -0700135 // Update the connection attributes.
136 if (is_connected) {
Gilad Arnoldef120fa2014-04-09 12:52:10 -0700137 DBusGProxy* service_proxy = GetProxy(default_service_path_.c_str(),
138 shill::kFlimflamServiceInterface);
139 GHashTable* hash_table = NULL;
140 if (GetProperties(service_proxy, &hash_table)) {
141 // Get the connection type.
142 const char* type_str = GetStrProperty(hash_table, shill::kTypeProperty);
143 if (type_str && !strcmp(type_str, shill::kTypeVPN)) {
144 type_str = GetStrProperty(hash_table,
145 shill::kPhysicalTechnologyProperty);
146 }
147 if (type_str) {
Gilad Arnoldd3df25f2014-04-22 08:39:48 -0700148 var_conn_type_.SetValue(ParseConnectionType(type_str));
Gilad Arnoldef120fa2014-04-09 12:52:10 -0700149 } else {
Gilad Arnoldd3df25f2014-04-22 08:39:48 -0700150 var_conn_type_.UnsetValue();
Gilad Arnoldef120fa2014-04-09 12:52:10 -0700151 LOG(ERROR) << "Could not find connection type ("
152 << default_service_path_ << ")";
153 }
154
155 // Get the connection tethering mode.
156 const char* tethering_str = GetStrProperty(hash_table,
157 shill::kTetheringProperty);
158 if (tethering_str) {
Gilad Arnoldd3df25f2014-04-22 08:39:48 -0700159 var_conn_tethering_.SetValue(ParseConnectionTethering(tethering_str));
Gilad Arnoldef120fa2014-04-09 12:52:10 -0700160 } else {
Gilad Arnoldd3df25f2014-04-22 08:39:48 -0700161 var_conn_tethering_.UnsetValue();
Gilad Arnoldef120fa2014-04-09 12:52:10 -0700162 LOG(ERROR) << "Could not find connection tethering mode ("
163 << default_service_path_ << ")";
164 }
165
166 g_hash_table_unref(hash_table);
167 }
168 dbus_->ProxyUnref(service_proxy);
Gilad Arnoldd3df25f2014-04-22 08:39:48 -0700169 } else {
170 var_conn_type_.UnsetValue();
171 var_conn_tethering_.UnsetValue();
Gilad Arnoldef120fa2014-04-09 12:52:10 -0700172 }
Gilad Arnolddf3dd242014-04-09 07:15:51 -0700173
Gilad Arnoldbeb39e92014-03-11 11:34:50 -0700174 return true;
175}
176
177void RealShillProvider::HandlePropertyChanged(DBusGProxy* proxy,
178 const char* name, GValue* value) {
179 if (!strcmp(name, shill::kDefaultServiceProperty))
180 ProcessDefaultService(value);
181}
182
183void RealShillProvider::HandlePropertyChangedStatic(DBusGProxy* proxy,
184 const char* name,
185 GValue* value,
186 void* data) {
187 auto obj = reinterpret_cast<RealShillProvider*>(data);
188 obj->HandlePropertyChanged(proxy, name, value);
189}
190
Gilad Arnold55f39b72014-01-28 12:51:45 -0800191} // namespace chromeos_policy_manager