3 * WPA supplicant library with GLib integration
5 * Copyright (C) 2012-2013 Intel Corporation. All rights reserved.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
29 #include <dbus/dbus.h>
33 #include <connman/log.h>
37 static DBusConnection *connection;
39 static GSList *method_calls;
41 struct method_call_data {
43 DBusPendingCall *pending_call;
44 supplicant_dbus_result_function function;
48 static void method_call_free(void *pointer)
50 struct method_call_data *method_call = pointer;
51 method_calls = g_slist_remove(method_calls, method_call);
55 static int find_method_call_by_caller(gconstpointer a, gconstpointer b)
57 const struct method_call_data *method_call = a;
58 gconstpointer caller = b;
60 return method_call->caller != caller;
63 static GSList *property_calls;
65 struct property_call_data {
67 DBusPendingCall *pending_call;
68 supplicant_dbus_property_function function;
72 static void property_call_free(void *pointer)
74 struct property_call_data *property_call = pointer;
75 property_calls = g_slist_remove(property_calls, property_call);
76 g_free(property_call);
79 static int find_property_call_by_caller(gconstpointer a, gconstpointer b)
81 const struct property_call_data *property_call = a;
82 gconstpointer caller = b;
84 return property_call->caller != caller;
87 void supplicant_dbus_setup(DBusConnection *conn)
91 property_calls = NULL;
94 void supplicant_dbus_array_foreach(DBusMessageIter *iter,
95 supplicant_dbus_array_function function,
98 DBusMessageIter entry;
100 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
103 dbus_message_iter_recurse(iter, &entry);
105 while (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_INVALID) {
107 function(&entry, user_data);
109 dbus_message_iter_next(&entry);
113 void supplicant_dbus_property_foreach(DBusMessageIter *iter,
114 supplicant_dbus_property_function function,
117 DBusMessageIter dict;
119 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
122 dbus_message_iter_recurse(iter, &dict);
124 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
125 DBusMessageIter entry, value;
128 dbus_message_iter_recurse(&dict, &entry);
130 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
133 dbus_message_iter_get_basic(&entry, &key);
134 dbus_message_iter_next(&entry);
136 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
139 dbus_message_iter_recurse(&entry, &value);
142 if (strcmp(key, "Properties") == 0)
143 supplicant_dbus_property_foreach(&value,
144 function, user_data);
146 function(key, &value, user_data);
149 dbus_message_iter_next(&dict);
153 void supplicant_dbus_property_call_cancel_all(gpointer caller)
155 while (property_calls) {
156 struct property_call_data *property_call;
157 GSList *elem = g_slist_find_custom(property_calls, caller,
158 find_property_call_by_caller);
162 property_call = elem->data;
163 property_calls = g_slist_delete_link(property_calls, elem);
165 dbus_pending_call_cancel(property_call->pending_call);
167 dbus_pending_call_unref(property_call->pending_call);
171 static void property_get_all_reply(DBusPendingCall *call, void *user_data)
173 struct property_call_data *property_call = user_data;
175 DBusMessageIter iter;
177 reply = dbus_pending_call_steal_reply(call);
179 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
182 if (!dbus_message_iter_init(reply, &iter))
185 supplicant_dbus_property_foreach(&iter, property_call->function,
186 property_call->user_data);
188 if (property_call->function)
189 property_call->function(NULL, NULL, property_call->user_data);
192 dbus_message_unref(reply);
194 dbus_pending_call_unref(call);
197 int supplicant_dbus_property_get_all(const char *path, const char *interface,
198 supplicant_dbus_property_function function,
199 void *user_data, gpointer caller)
201 struct property_call_data *property_call = NULL;
202 DBusMessage *message;
203 DBusPendingCall *call;
208 if (!path || !interface)
211 property_call = g_try_new0(struct property_call_data, 1);
215 message = dbus_message_new_method_call(SUPPLICANT_SERVICE, path,
216 DBUS_INTERFACE_PROPERTIES, "GetAll");
218 g_free(property_call);
222 dbus_message_set_auto_start(message, FALSE);
224 dbus_message_append_args(message, DBUS_TYPE_STRING, &interface, NULL);
226 if (!dbus_connection_send_with_reply(connection, message,
228 dbus_message_unref(message);
229 g_free(property_call);
234 dbus_message_unref(message);
235 g_free(property_call);
239 property_call->caller = caller;
240 property_call->pending_call = call;
241 property_call->function = function;
242 property_call->user_data = user_data;
244 property_calls = g_slist_prepend(property_calls, property_call);
246 dbus_pending_call_set_notify(call, property_get_all_reply,
247 property_call, property_call_free);
249 dbus_message_unref(message);
254 static void property_get_reply(DBusPendingCall *call, void *user_data)
256 struct property_call_data *property_call = user_data;
258 DBusMessageIter iter;
260 reply = dbus_pending_call_steal_reply(call);
262 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
265 if (!dbus_message_iter_init(reply, &iter))
268 if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_VARIANT) {
269 DBusMessageIter variant;
271 dbus_message_iter_recurse(&iter, &variant);
273 if (property_call->function)
274 property_call->function(NULL, &variant,
275 property_call->user_data);
278 dbus_message_unref(reply);
280 dbus_pending_call_unref(call);
283 int supplicant_dbus_property_get(const char *path, const char *interface,
285 supplicant_dbus_property_function function,
286 void *user_data, gpointer caller)
288 struct property_call_data *property_call = NULL;
289 DBusMessage *message;
290 DBusPendingCall *call;
295 if (!path || !interface || !method)
298 property_call = g_try_new0(struct property_call_data, 1);
302 message = dbus_message_new_method_call(SUPPLICANT_SERVICE, path,
303 DBUS_INTERFACE_PROPERTIES, "Get");
306 g_free(property_call);
310 dbus_message_set_auto_start(message, FALSE);
312 dbus_message_append_args(message, DBUS_TYPE_STRING, &interface,
313 DBUS_TYPE_STRING, &method, NULL);
315 if (!dbus_connection_send_with_reply(connection, message,
317 dbus_message_unref(message);
318 g_free(property_call);
323 dbus_message_unref(message);
324 g_free(property_call);
328 property_call->caller = caller;
329 property_call->pending_call = call;
330 property_call->function = function;
331 property_call->user_data = user_data;
333 property_calls = g_slist_prepend(property_calls, property_call);
335 dbus_pending_call_set_notify(call, property_get_reply,
336 property_call, property_call_free);
338 dbus_message_unref(message);
343 static void property_set_reply(DBusPendingCall *call, void *user_data)
345 struct property_call_data *property_call = user_data;
347 DBusMessageIter iter;
350 reply = dbus_pending_call_steal_reply(call);
352 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
353 error = dbus_message_get_error_name(reply);
357 dbus_message_iter_init(reply, &iter);
359 if (property_call->function)
360 property_call->function(error, &iter, property_call->user_data);
362 dbus_message_unref(reply);
364 dbus_pending_call_unref(call);
367 int supplicant_dbus_property_set(const char *path, const char *interface,
368 const char *key, const char *signature,
369 supplicant_dbus_setup_function setup,
370 supplicant_dbus_result_function function,
371 void *user_data, gpointer caller)
373 struct property_call_data *property_call = NULL;
374 DBusMessage *message;
375 DBusMessageIter iter, value;
376 DBusPendingCall *call;
381 if (!path || !interface)
384 if (!key || !signature || !setup)
387 property_call = g_try_new0(struct property_call_data, 1);
391 message = dbus_message_new_method_call(SUPPLICANT_SERVICE, path,
392 DBUS_INTERFACE_PROPERTIES, "Set");
394 g_free(property_call);
398 dbus_message_set_auto_start(message, FALSE);
400 dbus_message_iter_init_append(message, &iter);
401 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface);
402 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key);
404 dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
406 setup(&value, user_data);
407 dbus_message_iter_close_container(&iter, &value);
409 if (!dbus_connection_send_with_reply(connection, message,
411 dbus_message_unref(message);
412 g_free(property_call);
417 dbus_message_unref(message);
418 g_free(property_call);
422 property_call->caller = caller;
423 property_call->pending_call = call;
424 property_call->function = function;
425 property_call->user_data = user_data;
427 property_calls = g_slist_prepend(property_calls, property_call);
429 dbus_pending_call_set_notify(call, property_set_reply,
430 property_call, property_call_free);
432 dbus_message_unref(message);
437 void supplicant_dbus_method_call_cancel_all(gpointer caller)
439 while (method_calls) {
440 struct method_call_data *method_call;
441 GSList *elem = g_slist_find_custom(method_calls, caller,
442 find_method_call_by_caller);
446 method_call = elem->data;
447 method_calls = g_slist_delete_link(method_calls, elem);
449 dbus_pending_call_cancel(method_call->pending_call);
451 if (method_call->function)
452 method_call->function("net.connman.Error.OperationAborted",
453 NULL, method_call->user_data);
455 dbus_pending_call_unref(method_call->pending_call);
459 static void method_call_reply(DBusPendingCall *call, void *user_data)
461 struct method_call_data *method_call = user_data;
463 DBusMessageIter iter;
466 reply = dbus_pending_call_steal_reply(call);
468 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
469 error = dbus_message_get_error_name(reply);
473 dbus_message_iter_init(reply, &iter);
475 if (method_call && method_call->function)
476 method_call->function(error, &iter, method_call->user_data);
478 dbus_message_unref(reply);
480 dbus_pending_call_unref(call);
483 int supplicant_dbus_method_call(const char *path,
484 const char *interface, const char *method,
485 supplicant_dbus_setup_function setup,
486 supplicant_dbus_result_function function,
490 struct method_call_data *method_call = NULL;
491 DBusMessage *message;
492 DBusMessageIter iter;
493 DBusPendingCall *call;
498 if (!path || !interface || !method)
501 method_call = g_try_new0(struct method_call_data, 1);
505 message = dbus_message_new_method_call(SUPPLICANT_SERVICE, path,
512 dbus_message_set_auto_start(message, FALSE);
514 dbus_message_iter_init_append(message, &iter);
516 setup(&iter, user_data);
518 if (!dbus_connection_send_with_reply(connection, message,
520 dbus_message_unref(message);
526 dbus_message_unref(message);
531 method_call->caller = caller;
532 method_call->pending_call = call;
533 method_call->function = function;
534 method_call->user_data = user_data;
535 method_calls = g_slist_prepend(method_calls, method_call);
537 dbus_pending_call_set_notify(call, method_call_reply, method_call,
540 dbus_message_unref(message);
545 void supplicant_dbus_property_append_basic(DBusMessageIter *iter,
546 const char *key, int type, void *val)
548 DBusMessageIter value;
549 const char *signature;
551 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &key);
554 case DBUS_TYPE_BOOLEAN:
555 signature = DBUS_TYPE_BOOLEAN_AS_STRING;
557 case DBUS_TYPE_STRING:
558 signature = DBUS_TYPE_STRING_AS_STRING;
561 signature = DBUS_TYPE_BYTE_AS_STRING;
563 case DBUS_TYPE_UINT16:
564 signature = DBUS_TYPE_UINT16_AS_STRING;
566 case DBUS_TYPE_INT16:
567 signature = DBUS_TYPE_INT16_AS_STRING;
569 case DBUS_TYPE_UINT32:
570 signature = DBUS_TYPE_UINT32_AS_STRING;
572 case DBUS_TYPE_INT32:
573 signature = DBUS_TYPE_INT32_AS_STRING;
575 case DBUS_TYPE_OBJECT_PATH:
576 signature = DBUS_TYPE_OBJECT_PATH_AS_STRING;
579 signature = DBUS_TYPE_VARIANT_AS_STRING;
583 dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
585 dbus_message_iter_append_basic(&value, type, val);
586 dbus_message_iter_close_container(iter, &value);
589 void supplicant_dbus_property_append_fixed_array(DBusMessageIter *iter,
590 const char *key, int type, void *val, int len)
592 DBusMessageIter value, array;
593 const char *variant_sig, *array_sig;
597 variant_sig = DBUS_TYPE_ARRAY_AS_STRING
598 DBUS_TYPE_BYTE_AS_STRING;
599 array_sig = DBUS_TYPE_BYTE_AS_STRING;
605 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &key);
607 dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
608 variant_sig, &value);
610 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
612 dbus_message_iter_append_fixed_array(&array, type, val, len);
613 dbus_message_iter_close_container(&value, &array);
615 dbus_message_iter_close_container(iter, &value);
618 void supplicant_dbus_property_append_array(DBusMessageIter *iter,
619 const char *key, int type,
620 supplicant_dbus_array_function function,
623 DBusMessageIter value, array;
624 const char *variant_sig, *array_sig;
627 case DBUS_TYPE_STRING:
629 variant_sig = DBUS_TYPE_ARRAY_AS_STRING
630 DBUS_TYPE_ARRAY_AS_STRING
631 DBUS_TYPE_BYTE_AS_STRING;
632 array_sig = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING;
638 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &key);
640 dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
641 variant_sig, &value);
643 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
646 function(&array, user_data);
648 dbus_message_iter_close_container(&value, &array);
650 dbus_message_iter_close_container(iter, &value);