add storage class specifier(static)
[platform/core/connectivity/stc-manager.git] / plugin / monitor / stcplugin-monitor-connection.c
1 /*
2  * Copyright (c) 2016 Samsung Electronics Co., Ltd.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include <vconf.h>
17 #include <openssl/sha.h>
18
19 #include "stc-gdbus.h"
20 #include "stc-firewall.h"
21 #include "stc-plugin-firewall.h"
22 #include "stcplugin-monitor.h"
23 #include "stcplugin-monitor-connection.h"
24
25 /* connman service dbus details */
26 #define CONNMAN_SERVICE                          "net.connman"
27 #define CONNMAN_PATH                             "/net/connman"
28
29 #define CONNMAN_MANAGER_PATH                     "/"
30 #define CONNMAN_MANAGER_INTERFACE                CONNMAN_SERVICE ".Manager"
31 #define CONNMAN_SERVICE_INTERFACE                CONNMAN_SERVICE ".Service"
32
33 #define CONNMAN_CELLULAR_SERVICE_PROFILE_PREFIX  CONNMAN_PATH "/service/cellular_"
34 #define CONNMAN_WIFI_SERVICE_PROFILE_PREFIX      CONNMAN_PATH "/service/wifi_"
35 #define CONNMAN_ETHERNET_SERVICE_PROFILE_PREFIX  CONNMAN_PATH "/service/ethernet_"
36 #define CONNMAN_BLUETOOTH_SERVICE_PROFILE_PREFIX CONNMAN_PATH "/service/bluetooth_"
37
38 #define CONNMAN_SIGNAL_PROPERTY_CHANGED          "PropertyChanged"
39
40 /* telephony service dbus details */
41 #define TELEPHONY_SERVICE                        "org.tizen.telephony"
42 #define TELEPHONY_DEFAULT_PATH                   "/org/tizen/telephony"
43
44 #define TELEPHONY_SERVICE_MANAGER                TELEPHONY_SERVICE".Manager"
45 #define TELEPHONY_SIM_INTERFACE                  TELEPHONY_SERVICE".Sim"
46
47 #define TELEPHONY_GET_MODEMS                     "GetModems"
48 #define TELEPHONY_GET_IMSI                       "GetIMSI"
49
50 #define SIM_SLOT_SINGLE 1
51
52 #define VCONF_TELEPHONY_DEFAULT_DATA_SERVICE     "db/telephony/dualsim/default_data_service"
53
54 static stc_connection_s *g_default_connection = NULL;
55 static GSList *g_connection_list = NULL;
56 static guint g_connection_sub_id = 0;
57
58 static void __conn_list_free(gpointer value)
59 {
60         stc_connection_s *conn = (stc_connection_s *)value;
61
62         FREE(conn->path);
63         FREE(conn->ifname);
64         FREE(conn->tether_iface.ifname);
65         FREE(conn);
66 }
67
68 static gint __conn_list_comp(gconstpointer a, gconstpointer b)
69 {
70         stc_connection_s *conn = (stc_connection_s *)a;
71         char *path = (char *)b;
72
73         if (g_strcmp0(conn->path, path) == 0)
74                 return 0;
75
76         return -1;
77 }
78
79 static void __update_monitor_by_conn(gpointer data, gpointer user_data)
80 {
81         stc_connection_s *conn = (stc_connection_s *)data;
82
83         stc_monitor_update_by_connection(conn);
84 }
85
86 static int __telephony_get_current_sim(void)
87 {
88         int sim_slot_count = 0;
89         int current_sim = 0;
90
91         if (vconf_get_int(VCONFKEY_TELEPHONY_SIM_SLOT_COUNT, &sim_slot_count) != 0) {
92                 STC_LOGD("failed to get sim slot count"); //LCOV_EXCL_LINE
93                 return -1; //LCOV_EXCL_LINE
94         }
95
96         if (sim_slot_count == SIM_SLOT_SINGLE) {
97                STC_LOGD("It's single sim model"); //LCOV_EXCL_LINE
98                return current_sim; //LCOV_EXCL_LINE
99         }
100
101         if (vconf_get_int(VCONF_TELEPHONY_DEFAULT_DATA_SERVICE, &current_sim) != 0) {
102                 STC_LOGD("failed to get default data service = %d\n", //LCOV_EXCL_LINE
103                          current_sim);
104                 return -1; //LCOV_EXCL_LINE
105         }
106
107         return current_sim;
108 }
109
110 static void __make_imsi_to_subscriber_id(stc_connection_s *conn, char *imsi)
111 {
112         int i = 0;
113         SHA256_CTX ctx;
114         unsigned char md[SHA256_DIGEST_LENGTH];
115
116         SHA256_Init(&ctx);
117         SHA256_Update(&ctx, imsi, strlen(imsi));
118         SHA256_Final(md, &ctx);
119
120         for (i = 0; i < SHA256_DIGEST_LENGTH; ++i)
121                 snprintf(conn->subscriber_id + (i * 2), 3, "%02x", md[i]);
122 }
123
124 static void __telephony_get_modem_subscriber_id(GDBusConnection *connection,
125                                 stc_connection_s *conn, const char *default_modem_name)
126 {
127         GVariant *message = NULL;
128         char tel_path[MAX_PATH_LENGTH];
129         char imsi[IMSI_LENGTH];
130         const char *plmn = NULL;
131         int plmn_len = 0;
132         const char *msin = NULL;
133         int msin_len = 0;
134
135         snprintf(tel_path, sizeof(tel_path), "%s/%s", TELEPHONY_DEFAULT_PATH,
136                  default_modem_name);
137         message = stc_manager_gdbus_call_sync(connection,
138                                               TELEPHONY_SERVICE,
139                                               tel_path,
140                                               TELEPHONY_SIM_INTERFACE,
141                                               TELEPHONY_GET_IMSI,
142                                               NULL);
143         if (message == NULL) {
144                 STC_LOGE("Failed to get services informations"); //LCOV_EXCL_LINE
145                 goto done; //LCOV_EXCL_LINE
146         }
147
148         DEBUG_PARAMS(message);
149         DEBUG_PARAM_TYPE(message);
150         g_variant_get(message, "(&s&s)", &plmn, &msin);
151         if (plmn)
152                 plmn_len = strlen(plmn);
153         if (msin)
154                 msin_len = strlen(msin);
155
156         if (msin_len + plmn_len >= IMSI_LENGTH) {
157                 STC_LOGD("Incorrect length of mobile subscriber identifier + net id"); //LCOV_EXCL_LINE
158                 goto done; //LCOV_EXCL_LINE
159         }
160
161         snprintf(imsi, IMSI_LENGTH, "%s%s", plmn, msin);
162         __make_imsi_to_subscriber_id(conn, imsi);
163
164 done:
165         g_variant_unref(message);
166         return;
167 }
168
169 static void __telephony_update_default_modem_subscriber_id(GDBusConnection *connection,
170                                 stc_connection_s *conn)
171 {
172         GVariant *message = NULL;
173         GVariantIter *iter = NULL;
174         gchar *default_modem_name = NULL;
175         gchar *modem_name = NULL;
176         int current_sim = __telephony_get_current_sim();
177
178         if (current_sim < 0) {
179                 STC_LOGI("Sim not found"); //LCOV_EXCL_LINE
180                 return; //LCOV_EXCL_LINE
181         }
182
183         message = stc_manager_gdbus_call_sync(connection,
184                                               TELEPHONY_SERVICE,
185                                               TELEPHONY_DEFAULT_PATH,
186                                               TELEPHONY_SERVICE_MANAGER,
187                                               TELEPHONY_GET_MODEMS,
188                                               NULL);
189         if (message == NULL) {
190                 STC_LOGE("Failed to get services informations"); //LCOV_EXCL_LINE
191                 return; //LCOV_EXCL_LINE
192         }
193
194         g_variant_get(message, "(as)", &iter);
195         DEBUG_PARAMS(message);
196         DEBUG_PARAM_TYPE(message);
197         while (g_variant_iter_loop(iter, "s", &modem_name)) {
198                 if (current_sim == 0) {
199                         default_modem_name = g_strdup(modem_name);
200                         FREE(modem_name);
201                         break;
202                 }
203                 current_sim--; //LCOV_EXCL_LINE
204         }
205
206         __telephony_get_modem_subscriber_id(connection, conn, default_modem_name);
207
208         FREE(default_modem_name);
209         g_variant_iter_free(iter);
210         g_variant_unref(message);
211         return;
212 }
213
214 static void __print_connection_info(stc_connection_s *conn, const char *state)
215 {
216         STC_LOGI("============= connection info ============");
217         STC_LOGI("path    [%s]", conn->path);
218         STC_LOGI("type    [%d]", conn->type);
219         STC_LOGI("ifname  [%s]", conn->ifname);
220         STC_LOGI("roaming [%u]", conn->roaming ? TRUE : FALSE);
221         if (conn->type == STC_IFACE_DATACALL)
222                 STC_LOGI("sub_id  [%s]", conn->subscriber_id);
223         STC_LOGI("state   [%s]", state);
224         STC_LOGI("==================================================");
225 }
226
227 static void __print_tether_connection_info(void)
228 {
229         STC_LOGI("============= tethering connection info ============");
230         STC_LOGI("mode    [%u]", g_default_connection->tether_state ? TRUE : FALSE);
231         STC_LOGI("type    [%d]", g_default_connection->tether_iface.type);
232         STC_LOGI("ifname  [%s]", g_default_connection->tether_iface.ifname);
233         STC_LOGI("====================================================");
234 }
235
236 static gboolean __is_cellular_internet_profile(const char *profile)
237 {
238         const char internet_suffix[] = "_1";
239
240         if (profile == NULL)
241                 return FALSE;
242
243         if (g_str_has_prefix(profile, CONNMAN_CELLULAR_SERVICE_PROFILE_PREFIX)
244             == TRUE) {
245                 char *suffix = strrchr(profile, '_');
246                 if (g_strcmp0(suffix, internet_suffix) == 0)
247                         return TRUE;
248         }
249
250         return FALSE;
251 }
252
253 static gboolean __is_cellular_profile(const char *profile)
254 {
255         if (profile == NULL)
256                 return FALSE;
257
258         return g_str_has_prefix(profile, //LCOV_EXCL_LINE
259                                 CONNMAN_CELLULAR_SERVICE_PROFILE_PREFIX);
260 }
261
262 static gboolean __is_wifi_profile(const char *profile)
263 {
264         if (profile == NULL)
265                 return FALSE;
266
267         return g_str_has_prefix(profile, //LCOV_EXCL_LINE
268                                 CONNMAN_WIFI_SERVICE_PROFILE_PREFIX);
269 }
270
271 static gboolean __is_ethernet_profile(const char *profile)
272 {
273         if (profile == NULL)
274                 return FALSE;
275
276         return g_str_has_prefix(profile, //LCOV_EXCL_LINE
277                                 CONNMAN_ETHERNET_SERVICE_PROFILE_PREFIX);
278 }
279
280 static gboolean __is_bluetooth_profile(const char *profile)
281 {
282         if (profile == NULL)
283                 return FALSE;
284
285         return g_str_has_prefix(profile, //LCOV_EXCL_LINE
286                                 CONNMAN_BLUETOOTH_SERVICE_PROFILE_PREFIX);
287 }
288
289 static gboolean __is_connected(GVariantIter *array)
290 {
291         gboolean is_connected = FALSE;
292         GVariant *variant = NULL;
293         gchar *key = NULL;
294
295         while (g_variant_iter_loop(array, "{sv}", &key, &variant)) {
296                 if (g_strcmp0(key, "State") != 0)
297                         continue;
298
299                 if (g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)) {
300                         const gchar *state = NULL;
301
302                         state = g_variant_get_string(variant, NULL);
303                         if (g_strcmp0(state, "ready") == 0 ||
304                             g_strcmp0(state, "online") == 0)
305                                 is_connected = TRUE;
306                 }
307
308                 g_free(key);
309                 g_variant_unref(variant);
310                 break;
311         }
312
313         return is_connected;
314 }
315
316 static void __get_connection_info(GDBusConnection *connection,
317                                 stc_connection_s *conn, const char *object_path)
318 {
319         GVariant *message = NULL;
320         GVariantIter *iter = NULL;
321         GVariant *variant = NULL;
322         gchar *key = NULL;
323
324         if (object_path == NULL) {
325                 STC_LOGI("Object path is NULL, so information not available.");
326                 return;
327         }
328
329         message = stc_manager_gdbus_call_sync(connection,
330                                               CONNMAN_SERVICE,
331                                               object_path,
332                                               CONNMAN_SERVICE_INTERFACE,
333                                               "GetProperties", NULL);
334         if (message == NULL) {
335                 STC_LOGE("Failed to get services informations"); //LCOV_EXCL_LINE
336                 goto done; //LCOV_EXCL_LINE
337         }
338
339         g_variant_get(message, "(a{sv})", &iter);
340         if (iter == NULL) {
341                 STC_LOGE("Profile %s doesn't exist", object_path); //LCOV_EXCL_LINE
342                 goto done; //LCOV_EXCL_LINE
343         }
344
345         while (g_variant_iter_loop(iter, "{sv}", &key, &variant)) {
346                 if (g_strcmp0(key, "Ethernet") == 0) {
347                         GVariantIter *iter1 = NULL;
348                         GVariant *variant1 = NULL;
349                         gchar *key1 = NULL;
350
351                         g_variant_get(variant, "a{sv}", &iter1);
352                         if (iter1 == NULL)
353                                 continue; //LCOV_EXCL_LINE
354
355                         while (g_variant_iter_loop(iter1, "{sv}", &key1,
356                                                    &variant1)) {
357                                 if (g_strcmp0(key1, "Interface") == 0) {
358                                         const gchar *value =
359                                                 g_variant_get_string(variant1,
360                                                                      NULL);
361                                         conn->ifname = g_strdup(value);
362                                 }
363                         }
364
365                         g_variant_iter_free(iter1);
366
367                 } else if (g_strcmp0(key, "Roaming") == 0) {
368                         gboolean roaming = 0;
369
370                         if (g_variant_is_of_type(variant,
371                                                  G_VARIANT_TYPE_BOOLEAN)) {
372                                 roaming = g_variant_get_boolean(variant);
373                                 conn->roaming = roaming;
374                         }
375                 }
376         }
377
378 done:
379         if (iter)
380                 g_variant_iter_free(iter);
381
382         if (message)
383                 g_variant_unref(message);
384
385         return;
386 }
387
388 static stc_error_e __get_connected_profiles(GDBusConnection *connection)
389 {
390         GVariant *message = NULL;
391         GVariantIter *iter = NULL;
392         GVariantIter *next;
393         gchar *object_path;
394         stc_connection_s *conn;
395         gboolean default_conn = TRUE;
396
397         message = stc_manager_gdbus_call_sync(connection,
398                                               CONNMAN_SERVICE,
399                                               CONNMAN_MANAGER_PATH,
400                                               CONNMAN_MANAGER_INTERFACE,
401                                               "GetServices", NULL);
402         if (message == NULL) {
403                 STC_LOGE("Failed to get profiles"); //LCOV_EXCL_LINE
404                 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
405         }
406
407         g_slist_free_full(g_connection_list, __conn_list_free);
408
409         g_variant_get(message, "(a(oa{sv}))", &iter);
410         while (g_variant_iter_loop(iter, "(oa{sv})", &object_path, &next)) {
411                 if (object_path == NULL)
412                         continue; //LCOV_EXCL_LINE
413
414                 if (__is_cellular_profile(object_path) &&
415                     !__is_cellular_internet_profile(object_path))
416                         continue;
417
418                 if (__is_connected(next) == TRUE) {
419                         conn = MALLOC0(stc_connection_s, 1);
420                         if (conn == NULL)
421                                 continue;
422
423                         conn->path = g_strdup(object_path);
424                         conn->roaming = FALSE;
425
426                         if (__is_cellular_profile(conn->path)) {
427                                 conn->type = STC_IFACE_DATACALL;
428                                 __telephony_update_default_modem_subscriber_id(connection, conn);
429                         } else if (__is_wifi_profile(conn->path)) {
430                                 conn->type = STC_IFACE_WIFI;
431                         } else if (__is_ethernet_profile(conn->path)) {
432                                 conn->type = STC_IFACE_WIRED;
433                         } else if (__is_bluetooth_profile(conn->path)) {
434                                 conn->type = STC_IFACE_BLUETOOTH;
435                         } else {
436                                 conn->type = STC_IFACE_UNKNOWN;
437                         }
438
439                         __get_connection_info(connection, conn, conn->path);
440                         __print_connection_info(conn, "connected");
441
442                         if (default_conn == TRUE) {
443                                 g_default_connection = conn;
444                                 default_conn = FALSE;
445                         }
446
447                         g_connection_list = g_slist_append(g_connection_list, conn);
448                 }
449         }
450
451         g_variant_iter_free(iter);
452         g_variant_unref(message);
453
454         g_slist_foreach(g_connection_list, __update_monitor_by_conn, NULL);
455         stc_plugin_firewall_update();
456
457         return STC_ERROR_NONE;
458 }
459
460 static stc_error_e __get_default_connection(GDBusConnection *connection)
461 {
462         GVariant *message = NULL;
463         GVariantIter *iter = NULL;
464         GVariantIter *next;
465         gchar *object_path;
466
467         message = stc_manager_gdbus_call_sync(connection,
468                                               CONNMAN_SERVICE,
469                                               CONNMAN_MANAGER_PATH,
470                                               CONNMAN_MANAGER_INTERFACE,
471                                               "GetServices", NULL);
472         if (message == NULL) {
473                 STC_LOGE("Failed to get profiles"); //LCOV_EXCL_LINE
474                 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
475         }
476
477         g_variant_get(message, "(a(oa{sv}))", &iter);
478         while (g_variant_iter_loop(iter, "(oa{sv})", &object_path, &next)) {
479                 if (object_path == NULL)
480                         continue; //LCOV_EXCL_LINE
481
482                 if (__is_cellular_profile(object_path) &&
483                     !__is_cellular_internet_profile(object_path))
484                         continue;
485
486                 if (__is_connected(next) == TRUE) {
487                         GSList *comp = g_slist_find_custom(g_connection_list,
488                                                                 object_path, __conn_list_comp);
489                         if (comp && comp->data)
490                                 g_default_connection = comp->data;
491
492                         g_free(object_path);
493                         g_variant_iter_free(next);
494                         break;
495                 }
496         }
497
498         g_variant_iter_free(iter);
499         g_variant_unref(message);
500
501         return STC_ERROR_NONE;
502 }
503
504 static void __append_connected_profile(GDBusConnection *connection,
505                                 const char *path)
506 {
507         stc_connection_s *conn;
508
509         conn = MALLOC0(stc_connection_s, 1);
510         if (conn == NULL)
511                 return;
512
513         conn->path = g_strdup(path);
514         conn->roaming = FALSE;
515
516         if (__is_cellular_profile(conn->path)) {
517                 conn->type = STC_IFACE_DATACALL;
518                 __telephony_update_default_modem_subscriber_id(connection, conn);
519         } else if (__is_wifi_profile(conn->path)) {
520                 conn->type = STC_IFACE_WIFI;
521         } else if (__is_ethernet_profile(conn->path)) {
522                 conn->type = STC_IFACE_WIRED;
523         } else if (__is_bluetooth_profile(conn->path)) {
524                 conn->type = STC_IFACE_BLUETOOTH;
525         } else {
526                 conn->type = STC_IFACE_UNKNOWN;
527         }
528
529         __get_connection_info(connection, conn, conn->path);
530         __print_connection_info(conn, "connected");
531
532         g_connection_list = g_slist_append(g_connection_list, conn);
533
534         stc_monitor_add_by_connection(conn);
535         stc_plugin_firewall_update();
536
537         __get_default_connection(connection);
538 }
539
540 static void __remove_disconnected_profile(GDBusConnection *connection,
541                                 stc_connection_s *conn)
542 {
543         __print_connection_info(conn, "disconnected");
544
545         stc_monitor_remove_by_connection(conn);
546
547         g_connection_list = g_slist_remove(g_connection_list, conn);
548
549         __get_default_connection(connection);
550
551         FREE(conn->path);
552         FREE(conn->ifname);
553         FREE(conn->tether_iface.ifname);
554         FREE(conn);
555 }
556
557 static void __vconf_key_callback(keynode_t *node, void *user_data)
558 {
559         int vconf_key;
560
561         if (node == NULL) {
562                 STC_LOGE("Invalid parameter");
563                 return;
564         }
565
566         if (g_default_connection == NULL)
567                 return;
568
569         if (vconf_keynode_get_type(node) != VCONF_TYPE_INT) {
570                 STC_LOGE("Invalid vconf key type");
571                 return;
572         }
573
574         vconf_key = vconf_keynode_get_int(node);
575
576         /* Check the tethering type */
577         switch (vconf_key) {
578         case VCONFKEY_MOBILE_HOTSPOT_MODE_USB:
579                 STC_LOGI("Hotspot mode USB type !");
580                 g_default_connection->tether_state = TRUE;
581                 g_default_connection->tether_iface.ifname = g_strdup(TETHERING_USB_IF);
582                 g_default_connection->tether_iface.type = STC_IFACE_USB;
583                 break;
584         case VCONFKEY_MOBILE_HOTSPOT_MODE_WIFI:
585                 STC_LOGI("Hotspot mode Wi-Fi type !");
586                 g_default_connection->tether_state = TRUE;
587                 g_default_connection->tether_iface.ifname = g_strdup(TETHERING_WIFI_IF);
588                 g_default_connection->tether_iface.type = STC_IFACE_WIFI;
589                 break;
590         case VCONFKEY_MOBILE_HOTSPOT_MODE_BT:
591                 STC_LOGI("Hotspot mode Bluetooth type !");
592                 g_default_connection->tether_state = TRUE;
593                 g_default_connection->tether_iface.ifname = g_strdup(TETHERING_BT_IF);
594                 g_default_connection->tether_iface.type = STC_IFACE_BLUETOOTH;
595                 break;
596         case VCONFKEY_MOBILE_HOTSPOT_MODE_P2P:
597                 STC_LOGI("Hotspot mode P2P type !");
598                 g_default_connection->tether_state = TRUE;
599                 g_default_connection->tether_iface.ifname = g_strdup(TETHERING_P2P_IF);
600                 g_default_connection->tether_iface.type = STC_IFACE_P2P;
601                 break;
602         case VCONFKEY_MOBILE_HOTSPOT_MODE_NONE:
603                 STC_LOGI("Hotspot mode none");
604                 g_default_connection->tether_state = FALSE;
605                 break;
606         default:
607                 STC_LOGE("Unknown Hotspot mode type !");
608                 break;
609         }
610
611         /* add monitoring for tethering if active found */
612         if (g_default_connection->tether_state == TRUE && g_default_connection->tether_iface.ifname) {
613                 __print_tether_connection_info();
614                 stc_monitor_update_by_connection(g_default_connection);
615                 stc_plugin_firewall_update();
616                 STC_LOGI("Data monitoring started for tethering iface !");
617                 return;
618         }
619
620         /* remove monitoring for tethering if in-active found */
621         if (g_default_connection->tether_state == FALSE && g_default_connection->tether_iface.ifname) {
622                 stc_monitor_update_by_connection(g_default_connection);
623                 g_free(g_default_connection->tether_iface.ifname);
624                 g_default_connection->tether_iface.ifname = NULL;
625                 g_default_connection->tether_iface.type = STC_IFACE_UNKNOWN;
626                 STC_LOGI("Data monitoring stopped for tethering iface !");
627                 return;
628         }
629 }
630
631 static void _service_signal_cb(GDBusConnection *connection,
632                                const gchar *name, const gchar *path,
633                                const gchar *interface, const gchar *sig,
634                                GVariant *param, gpointer user_data)
635 {
636         gchar *sigvalue = NULL;
637         GVariant *variant = NULL;
638         stc_s *stc = (stc_s *)stc_get_manager();
639         ret_msg_if(stc == NULL, "failed to get stc data");
640
641         if (path == NULL || param == NULL)
642                 goto done;
643
644         g_variant_get(param, "(sv)", &sigvalue, &variant);
645         if (sigvalue == NULL)
646                 goto done;
647
648         if (g_strcmp0(sig, CONNMAN_SIGNAL_PROPERTY_CHANGED) != 0)
649                 goto done;
650
651         if (g_strcmp0(sigvalue, "State") == 0 &&
652             g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)) {
653                 const gchar *state = NULL;
654
655                 state = g_variant_get_string(variant, NULL);
656                 if (g_strcmp0(state, "ready") == 0 ||
657                     g_strcmp0(state, "online") == 0) {
658                         GSList *comp = g_slist_find_custom(g_connection_list,
659                                                                 path, __conn_list_comp);
660                         if (!comp)
661                                 __append_connected_profile(stc->connection, path);
662                 } else if (g_strcmp0(state, "idle") == 0 ||
663                         g_strcmp0(state, "disconnect") == 0) {
664                         GSList *comp = g_slist_find_custom(g_connection_list,
665                                                                 path, __conn_list_comp);
666                         if (comp && comp->data)
667                                 __remove_disconnected_profile(stc->connection, comp->data);
668                 }
669         } else if (g_strcmp0(sigvalue, "Roaming") == 0) {
670                 //LCOV_EXCL_START
671                 GSList *comp = g_slist_find_custom(g_connection_list,
672                                                         path, __conn_list_comp);
673
674                 if (comp) {
675                         stc_connection_s *conn = comp->data;
676                         gboolean roaming = 0;
677
678                         if (g_variant_is_of_type(variant, G_VARIANT_TYPE_BOOLEAN)) {
679                                 roaming = g_variant_get_boolean(variant);
680                                 conn->roaming = roaming;
681                         }
682                 }
683                 //LCOV_EXCL_STOP
684         } else {
685                 ;//Do nothing
686         }
687 done:
688         if (sigvalue)
689                 g_free(sigvalue);
690
691         if (variant)
692                 g_variant_unref(variant);
693
694         return;
695 }
696
697 stc_error_e stc_plugin_monitor_connection_init(stc_s *stc)
698 {
699         int ret;
700         ret_value_msg_if(stc == NULL, STC_ERROR_INVALID_PARAMETER, "failed to get stc data");
701
702         __get_connected_profiles(stc->connection);
703         g_connection_sub_id =
704                 stc_manager_gdbus_subscribe_signal(stc->connection,
705                                                    CONNMAN_SERVICE,
706                                                    CONNMAN_SERVICE_INTERFACE,
707                                                    CONNMAN_SIGNAL_PROPERTY_CHANGED,
708                                                    NULL, NULL,
709                                                    G_DBUS_SIGNAL_FLAGS_NONE,
710                                                    _service_signal_cb,
711                                                    NULL, NULL);
712
713         ret = vconf_notify_key_changed(VCONFKEY_MOBILE_HOTSPOT_MODE, __vconf_key_callback, NULL);
714         if (ret < 0)
715                 STC_LOGE("vconf_notify_key_changed failed: %d", ret);
716
717         STC_LOGI("Successfully subscribed connman [%s] signal", CONNMAN_SIGNAL_PROPERTY_CHANGED);
718         return STC_ERROR_NONE;
719 }
720
721 stc_error_e stc_plugin_monitor_connection_deinit(stc_s *stc)
722 {
723         ret_value_msg_if(stc == NULL, STC_ERROR_INVALID_PARAMETER, "failed to get stc data");
724
725         stc_manager_gdbus_unsubscribe_signal(stc->connection,
726                                              g_connection_sub_id);
727
728         g_slist_free_full(g_connection_list, __conn_list_free);
729
730         return STC_ERROR_NONE;
731 }
732
733 GSList *stc_get_connection_list(void)
734 {
735         return g_connection_list;
736 }