adding network sample
[libicd-wpa] / dbus-helper.c
1 /**
2   @file dbus-helper.c
3
4   Copyright (C) 2004 Nokia Corporation. All rights reserved.
5   Copyright (C) 2003-2009, Jouni Malinen <j@w1.fi> and contributors. 
6   Copyright (C) 2009 Javier S. Pedro
7
8   @author Janne Ylalehto <janne.ylalehto@nokia.com>
9   @author Johan Hedberg <johan.hedberg@nokia.com> 
10   @author Jouni Malinen <j@w1.fi> and contributors
11   @author Javier S. Pedro <javispedro@javispedro.com>
12
13   This program is free software; you can redistribute it and/or modify it
14   under the terms of the GNU General Public License as published by the
15   Free Software Foundation; either version 2 of the License, or (at your
16   option) any later version.
17
18   This program is distributed in the hope that it will be useful, but
19   WITHOUT ANY WARRANTY; without even the implied warranty of
20   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
21   General Public License for more details.
22
23   You should have received a copy of the GNU General Public License along
24   with this program; if not, write to the Free Software Foundation, Inc.,
25   59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
26
27
28 */
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <glib.h>
32
33 #define DBUS_API_SUBJECT_TO_CHANGE
34 #include <dbus/dbus.h>
35 #include "log.h"
36 #include "dbus-helper.h"
37
38 DBusMessage *new_dbus_signal(const char *path,
39                              const char *interface,
40                              const char *name,
41                              const char *destination) {
42         DBusMessage *signal;
43
44         signal = dbus_message_new_signal(path, interface, name);
45         if (signal == NULL) {
46                 die("Out of memory during dbus_message_new_error()");
47         }
48
49         if (destination) {
50                 if (!dbus_message_set_destination(signal, destination)) {
51                         die("Out of memory during dbus_message_set_destination()");
52                 }
53         }
54
55         dbus_message_set_no_reply(signal, TRUE);
56
57         return signal;
58 }
59
60 DBusMessage *new_dbus_method_call(const char *service,
61                                   const char *path,
62                                   const char *interface,
63                                   const char *method) {
64         DBusMessage *message;
65
66         message = dbus_message_new_method_call(service, path, interface, method);
67         if (message == NULL) {
68                 die("Out of memory during dbus_message_new_method_call()");
69         }
70
71         return message;
72 }
73
74 DBusMessage *new_dbus_method_return(DBusMessage *message) {
75         DBusMessage *reply;
76
77         reply = dbus_message_new_method_return(message);
78         if (reply == NULL) {
79                 die("Out of memory during dbus_message_new_method_return()");
80         }
81
82         return reply;
83 }
84
85 DBusMessage *new_dbus_error(DBusMessage *message, const char *name) {
86         DBusMessage *error;
87
88         error = dbus_message_new_error(message, name, NULL);
89         if (error == NULL) {
90                 die("Out of memory during dbus_message_new_error()");
91         }
92
93         return error;
94 }
95
96 int send_and_unref(DBusConnection *connection, DBusMessage *message) {
97         if (!dbus_connection_send(connection, message, NULL)) {
98                 dbus_message_unref(message);
99                 return -1;
100         }
101
102         dbus_connection_flush(connection);
103         dbus_message_unref(message);
104
105         return 0;
106 }
107
108 int send_invalid_args(DBusConnection *connection, DBusMessage *message) {
109         DBusMessage *reply;
110
111         reply = new_dbus_error(message, DBUS_ERROR_INVALID_ARGS);
112
113         return send_and_unref(connection, reply);
114 }
115
116 void append_dbus_args(DBusMessage *message, int first_arg_type, ...) {
117         dbus_bool_t ret;
118         va_list ap;
119
120         va_start(ap, first_arg_type);
121         ret = dbus_message_append_args_valist(message, first_arg_type, ap);
122         va_end(ap);
123
124         if (ret == FALSE) {
125                 die("dbus_message_append_args failed");
126         }
127 }
128
129 /**
130  * Start a dict in a dbus message.  Should be paired with a call to
131  * {@link wpa_dbus_dict_close_write}.
132  *
133  * @param iter A valid dbus message iterator
134  * @param iter_dict (out) A dict iterator to pass to further dict functions
135  * @return 0 on success, -1 on failure
136  *
137  */
138 int dbus_dict_open_write(DBusMessageIter *iter,
139                                      DBusMessageIter *iter_dict)
140 {
141         dbus_bool_t result;
142
143         if (!iter || !iter_dict)
144                 return FALSE;
145
146         result = dbus_message_iter_open_container(
147                 iter,
148                 DBUS_TYPE_ARRAY,
149                 DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
150                 DBUS_TYPE_STRING_AS_STRING
151                 DBUS_TYPE_VARIANT_AS_STRING
152                 DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
153                 iter_dict);
154         
155         return (result ? 0 : -1);
156 }
157
158 /**
159  * End a dict element in a dbus message.  Should be paired with
160  * a call to {@link wpa_dbus_dict_open_write}.
161  *
162  * @param iter valid dbus message iterator, same as passed to
163  *    wpa_dbus_dict_open_write()
164  * @param iter_dict a dbus dict iterator returned from
165  *    {@link wpa_dbus_dict_open_write}
166  * @return 0 on success, -1 on failure
167  *
168  */
169 int dbus_dict_close_write(DBusMessageIter *iter,
170                                       DBusMessageIter *iter_dict)
171 {
172         if (!iter || !iter_dict)
173                 return FALSE;
174
175         return dbus_message_iter_close_container(iter, iter_dict) ? 0 : -1;
176 }
177
178 static const char * _get_type_as_string_from_type(const int type)
179 {
180         switch(type) {
181         case DBUS_TYPE_BYTE:
182                 return DBUS_TYPE_BYTE_AS_STRING;
183         case DBUS_TYPE_BOOLEAN:
184                 return DBUS_TYPE_BOOLEAN_AS_STRING;
185         case DBUS_TYPE_INT16:
186                 return DBUS_TYPE_INT16_AS_STRING;
187         case DBUS_TYPE_UINT16:
188                 return DBUS_TYPE_UINT16_AS_STRING;
189         case DBUS_TYPE_INT32:
190                 return DBUS_TYPE_INT32_AS_STRING;
191         case DBUS_TYPE_UINT32:
192                 return DBUS_TYPE_UINT32_AS_STRING;
193         case DBUS_TYPE_INT64:
194                 return DBUS_TYPE_INT64_AS_STRING;
195         case DBUS_TYPE_UINT64:
196                 return DBUS_TYPE_UINT64_AS_STRING;
197         case DBUS_TYPE_DOUBLE:
198                 return DBUS_TYPE_DOUBLE_AS_STRING;
199         case DBUS_TYPE_STRING:
200                 return DBUS_TYPE_STRING_AS_STRING;
201         case DBUS_TYPE_OBJECT_PATH:
202                 return DBUS_TYPE_OBJECT_PATH_AS_STRING;
203         case DBUS_TYPE_ARRAY:
204                 return DBUS_TYPE_ARRAY_AS_STRING;
205         default:
206                 return NULL;
207         }
208 }
209
210 static int _dbus_add_dict_entry_start(
211         DBusMessageIter *iter_dict, DBusMessageIter *iter_dict_entry,
212         const char *key, const int value_type)
213 {
214         if (!dbus_message_iter_open_container(iter_dict,
215                                               DBUS_TYPE_DICT_ENTRY, NULL,
216                                               iter_dict_entry))
217                 return FALSE;
218
219         if (!dbus_message_iter_append_basic(iter_dict_entry, DBUS_TYPE_STRING,
220                                             &key))
221                 return FALSE;
222
223         return TRUE;
224 }
225
226
227 static dbus_bool_t _dbus_add_dict_entry_end(
228         DBusMessageIter *iter_dict, DBusMessageIter *iter_dict_entry,
229         DBusMessageIter *iter_dict_val)
230 {
231         if (!dbus_message_iter_close_container(iter_dict_entry, iter_dict_val))
232                 return FALSE;
233         if (!dbus_message_iter_close_container(iter_dict, iter_dict_entry))
234                 return FALSE;
235
236         return TRUE;
237 }
238
239 static dbus_bool_t _dbus_add_dict_entry_basic(DBusMessageIter *iter_dict,
240                                                   const char *key,
241                                                   const int value_type,
242                                                   const void *value)
243 {
244         DBusMessageIter iter_dict_entry, iter_dict_val;
245         const char *type_as_string = NULL;
246
247         type_as_string = _get_type_as_string_from_type(value_type);
248         if (!type_as_string)
249                 return FALSE;
250
251         if (!_dbus_add_dict_entry_start(iter_dict, &iter_dict_entry,
252                                             key, value_type))
253                 return FALSE;
254
255         if (!dbus_message_iter_open_container(&iter_dict_entry,
256                                               DBUS_TYPE_VARIANT,
257                                               type_as_string, &iter_dict_val))
258                 return FALSE;
259
260         if (!dbus_message_iter_append_basic(&iter_dict_val, value_type, value))
261                 return FALSE;
262
263         if (!_dbus_add_dict_entry_end(iter_dict, &iter_dict_entry,
264                                           &iter_dict_val))
265                 return FALSE;
266
267         return TRUE;
268 }
269
270 /**
271  * Add a string entry to the dict.
272  *
273  * @param iter_dict A valid DBusMessageIter returned from
274  *    {@link wpa_dbus_dict_open_write}
275  * @param key The key of the dict item
276  * @param value The string value
277  * @return TRUE on success, FALSE on failure
278  *
279  */
280 int dbus_dict_append_string(DBusMessageIter *iter_dict,
281                                         const char *key, const char *value)
282 {
283         if (!key || !value)
284                 return FALSE;
285         return _dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_STRING,
286                                               &value) ? 0 : -1;
287 }
288
289 /**
290  * Add a 32-bit signed integer to the dict.
291  *
292  * @param iter_dict A valid DBusMessageIter returned from
293  *    {@link wpa_dbus_dict_open_write}
294  * @param key The key of the dict item
295  * @param value The 32-bit signed integer value
296  * @return TRUE on success, FALSE on failure
297  *
298  */
299 int dbus_dict_append_int32(DBusMessageIter *iter_dict,
300                                        const char *key,
301                                        const dbus_int32_t value)
302 {
303         if (!key)
304                 return FALSE;
305         return _dbus_add_dict_entry_basic(iter_dict, key, DBUS_TYPE_INT32,
306                                               &value) ? 0 : -1;
307 }
308