Check already powered during Wi-Fi enable/disable
[platform/core/connectivity/net-config.git] / src / dbus / netdbus.c
1 /*
2  * Network Configuration Module
3  *
4  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd. All rights reserved.
5  *
6  * Licensed under the Apache License, Version 2.0 (the "License");
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  * http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  *
18  */
19
20 #include <stdio.h>
21 #include <string.h>
22 #include <stdlib.h>
23
24 #include "log.h"
25 #include "netdbus.h"
26 #include "netconfig.h"
27
28 #define NETCONFIG_DBUS_REPLY_TIMEOUT (10 * 1000)
29
30 #define DBUS_PARAM_TYPE_STRING          "string"
31 #define DBUS_PARAM_TYPE_INT16           "int16"
32 #define DBUS_PARAM_TYPE_UINT16          "uint16"
33 #define DBUS_PARAM_TYPE_INT32           "int32"
34 #define DBUS_PARAM_TYPE_UINT32          "uint32"
35 #define DBUS_PARAM_TYPE_INT64           "int64"
36 #define DBUS_PARAM_TYPE_UINT64          "uint64"
37 #define DBUS_PARAM_TYPE_DOUBLE          "double"
38 #define DBUS_PARAM_TYPE_BYTE            "byte"
39 #define DBUS_PARAM_TYPE_BOOLEAN         "boolean"
40 #define DBUS_PARAM_TYPE_OBJECT_PATH     "objpath"
41 #define DBUS_PARAM_TYPE_VARIANT         "variant"
42 #define DBUS_PARAM_TYPE_ARRAY           "array"
43
44
45 static gboolean __netconfig_dbus_append_param_variant(
46                 DBusMessageIter *iter, char *type, char *param)
47 {
48         DBusMessageIter value, array;
49         char *args = NULL, *ch = NULL;
50         dbus_bool_t b_value = FALSE;
51
52         if (strcmp(type, DBUS_PARAM_TYPE_STRING) == 0) {
53                 dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
54                                 DBUS_TYPE_STRING_AS_STRING, &value);
55
56                 dbus_message_iter_append_basic(&value, DBUS_TYPE_STRING, &param);
57
58                 dbus_message_iter_close_container(iter, &value);
59         } else if (strcmp(type, DBUS_PARAM_TYPE_BOOLEAN) == 0) {
60                 if (strcmp(param, "true") == 0) {
61                         b_value = TRUE;
62                         dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
63                                         DBUS_TYPE_BOOLEAN_AS_STRING, &value);
64                         dbus_message_iter_append_basic(&value,
65                                         DBUS_TYPE_BOOLEAN, &b_value);
66                         dbus_message_iter_close_container(iter, &value);
67                 } else if (strcmp(param, "false") == 0) {
68                         b_value = FALSE;
69                         dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
70                                         DBUS_TYPE_BOOLEAN_AS_STRING, &value);
71                         dbus_message_iter_append_basic(&value,
72                                         DBUS_TYPE_BOOLEAN, &b_value);
73                         dbus_message_iter_close_container(iter, &value);
74                 } else {
75                         ERR("Error!!! Expected \"true\" or"
76                                 "\"false\" instead of \"%s\"", ch);
77                         return FALSE;
78                 }
79         } else if (strcmp(type, DBUS_PARAM_TYPE_OBJECT_PATH) == 0) {
80                 dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
81                                 DBUS_TYPE_OBJECT_PATH_AS_STRING, &value);
82
83                 dbus_message_iter_append_basic(&value, DBUS_TYPE_OBJECT_PATH, &param);
84
85                 dbus_message_iter_close_container(iter, &value);
86         } else if (strcmp(type, DBUS_PARAM_TYPE_ARRAY) == 0) {
87                 args = param;
88                 ch = strchr(args, ':');
89                 if (ch == NULL) {
90                         ERR("Error!!! Invalid data format[\"%s\"]", args);
91                         return FALSE;
92                 }
93                 *ch = 0; ch++;
94
95                 if (strcmp(args, DBUS_PARAM_TYPE_STRING) == 0) {
96                         dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
97                                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_STRING_AS_STRING,
98                                         &value);
99
100                         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
101                                         DBUS_TYPE_STRING_AS_STRING, &array);
102
103                         dbus_message_iter_append_basic(&array, DBUS_TYPE_STRING, &ch);
104
105                         dbus_message_iter_close_container(&value, &array);
106
107                         dbus_message_iter_close_container(iter, &value);
108                 } else if (strcmp(args, DBUS_PARAM_TYPE_OBJECT_PATH) == 0) {
109                         dbus_message_iter_open_container(iter, DBUS_TYPE_VARIANT,
110                                         DBUS_TYPE_ARRAY_AS_STRING DBUS_TYPE_OBJECT_PATH_AS_STRING,
111                                         &value);
112
113                         dbus_message_iter_open_container(&value, DBUS_TYPE_ARRAY,
114                                         DBUS_TYPE_OBJECT_PATH_AS_STRING, &array);
115
116                         dbus_message_iter_append_basic(&array, DBUS_TYPE_OBJECT_PATH, &ch);
117
118                         dbus_message_iter_close_container(&value, &array);
119
120                         dbus_message_iter_close_container(iter, &value);
121                 } else {
122                         ERR("Error!!! Not supported data format[\"%s\"]", args);
123                         return FALSE;
124                 }
125         } else {
126                 ERR("Error!!! Not supported data format[\"%s\"]", args);
127                 return FALSE;
128         }
129
130         return TRUE;
131 }
132
133 static gboolean __netconfig_dbus_append_param(
134                 DBusMessage *message, char *param_array[])
135 {
136         int count = 0;
137         dbus_uint32_t uint32 = 0;
138         DBusMessageIter iter;
139         char *args = NULL, *ch = NULL;
140
141         if (param_array == NULL)
142                 return TRUE;
143
144         dbus_message_iter_init_append(message, &iter);
145
146         while (param_array[count] != NULL) {
147                 args = param_array[count];
148                 DBG("parameter %d - [%s]", count, param_array[count]);
149
150                 ch = strchr(args, ':');
151                 if (ch == NULL) {
152                         ERR("Error!!! Invalid parameter[\"%s\"]\n", args);
153                         return FALSE;
154                 }
155                 *ch = 0; ch++;
156
157                 if (strcmp(args, DBUS_PARAM_TYPE_STRING) == 0) {
158                         dbus_message_iter_append_basic(&iter, DBUS_TYPE_STRING, &ch);
159                 } else if (strcmp(args, DBUS_PARAM_TYPE_UINT32) == 0) {
160                         uint32 = strtoul(ch, NULL, 0);
161                         dbus_message_iter_append_basic(&iter, DBUS_TYPE_UINT32, &uint32);
162                 } else if (strcmp(args, DBUS_PARAM_TYPE_VARIANT) == 0) {
163                         args = ch;
164                         ch = strchr(args, ':');
165                         if (ch == NULL) {
166                                 ERR("Error!!! Invalid data format[\"%s\"]\n", args);
167                                 return FALSE;
168                         }
169                         *ch = 0; ch++;
170
171                         if (__netconfig_dbus_append_param_variant(&iter, args, ch) != TRUE)
172                                 return FALSE;
173
174                 } else if (strcmp(args, DBUS_PARAM_TYPE_OBJECT_PATH) == 0) {
175                         dbus_message_iter_append_basic(&iter, DBUS_TYPE_OBJECT_PATH, &ch);
176                 } else {
177                         ERR("Error!!! Not supported data format[\"%s\"]", args);
178                         return FALSE;
179                 }
180
181                 count++;
182         }
183
184         return TRUE;
185 }
186
187 gboolean netconfig_dbus_get_basic_params_string(DBusMessage *message,
188                 char **key, int type, void *value)
189 {
190         DBusMessageIter iter, iter_variant;
191
192         dbus_message_iter_init(message, &iter);
193         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_STRING) {
194                 DBG("Argument type %d", dbus_message_iter_get_arg_type(&iter));
195                 return FALSE;
196         }
197
198         dbus_message_iter_get_basic(&iter, key);
199
200         if (value == NULL)
201                 return TRUE;
202
203         dbus_message_iter_next(&iter);
204         if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_VARIANT) {
205                 DBG("Argument type %d", dbus_message_iter_get_arg_type(&iter));
206                 return TRUE;
207         }
208
209         dbus_message_iter_recurse(&iter, &iter_variant);
210         if (dbus_message_iter_get_arg_type(&iter_variant) != type)
211                 return FALSE;
212
213         dbus_message_iter_get_basic(&iter_variant, value);
214
215         return TRUE;
216 }
217
218 gboolean netconfig_dbus_get_basic_params_array(DBusMessage *message,
219                 char **key, void **value)
220 {
221         DBusMessageIter args, dict, entry, variant;
222         int type = 0;
223
224         if (key == NULL)
225                 return FALSE;
226
227         /* read parameters */
228         if (dbus_message_iter_init(message, &args) == FALSE) {
229                 DBG("Message does not have parameters");
230                 return FALSE;
231         }
232
233         if (dbus_message_iter_get_arg_type(&args) != DBUS_TYPE_ARRAY) {
234                 DBG("Argument type %d", dbus_message_iter_get_arg_type(&args));
235                 return FALSE;
236         }
237
238         dbus_message_iter_recurse(&args, &dict);
239
240         if (dbus_message_iter_get_arg_type(&dict) != DBUS_TYPE_DICT_ENTRY) {
241                 DBG("Argument type %d", dbus_message_iter_get_arg_type(&dict));
242                 return FALSE;
243         }
244
245         dbus_message_iter_recurse(&dict, &entry);
246
247         if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_STRING) {
248                 DBG("Argument type %d", dbus_message_iter_get_arg_type(&entry));
249                 return FALSE;
250         }
251
252         dbus_message_iter_get_basic(&entry, key);
253
254         if (value == NULL)
255                 return TRUE;
256
257         dbus_message_iter_next(&entry);
258
259         if (dbus_message_iter_get_arg_type(&entry) != DBUS_TYPE_VARIANT) {
260                 DBG("Argument type %d", dbus_message_iter_get_arg_type(&entry));
261                 return TRUE;
262         }
263
264         dbus_message_iter_recurse(&entry, &variant);
265
266         type = dbus_message_iter_get_arg_type(&variant);
267         if (type == DBUS_TYPE_STRING)
268                 dbus_message_iter_get_basic(&variant, value);
269         else if (type == DBUS_TYPE_BYTE || type == DBUS_TYPE_BOOLEAN ||
270                         type == DBUS_TYPE_INT16 || type == DBUS_TYPE_UINT16 ||
271                         type == DBUS_TYPE_INT32 || type == DBUS_TYPE_UINT32 ||
272                         type == DBUS_TYPE_DOUBLE)
273                 dbus_message_iter_get_basic(&variant, *value);
274         else
275                 DBG("Argument type %d", type);
276
277         return TRUE;
278 }
279
280 gboolean netconfig_is_cellular_profile(const char *profile)
281 {
282         if (profile == NULL)
283                 return FALSE;
284
285         return g_str_has_prefix(profile, CONNMAN_CELLULAR_SERVICE_PROFILE_PREFIX);
286 }
287
288 gboolean netconfig_is_wifi_profile(const char *profile)
289 {
290         if (profile == NULL)
291                 return FALSE;
292
293         return g_str_has_prefix(profile, CONNMAN_WIFI_SERVICE_PROFILE_PREFIX);
294 }
295
296 gboolean netconfig_is_ethernet_profile(const char *profile)
297 {
298         if (profile == NULL)
299                 return FALSE;
300
301         return g_str_has_prefix(profile, CONNMAN_ETHERNET_SERVICE_PROFILE_PREFIX);
302 }
303
304 gboolean netconfig_is_bluetooth_profile(const char *profile)
305 {
306         if (profile == NULL)
307                 return FALSE;
308
309         return g_str_has_prefix(profile, CONNMAN_BLUETOOTH_SERVICE_PROFILE_PREFIX);
310 }
311
312 gboolean netconfig_invoke_dbus_method_nonblock(
313                 const char *dest, const char *path,
314                 const char *interface_name, const char *method, char *param_array[],
315                 DBusPendingCallNotifyFunction notify_func)
316 {
317         dbus_bool_t result;
318         DBusPendingCall *call;
319         DBusMessage *message = NULL;
320         DBusConnection *connection = NULL;
321
322         DBG("[DBUS Async] %s %s %s", interface_name, method, path);
323
324         connection = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
325         if (connection == NULL) {
326                 ERR("Failed to get system bus");
327
328                 return FALSE;
329         }
330
331         message = dbus_message_new_method_call(dest, path, interface_name, method);
332         if (message == NULL) {
333                 ERR("Failed DBus method call");
334
335                 dbus_connection_unref(connection);
336
337                 return FALSE;
338         }
339
340         if (__netconfig_dbus_append_param(message, param_array) == FALSE) {
341                 ERR("Failed to append DBus params");
342
343                 dbus_message_unref(message);
344                 dbus_connection_unref(connection);
345
346                 return FALSE;
347         }
348
349         result = dbus_connection_send_with_reply(connection, message, &call,
350                         NETCONFIG_DBUS_REPLY_TIMEOUT);
351
352         if (result != TRUE || call == NULL) {
353                 ERR("dbus_connection_send_with_reply() failed.");
354
355                 dbus_message_unref(message);
356                 dbus_connection_unref(connection);
357
358                 return FALSE;
359         }
360
361         if (notify_func == NULL)
362                 dbus_pending_call_cancel(call);
363         else
364                 dbus_pending_call_set_notify(call, notify_func, NULL, NULL);
365
366         dbus_message_unref(message);
367         dbus_connection_unref(connection);
368
369         return TRUE;
370 }
371
372 DBusMessage *netconfig_invoke_dbus_method(const char *dest, const char *path,
373                 const char *interface_name, const char *method, char *param_array[])
374 {
375         DBusError error;
376         DBusConnection *conn = NULL;
377         DBusMessage *reply = NULL;
378         DBusMessage *message = NULL;
379
380         DBG("[DBUS Sync] %s %s %s", interface_name, method, path);
381
382         conn = dbus_bus_get(DBUS_BUS_SYSTEM, NULL);
383         if (conn == NULL) {
384                 ERR("Failed to get system bus");
385
386                 return NULL;
387         }
388
389         message = dbus_message_new_method_call(dest, path, interface_name, method);
390         if (message == NULL) {
391                 ERR("Error!!! Failed to GetProperties");
392
393                 dbus_connection_unref(conn);
394
395                 return NULL;
396         }
397
398         if (__netconfig_dbus_append_param(message, param_array) == FALSE) {
399                 ERR("Error!!! __netconfig_dbus_append_param() failed");
400
401                 dbus_message_unref(message);
402                 dbus_connection_unref(conn);
403
404                 return NULL;
405         }
406
407         dbus_error_init(&error);
408
409         reply = dbus_connection_send_with_reply_and_block(conn, message,
410                         NETCONFIG_DBUS_REPLY_TIMEOUT, &error);
411
412         if (reply == NULL) {
413                 if (dbus_error_is_set(&error) == TRUE) {
414                         ERR("Error!!! dbus_connection_send_with_reply_and_block() failed. "
415                                         "DBus error [%s: %s]", error.name, error.message);
416
417                         dbus_error_free(&error);
418                 } else
419                         ERR("Error!!! Failed to get properties");
420
421                 dbus_message_unref(message);
422                 dbus_connection_unref(conn);
423
424                 return NULL;
425         }
426
427         dbus_message_unref(message);
428         dbus_connection_unref(conn);
429
430         return reply;
431 }
432
433 char *netconfig_wifi_get_connected_service_name(DBusMessage *message)
434 {
435         int is_connected = 0;
436         char *essid_name = NULL;
437         DBusMessageIter iter, array;
438
439         dbus_message_iter_init(message, &iter);
440         dbus_message_iter_recurse(&iter, &array);
441
442         while (dbus_message_iter_get_arg_type(&array) == DBUS_TYPE_DICT_ENTRY) {
443                 DBusMessageIter entry, string;
444                 const char *key = NULL;
445
446                 dbus_message_iter_recurse(&array, &entry);
447                 dbus_message_iter_get_basic(&entry, &key);
448
449                 if (g_str_equal(key, "State") == TRUE && is_connected == 0) {
450                         dbus_message_iter_next(&entry);
451                         dbus_message_iter_recurse(&entry, &string);
452
453                         if (dbus_message_iter_get_arg_type(&string) == DBUS_TYPE_STRING) {
454                                 dbus_message_iter_get_basic(&string, &key);
455
456                                 if (g_str_equal(key, "ready") == TRUE ||
457                                                 g_str_equal(key, "online") == TRUE)
458                                         is_connected = 1;
459                         }
460                 } else if (g_str_equal(key, "Name") == TRUE) {
461                         dbus_message_iter_next(&entry);
462                         dbus_message_iter_recurse(&entry, &string);
463
464                         if (dbus_message_iter_get_arg_type(&string) == DBUS_TYPE_STRING) {
465                                 dbus_message_iter_get_basic(&string, &key);
466
467                                 essid_name = (char *)g_strdup(key);
468                         }
469                 }
470
471                 dbus_message_iter_next(&array);
472         }
473
474         if (is_connected == 1 && essid_name != NULL)
475                 return essid_name;
476
477         if (essid_name != NULL)
478                 g_free(essid_name);
479
480         return NULL;
481 }
482
483 DBusGConnection *netconfig_setup_dbus(void)
484 {
485         DBusGConnection* connection = NULL;
486         GError *error = NULL;
487         DBusGProxy *proxy;
488         guint rv = 0;
489
490         connection = dbus_g_bus_get(DBUS_BUS_SYSTEM, &error);
491         if (connection == NULL) {
492                 ERR("Fail to get DBus(%s)", error->message);
493                 g_error_free(error);
494
495                 return connection;
496         }
497
498         INFO("Successfully get system DBus connection(%p)", connection);
499
500         proxy = dbus_g_proxy_new_for_name(connection, "org.freedesktop.DBus",
501                         "/org/freedesktop/DBus",
502                         "org.freedesktop.DBus");
503
504         if (!dbus_g_proxy_call(proxy, "RequestName", &error,
505                         G_TYPE_STRING, NETCONFIG_SERVICE, G_TYPE_UINT, 0,
506                         G_TYPE_INVALID, G_TYPE_UINT, &rv,
507                         G_TYPE_INVALID)) {
508                 ERR("Failed to acquire service(%s) error(%s)",
509                                 NETCONFIG_SERVICE, error->message);
510                 g_error_free(error);
511
512                 dbus_g_connection_unref(connection);
513
514                 return NULL;
515         }
516
517         if (rv != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
518                 ERR("Service name is already in use");
519
520                 dbus_g_connection_unref(connection);
521
522                 return NULL;
523         }
524
525         return connection;
526 }