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>
36 static DBusConnection *connection;
38 static GSList *method_calls;
40 struct method_call_data {
42 DBusPendingCall *pending_call;
43 supplicant_dbus_result_function function;
47 static void method_call_free(void *pointer)
49 struct method_call_data *method_call = pointer;
50 method_calls = g_slist_remove(method_calls, method_call);
54 static int find_method_call_by_caller(gconstpointer a, gconstpointer b)
56 const struct method_call_data *method_call = a;
57 gconstpointer caller = b;
59 return method_call->caller != caller;
62 static GSList *property_calls;
64 struct property_call_data {
66 DBusPendingCall *pending_call;
67 supplicant_dbus_property_function function;
71 static void property_call_free(void *pointer)
73 struct property_call_data *property_call = pointer;
74 property_calls = g_slist_remove(property_calls, property_call);
75 g_free(property_call);
78 static int find_property_call_by_caller(gconstpointer a, gconstpointer b)
80 const struct property_call_data *property_call = a;
81 gconstpointer caller = b;
83 return property_call->caller != caller;
86 void supplicant_dbus_setup(DBusConnection *conn)
90 property_calls = NULL;
93 void supplicant_dbus_array_foreach(DBusMessageIter *iter,
94 supplicant_dbus_array_function function,
97 DBusMessageIter entry;
99 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
102 dbus_message_iter_recurse(iter, &entry);
104 while (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_INVALID) {
106 function(&entry, user_data);
108 dbus_message_iter_next(&entry);
112 void supplicant_dbus_property_foreach(DBusMessageIter *iter,
113 supplicant_dbus_property_function function,
116 DBusMessageIter dict;
118 if (dbus_message_iter_get_arg_type(iter) != DBUS_TYPE_ARRAY)
121 dbus_message_iter_recurse(iter, &dict);
123 while (dbus_message_iter_get_arg_type(&dict) == DBUS_TYPE_DICT_ENTRY) {
124 DBusMessageIter entry, value;
127 dbus_message_iter_recurse(&dict, &entry);
129 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING)
132 dbus_message_iter_get_basic(&entry, &key);
133 dbus_message_iter_next(&entry);
135 if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT)
138 dbus_message_iter_recurse(&entry, &value);
141 if (strcmp(key, "Properties") == 0)
142 supplicant_dbus_property_foreach(&value,
143 function, user_data);
145 function(key, &value, user_data);
148 dbus_message_iter_next(&dict);
152 void supplicant_dbus_property_call_cancel_all(gpointer caller)
154 while (property_calls) {
155 struct property_call_data *property_call;
156 GSList *elem = g_slist_find_custom(property_calls, caller,
157 find_property_call_by_caller);
161 property_call = elem->data;
162 property_calls = g_slist_delete_link(property_calls, elem);
164 dbus_pending_call_cancel(property_call->pending_call);
166 dbus_pending_call_unref(property_call->pending_call);
170 static void property_get_all_reply(DBusPendingCall *call, void *user_data)
172 struct property_call_data *property_call = user_data;
174 DBusMessageIter iter;
176 reply = dbus_pending_call_steal_reply(call);
178 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
181 if (!dbus_message_iter_init(reply, &iter))
184 supplicant_dbus_property_foreach(&iter, property_call->function,
185 property_call->user_data);
187 if (property_call->function)
188 property_call->function(NULL, NULL, property_call->user_data);
191 dbus_message_unref(reply);
193 dbus_pending_call_unref(call);
196 int supplicant_dbus_property_get_all(const char *path, const char *interface,
197 supplicant_dbus_property_function function,
198 void *user_data, gpointer caller)
200 struct property_call_data *property_call = NULL;
201 DBusMessage *message;
202 DBusPendingCall *call;
207 if (!path || !interface)
210 property_call = g_try_new0(struct property_call_data, 1);
214 message = dbus_message_new_method_call(SUPPLICANT_SERVICE, path,
215 DBUS_INTERFACE_PROPERTIES, "GetAll");
217 g_free(property_call);
221 dbus_message_set_auto_start(message, FALSE);
223 dbus_message_append_args(message, DBUS_TYPE_STRING, &interface, NULL);
225 if (!dbus_connection_send_with_reply(connection, message,
227 dbus_message_unref(message);
228 g_free(property_call);
233 dbus_message_unref(message);
234 g_free(property_call);
238 property_call->caller = caller;
239 property_call->pending_call = call;
240 property_call->function = function;
241 property_call->user_data = user_data;
243 property_calls = g_slist_prepend(property_calls, property_call);
245 dbus_pending_call_set_notify(call, property_get_all_reply,
246 property_call, property_call_free);
248 dbus_message_unref(message);
253 static void property_get_reply(DBusPendingCall *call, void *user_data)
255 struct property_call_data *property_call = user_data;
257 DBusMessageIter iter;
259 reply = dbus_pending_call_steal_reply(call);
261 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
264 if (!dbus_message_iter_init(reply, &iter))
267 if (dbus_message_iter_get_arg_type(&iter) == DBUS_TYPE_VARIANT) {
268 DBusMessageIter variant;
270 dbus_message_iter_recurse(&iter, &variant);
272 if (property_call->function)
273 property_call->function(NULL, &variant,
274 property_call->user_data);
277 dbus_message_unref(reply);
279 dbus_pending_call_unref(call);
282 int supplicant_dbus_property_get(const char *path, const char *interface,
284 supplicant_dbus_property_function function,
285 void *user_data, gpointer caller)
287 struct property_call_data *property_call = NULL;
288 DBusMessage *message;
289 DBusPendingCall *call;
294 if (!path || !interface || !method)
297 property_call = g_try_new0(struct property_call_data, 1);
301 message = dbus_message_new_method_call(SUPPLICANT_SERVICE, path,
302 DBUS_INTERFACE_PROPERTIES, "Get");
305 g_free(property_call);
309 dbus_message_set_auto_start(message, FALSE);
311 dbus_message_append_args(message, DBUS_TYPE_STRING, &interface,
312 DBUS_TYPE_STRING, &method, NULL);
314 if (!dbus_connection_send_with_reply(connection, message,
316 dbus_message_unref(message);
317 g_free(property_call);
322 dbus_message_unref(message);
323 g_free(property_call);
327 property_call->caller = caller;
328 property_call->pending_call = call;
329 property_call->function = function;
330 property_call->user_data = user_data;
332 property_calls = g_slist_prepend(property_calls, property_call);
334 dbus_pending_call_set_notify(call, property_get_reply,
335 property_call, property_call_free);
337 dbus_message_unref(message);
342 static void property_set_reply(DBusPendingCall *call, void *user_data)
344 struct property_call_data *property_call = user_data;
346 DBusMessageIter iter;
349 reply = dbus_pending_call_steal_reply(call);
351 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
352 error = dbus_message_get_error_name(reply);
356 dbus_message_iter_init(reply, &iter);
358 if (property_call->function)
359 property_call->function(error, &iter, property_call->user_data);
361 dbus_message_unref(reply);
363 dbus_pending_call_unref(call);
366 int supplicant_dbus_property_set(const char *path, const char *interface,
367 const char *key, const char *signature,
368 supplicant_dbus_setup_function setup,
369 supplicant_dbus_result_function function,
370 void *user_data, gpointer caller)
372 struct property_call_data *property_call = NULL;
373 DBusMessage *message;
374 DBusMessageIter iter, value;
375 DBusPendingCall *call;
380 if (!path || !interface)
383 if (!key || !signature || !setup)
386 property_call = g_try_new0(struct property_call_data, 1);
390 message = dbus_message_new_method_call(SUPPLICANT_SERVICE, path,
391 DBUS_INTERFACE_PROPERTIES, "Set");
393 g_free(property_call);
397 dbus_message_set_auto_start(message, FALSE);
399 dbus_message_iter_init_append(message, &iter);
400 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &interface);
401 dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &key);
403 dbus_message_iter_open_container(&iter, DBUS_TYPE_VARIANT,
405 setup(&value, user_data);
406 dbus_message_iter_close_container(&iter, &value);
408 if (!dbus_connection_send_with_reply(connection, message,
410 dbus_message_unref(message);
411 g_free(property_call);
416 dbus_message_unref(message);
417 g_free(property_call);
421 property_call->caller = caller;
422 property_call->pending_call = call;
423 property_call->function = function;
424 property_call->user_data = user_data;
426 property_calls = g_slist_prepend(property_calls, property_call);
428 dbus_pending_call_set_notify(call, property_set_reply,
429 property_call, property_call_free);
431 dbus_message_unref(message);
436 void supplicant_dbus_method_call_cancel_all(gpointer caller)
438 while (method_calls) {
439 struct method_call_data *method_call;
440 GSList *elem = g_slist_find_custom(method_calls, caller,
441 find_method_call_by_caller);
445 method_call = elem->data;
446 method_calls = g_slist_delete_link(method_calls, elem);
448 dbus_pending_call_cancel(method_call->pending_call);
450 if (method_call->function)
451 method_call->function("net.connman.Error.OperationAborted",
452 NULL, method_call->user_data);
454 dbus_pending_call_unref(method_call->pending_call);
458 static void method_call_reply(DBusPendingCall *call, void *user_data)
460 struct method_call_data *method_call = user_data;
462 DBusMessageIter iter;
465 reply = dbus_pending_call_steal_reply(call);
467 if (dbus_message_get_type(reply) == DBUS_MESSAGE_TYPE_ERROR)
468 error = dbus_message_get_error_name(reply);
472 dbus_message_iter_init(reply, &iter);
474 if (method_call && method_call->function)
475 method_call->function(error, &iter, method_call->user_data);
477 dbus_message_unref(reply);
479 dbus_pending_call_unref(call);
482 int supplicant_dbus_method_call(const char *path,
483 const char *interface, const char *method,
484 supplicant_dbus_setup_function setup,
485 supplicant_dbus_result_function function,
489 struct method_call_data *method_call = NULL;
490 DBusMessage *message;
491 DBusMessageIter iter;
492 DBusPendingCall *call;
497 if (!path || !interface || !method)
500 method_call = g_try_new0(struct method_call_data, 1);
504 message = dbus_message_new_method_call(SUPPLICANT_SERVICE, path,
511 dbus_message_set_auto_start(message, FALSE);
513 dbus_message_iter_init_append(message, &iter);
515 setup(&iter, user_data);
517 if (!dbus_connection_send_with_reply(connection, message,
519 dbus_message_unref(message);
525 dbus_message_unref(message);
530 method_call->caller = caller;
531 method_call->pending_call = call;
532 method_call->function = function;
533 method_call->user_data = user_data;
534 method_calls = g_slist_prepend(method_calls, method_call);
536 dbus_pending_call_set_notify(call, method_call_reply, method_call,
539 dbus_message_unref(message);
544 void supplicant_dbus_property_append_basic(DBusMessageIter *iter,
545 const char *key, int type, void *val)
547 DBusMessageIter value;
548 const char *signature;
550 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &key);
553 case DBUS_TYPE_BOOLEAN:
554 signature = DBUS_TYPE_BOOLEAN_AS_STRING;
556 case DBUS_TYPE_STRING:
557 signature = DBUS_TYPE_STRING_AS_STRING;
560 signature = DBUS_TYPE_BYTE_AS_STRING;
562 case DBUS_TYPE_UINT16:
563 signature = DBUS_TYPE_UINT16_AS_STRING;
565 case DBUS_TYPE_INT16:
566 signature = DBUS_TYPE_INT16_AS_STRING;
568 case DBUS_TYPE_UINT32:
569 signature = DBUS_TYPE_UINT32_AS_STRING;
571 case DBUS_TYPE_INT32:
572 signature = DBUS_TYPE_INT32_AS_STRING;
574 case DBUS_TYPE_OBJECT_PATH:
575 signature = DBUS_TYPE_OBJECT_PATH_AS_STRING;
578 signature = DBUS_TYPE_VARIANT_AS_STRING;
582 dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
584 dbus_message_iter_append_basic(&value, type, val);
585 dbus_message_iter_close_container(iter, &value);
588 void supplicant_dbus_property_append_fixed_array(DBusMessageIter *iter,
589 const char *key, int type, void *val, int len)
591 DBusMessageIter value, array;
592 const char *variant_sig, *array_sig;
596 variant_sig = DBUS_TYPE_ARRAY_AS_STRING
597 DBUS_TYPE_BYTE_AS_STRING;
598 array_sig = DBUS_TYPE_BYTE_AS_STRING;
604 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &key);
606 dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
607 variant_sig, &value);
609 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
611 dbus_message_iter_append_fixed_array(&array, type, val, len);
612 dbus_message_iter_close_container(&value, &array);
614 dbus_message_iter_close_container(iter, &value);
617 void supplicant_dbus_property_append_array(DBusMessageIter *iter,
618 const char *key, int type,
619 supplicant_dbus_array_function function,
622 DBusMessageIter value, array;
623 const char *variant_sig, *array_sig;
626 case DBUS_TYPE_STRING:
628 variant_sig = DBUS_TYPE_ARRAY_AS_STRING
629 DBUS_TYPE_ARRAY_AS_STRING
630 DBUS_TYPE_BYTE_AS_STRING;
631 array_sig = DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_BYTE_AS_STRING;
637 dbus_message_iter_append_basic(iter, DBUS_TYPE_STRING, &key);
639 dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
640 variant_sig, &value);
642 dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
645 function(&array, user_data);
647 dbus_message_iter_close_container(&value, &array);
649 dbus_message_iter_close_container(iter, &value);