4 * @brief Connman technology request handling.
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 "technology.hpp"
28 #include "service.hpp"
29 #include <settingsd/response_callback.hpp>
30 #include <settingsd/glib_traits.hpp>
31 #include <settingsd/json_glib_traits.hpp>
32 #include <settingsd/smart_ptr.hpp>
38 ivi::settings::technology::technology(std::string tech)
39 : connman_("net.connman.Technology", // Interface
40 ("/net/connman/technology/"
41 + tech).c_str()) // Object path
48 ivi::settings::technology::handle_request(std::string request,
49 response_callback response)
51 smart_ptr<JsonParser> const parser(json_parser_new());
52 json_parser_load_from_data(parser.get(), request.c_str(), -1, nullptr);
54 smart_ptr<JsonReader> const safe_reader(
55 json_reader_new(json_parser_get_root(parser.get())));
56 JsonReader * const reader = safe_reader.get();
58 char const * name = nullptr;
59 if (json_reader_read_member(reader, "name"))
60 name = json_reader_get_string_value(reader);
63 "Malformed " + technology_ + " request: missing 'name' element");
65 json_reader_end_member(reader);
67 if (name != nullptr) {
68 if (strcmp(name, "is_enabled") == 0)
69 get_powered(reader, response);
70 else if (strcmp(name, "enable") == 0)
71 set_powered(reader, response);
72 else if (strcmp(name, "scan") == 0)
73 scan(reader, response);
74 else if (strcmp(name, "connect") == 0)
75 connect(reader, response);
76 else if (strcmp(name, "disconnect") == 0)
77 disconnect(reader, response);
80 "Unrecognized " + technology_ + " request name: "
85 "Operation name for " + technology_ + " request is not a string.");
90 ivi::settings::technology::get_powered(JsonReader * reader,
91 response_callback response)
94 if (json_reader_read_member(reader, "value")) {
95 null = json_reader_get_null_value(reader);
97 json_reader_end_member(reader);
101 technology_ + " is_enabled parameter is not null.");
105 smart_ptr<GVariant> const property(
106 get_property("Powered", G_VARIANT_TYPE_BOOLEAN, response));
108 if (property != nullptr) {
109 bool const powered = g_variant_get_boolean(property.get());
111 response.send_response(
112 [powered](JsonBuilder * builder)
114 json_builder_set_member_name(builder, "value");
115 json_builder_add_boolean_value(builder, powered);
119 // Error responses handled in get_property() method.
123 ivi::settings::technology::set_powered(JsonReader * reader,
124 response_callback response)
127 if (json_reader_read_member(reader, "value")) {
128 enable = json_reader_get_boolean_value(reader);
131 json_reader_end_member(reader);
133 constexpr char const name[] = "Powered";
135 // Get notified when the technology property has changed.
136 auto property_promise = connman_.get_property_changed_promise(name);
137 auto property_future = property_promise->get_future();
139 GError * error = nullptr;
141 smart_ptr<GVariant> ret(
142 connman_.set_property(name,
143 g_variant_new_boolean(enable),
146 smart_ptr<GError> safe_error(error);
148 if (ret != nullptr) {
149 constexpr int const timeout = 5000; // milliseconds
151 // Block until the technology property has changed..
152 std::future_status const status =
153 property_future.wait_for(std::chrono::milliseconds(timeout));
155 if (status == std::future_status::ready) {
157 // Nothing to add to successful response.
158 response.send_response(
159 [](JsonBuilder * /* builder */) {});
164 std::string("Wait for enable status failed: ")
165 + (status == std::future_status::timeout
170 } else if (error != nullptr) {
172 "Unable to set " + technology_ + " powered state: "
176 "Malformed " + technology_ + " enable request value.");
181 ivi::settings::technology::scan(JsonReader * reader,
182 response_callback response)
185 if (json_reader_read_member(reader, "value")) {
186 null = json_reader_get_null_value(reader);
188 json_reader_end_member(reader);
191 response.send_error(technology_ + " scan parameter is not null.");
195 // Get notified when scan results are available.
196 auto services_promise = manager_.get_services_changed_promise();
197 auto services_future = services_promise->get_future();
199 // The scan could take a while.
200 constexpr gint const timeout = 10000; // milliseconds
201 GError * error = nullptr;
203 smart_ptr<GVariant> const ret(
204 g_dbus_proxy_call_sync(connman_.proxy(),
206 nullptr, // No parameters
207 G_DBUS_CALL_FLAGS_NONE,
209 nullptr, // Not cancellable
212 smart_ptr<GError> safe_error(error);
214 if (ret != nullptr) {
215 constexpr gint const future_timeout = 5000; // milliseconds
217 // Block until the scan results are in.
218 std::future_status const status =
219 services_future.wait_for(std::chrono::milliseconds(future_timeout));
221 if (status != std::future_status::deferred) {
222 // Don't call get() if the future isn't ready. Otherwise this
223 // will be a blocking call.
224 if (status == std::future_status::ready) {
225 smart_ptr<JsonNode> const changed_services(services_future.get());
228 send_services(response, error);
230 // A timeout is okay since some services may not have changed
231 // within the timeout period but log it just in case.
232 if (status == std::future_status::timeout)
233 g_debug("%s settings: Timed out waiting for changed services.\n",
234 technology_.c_str());
236 // We only get here if the future status is
237 // std::future_status::deferred, meaning the result hasn't been
238 // determined yet. That should never happen in our case.
239 response.send_error("Wait for scan results failed: deferred");
241 } else if (error != nullptr) {
243 "Unable to scan " + technology_ + ": "
247 "Malformed " + technology_ + " scan request value.");
252 ivi::settings::technology::connect(JsonReader * reader,
253 response_callback response)
255 char const * service_path = nullptr;
256 if (json_reader_read_member(reader, "value")) {
257 service_path = json_reader_get_string_value(reader);
259 json_reader_end_member(reader);
261 /// @todo Refactor malformed JSON request handling code.
262 if (service_path != nullptr) {
263 service s(service_path);
267 "Malformed " + technology_ + " connect request value.");
272 ivi::settings::technology::disconnect(JsonReader * reader,
273 response_callback response)
275 char const * service_path = nullptr;
276 if (json_reader_read_member(reader, "value")) {
277 service_path = json_reader_get_string_value(reader);
279 json_reader_end_member(reader);
281 if (service_path != nullptr) {
282 service s(service_path);
283 s.disconnect(response);
286 "Malformed " + technology_ + " disconnect request value.");
291 ivi::settings::technology::send_services(response_callback response,
294 smart_ptr<GVariant> const services(manager_.get_services(error));
296 if (services != nullptr) {
297 response.send_response(
298 [&services](JsonBuilder * builder)
301 * @todo Can @c json_gvariant_serialize() ever return a nullptr?
303 JsonNode * const value =
304 json_gvariant_serialize(services.get());
306 json_builder_set_member_name(builder, "value");
307 json_builder_add_value(builder, value);
309 // No need to free the JsonNode. The builder will take
316 ivi::settings::technology::get_property(char const * name,
317 GVariantType const * type,
318 response_callback response)
320 GError * error = nullptr;
322 smart_ptr<GVariant> const properties(
323 manager_.get_properties(technology_, error));
325 smart_ptr<GError> safe_error(error);
327 smart_ptr<GVariant> property;
328 if (properties != nullptr) {
330 g_variant_lookup_value(properties.get(), name, type));
332 if (property == nullptr) {
334 "Internal " + technology_
335 + "error: \"" + name + "\" property lookup failed.");
337 } else if (error != nullptr) {
339 "Unable to get " + technology_ + "properties: "
342 // This scenario will occur if the technology doesn't exist on
343 // the platform. For example, attempting to retrieve the wifi
344 // "Powered" property on a platform without supported hardware
345 // will result in this error.
346 response.send_error(technology_ + " properties are not available.");
349 return property.release();
356 // indent-tabs-mode: nil