2 * @file connman_manager.cpp
4 * @brief Connman Manager operations.
6 * @author Ossama Othman @<ossama.othman@@intel.com@>
9 * Copyright 2013 Intel Corporation All Rights Reserved.
11 * This library is free software; you can redistribute it and/or
12 * modify it under the terms of the GNU Lesser General Public
13 * License as published by the Free Software Foundation;
14 * version 2.1 of the License.
16 * This library is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
19 * Lesser General Public License for more details.
21 * You should have received a copy of the GNU Lesser General Public
22 * License along with this library; if not, write to the Free Software
23 * Foundation, Inc., 51 Franklin Street, Fifth Floor,
24 * Boston, MA 02110-1301 USA
27 #include "connman_manager.hpp"
29 #include <settingsd/response_callback.hpp>
30 #include <settingsd/dbus_signal_callback.hpp>
31 #include <settingsd/glib_traits.hpp>
32 #include <settingsd/unique_ptr.hpp>
37 // ----------------------------------------------------------------------
41 std::string const manager_name("connman::manager");
44 on_technology_added(GDBusConnection * connection,
45 char const * sender_name,
46 char const * object_path,
47 char const * interface_name,
48 char const * signal_name,
49 GVariant * parameters,
52 // The technology's object path is found in the first argument.
53 ivi::settings::unique_ptr<GVariant> const tech_path(
54 g_variant_get_child_value(parameters, 0));
56 // Subscribe to the technology's PropertyChanged signal.
57 typedef ivi::settings::connman_manager::signal_data signal_data;
58 signal_data * const data = static_cast<signal_data *>(user_data);
60 data->subscriptions.subscribe("net.connman.Technology",
62 g_variant_get_string(tech_path.get(),
65 ivi::settings::on_dbus_signal(connection,
75 on_technology_removed(GDBusConnection * connection,
76 char const * sender_name,
77 char const * object_path,
78 char const * interface_name,
79 char const * signal_name,
80 GVariant * parameters,
83 // The technology's object path is found in the first argument.
84 ivi::settings::unique_ptr<GVariant> const tech_path(
85 g_variant_get_child_value(parameters, 0));
87 // Unubscribe from the technology's PropertyChanged signal.
88 typedef ivi::settings::connman_manager::signal_data signal_data;
89 signal_data * const data = static_cast<signal_data *>(user_data);
91 data->subscriptions.unsubscribe(
92 g_variant_get_string(tech_path.get(), nullptr));
94 ivi::settings::on_dbus_signal(connection,
104 // ----------------------------------------------------------------------
106 ivi::settings::connman_manager::connman_manager(
107 GDBusConnection * connection,
108 event_callback const & e)
109 : connman_("net.connman.Manager", // Interface
112 , data_(connection, e)
113 , technology_added_id_(subscribe_to_signal(connection,
117 , technology_removed_id_(subscribe_to_signal(connection,
119 on_technology_removed,
121 , services_changed_id_(subscribe_to_signal(connection,
127 // The ServicesChanged signal parameters are:
129 // array{object, dict}, array{object})
131 // where "object" is the D-Bus object path, and "dict" is a
132 // dictionary of object-specific properties. The first parameter is
133 // list of changed services. The second is a list of removed
137 * @todo Refactor duplicate code found here an in get_properties()
140 // Subscribe to PropertyChanged signal for all technologies.
141 GError * error = nullptr;
143 unique_ptr<GVariant> const dictionary(
144 call_method("GetTechnologies",
145 nullptr, // No parameters,
148 unique_ptr<GError> safe_error(error);
150 if (dictionary != nullptr) {
151 GVariantIter * i = nullptr;
152 g_variant_get(dictionary.get(), "(a(oa{sv}))", &i);
153 unique_ptr<GVariantIter> const safe_i(i);
155 for (unique_ptr<GVariant> child(g_variant_iter_next_value(i));
157 child.reset(g_variant_iter_next_value(i))) {
159 // The object path is the first tuple element.
160 unique_ptr<GVariant> const tmp(
161 g_variant_get_child_value(child.get(), 0));
163 char const * const tech_path =
164 g_variant_get_string(tmp.get(), nullptr);
166 data_.subscriptions.subscribe("net.connman.Technology",
172 // Register the Agent implementation responsible for handling input
173 // requests for secure and hidden networks.
174 if (!g_variant_is_object_path(agent_.object_path())) {
175 throw std::invalid_argument(std::string("Invalid Agent object path: ")
176 + agent_.object_path());
180 unique_ptr<GVariant> const ret(
181 call_method("RegisterAgent",
183 agent_.object_path()),
186 if (ret == nullptr) {
187 safe_error.reset(error);
189 g_warning("Unable to register agent: %s. "
190 "Hidden and protected connections will "
191 "not be supported.\n",
196 ivi::settings::connman_manager::~connman_manager()
199 if (g_variant_is_object_path(agent_.object_path())) {
200 GError * error = nullptr;
202 unique_ptr<GVariant> const ret(
203 call_method("UnregisterAgent",
205 agent_.object_path()),
208 if (ret == nullptr) {
209 unique_ptr<GError> const safe_error(error);
211 g_warning("Unable to unregister agent: %s\n", error->message);
215 // Unsubscribe from ServicesChanged, TechnologyRemoved and
216 // TechnologyAdded signals.
217 g_dbus_connection_signal_unsubscribe(connman_.connection(),
218 services_changed_id_);
219 g_dbus_connection_signal_unsubscribe(connman_.connection(),
220 technology_removed_id_);
221 g_dbus_connection_signal_unsubscribe(connman_.connection(),
222 technology_added_id_);
226 ivi::settings::connman_manager::id() const
232 ivi::settings::connman_manager::handle_request(
234 response_callback response)
236 unique_ptr<JsonParser> const parser(json_parser_new());
237 json_parser_load_from_data(parser.get(), request.c_str(), -1, nullptr);
239 unique_ptr<JsonReader> const safe_reader(
240 json_reader_new(json_parser_get_root(parser.get())));
241 JsonReader * const reader = safe_reader.get();
243 char const * name = nullptr;
244 if (json_reader_read_member(reader, "name"))
245 name = json_reader_get_string_value(reader);
248 "Malformed " + id() + " request: missing 'name' element");
250 json_reader_end_member(reader);
252 if (name != nullptr) {
253 if (strcmp(name, "get_technologies") == 0)
254 get_technologies(response);
255 else if (strcmp(name, "get_services") == 0)
256 get_services(response);
259 "Unrecognized " + id() + " request name: "
264 "Operation name for " + id() + " request is not a string.");
269 ivi::settings::connman_manager::register_connect_data(
270 char const * service_path,
271 std::map<std::string, std::string> && info,
272 response_callback const & response)
274 return agent_.register_connect_data(service_path,
280 ivi::settings::connman_manager::deregister_connect_data(
281 char const * service_path)
283 return agent_.deregister_connect_data(service_path);
287 ivi::settings::connman_manager::get_properties(
288 std::string const & technology,
289 GError *& error) const
291 unique_ptr<GVariant> const dictionary(
292 call_method("GetTechnologies",
293 nullptr, // No parameters,
296 if (dictionary != nullptr) {
297 GVariantIter * i = nullptr;
298 g_variant_get(dictionary.get(), "(a(oa{sv}))", &i);
299 unique_ptr<GVariantIter> const safe_i(i);
301 for (unique_ptr<GVariant> child(g_variant_iter_next_value(i));
303 child.reset(g_variant_iter_next_value(i))) {
305 // The object path is the first tuple element.
306 unique_ptr<GVariant> const tmp(
307 g_variant_get_child_value(child.get(), 0));
309 char const * const object =
310 g_variant_get_string(tmp.get(), nullptr);
312 // The technology is found at end the object path,
313 // e.g. "/net/connman/technology/wifi" for the wifi.
314 char const * tech = strrchr(object, '/');
316 if (tech != nullptr) {
317 ++tech; // Skip the found '/'.
319 if (technology == tech) {
320 // The property dictionary is the second tuple element.
321 return g_variant_get_child_value(child.get(), 1);
331 ivi::settings::connman_manager::get_services(
332 response_callback & response) const
334 constexpr char name[] = "GetServices";
335 GError * error = nullptr;
337 unique_ptr<GVariant> ret(call_method(name,
338 nullptr, // No parameters
341 unique_ptr<GError> safe_error(error);
343 handle_return_value(name, ret.get(), error, response);
347 ivi::settings::connman_manager::get_technologies(
348 response_callback & response) const
350 constexpr char name[] = "GetTechnologies";
351 GError * error = nullptr;
353 unique_ptr<GVariant> ret(call_method(name,
354 nullptr, // No parameters
357 unique_ptr<GError> safe_error(error);
359 handle_return_value(name, ret.get(), error, response);
363 ivi::settings::connman_manager::call_method(
365 GVariant * parameters,
366 GError *& error) const
368 constexpr gint const timeout = 5000; // milliseconds
371 g_dbus_proxy_call_sync(connman_.proxy(),
374 G_DBUS_CALL_FLAGS_NONE,
376 nullptr, // Not cancellable
381 ivi::settings::connman_manager::handle_return_value(
385 response_callback & response) const
387 if (ret != nullptr) {
388 response.send_response(
389 [ret](JsonBuilder * builder)
392 * @todo Can @c json_gvariant_serialize() ever return a nullptr?
394 JsonNode * const value =
395 json_gvariant_serialize(ret);
397 json_builder_set_member_name(builder, "value");
398 json_builder_add_value(builder, value);
400 // No need to free the JsonNode. The builder will take
403 } else if (error != nullptr) {
404 response.send_error(std::string(name) + " failed: " + error->message);
409 ivi::settings::connman_manager::subscribe_to_signal(
410 GDBusConnection * connection,
412 ivi_signal_callback callback,
416 g_dbus_connection_signal_subscribe(connection,
418 connman_.interface_name(),
420 connman_.object_path(),
422 G_DBUS_SIGNAL_FLAGS_NONE,
431 // indent-tabs-mode: nil