Separate monitoring function plugin
[platform/core/connectivity/stc-manager.git] / plugin / monitor / stc-plugin-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
17 #include <vconf/vconf.h>
18 #include <openssl/sha.h>
19
20 #include "stc-firewall.h"
21 #include "stc-manager-gdbus.h"
22 #include "stc-plugin-monitor.h"
23 #include "stc-plugin-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 stc_connection_s *g_default_connection = NULL;
55 GSList *g_connection_list = NULL;
56 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)
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("==================================================");
224 }
225
226 static void __print_tether_connection_info(void)
227 {
228         STC_LOGI("============= tethering connection info ============");
229         STC_LOGI("mode    [%u]", g_default_connection->tether_state ? TRUE : FALSE);
230         STC_LOGI("type    [%d]", g_default_connection->tether_iface.type);
231         STC_LOGI("ifname  [%s]", g_default_connection->tether_iface.ifname);
232         STC_LOGI("====================================================");
233 }
234
235 static gboolean __is_cellular_internet_profile(const char *profile)
236 {
237         const char internet_suffix[] = "_1";
238
239         if (profile == NULL)
240                 return FALSE;
241
242         if (g_str_has_prefix(profile, CONNMAN_CELLULAR_SERVICE_PROFILE_PREFIX)
243             == TRUE) {
244                 char *suffix = strrchr(profile, '_');
245                 if (g_strcmp0(suffix, internet_suffix) == 0)
246                         return TRUE;
247         }
248
249         return FALSE;
250 }
251
252 static gboolean __is_cellular_profile(const char *profile)
253 {
254         if (profile == NULL)
255                 return FALSE;
256
257         return g_str_has_prefix(profile, //LCOV_EXCL_LINE
258                                 CONNMAN_CELLULAR_SERVICE_PROFILE_PREFIX);
259 }
260
261 static gboolean __is_wifi_profile(const char *profile)
262 {
263         if (profile == NULL)
264                 return FALSE;
265
266         return g_str_has_prefix(profile, //LCOV_EXCL_LINE
267                                 CONNMAN_WIFI_SERVICE_PROFILE_PREFIX);
268 }
269
270 static gboolean __is_ethernet_profile(const char *profile)
271 {
272         if (profile == NULL)
273                 return FALSE;
274
275         return g_str_has_prefix(profile, //LCOV_EXCL_LINE
276                                 CONNMAN_ETHERNET_SERVICE_PROFILE_PREFIX);
277 }
278
279 static gboolean __is_bluetooth_profile(const char *profile)
280 {
281         if (profile == NULL)
282                 return FALSE;
283
284         return g_str_has_prefix(profile, //LCOV_EXCL_LINE
285                                 CONNMAN_BLUETOOTH_SERVICE_PROFILE_PREFIX);
286 }
287
288 static gboolean __is_connected(GVariantIter *array)
289 {
290         gboolean is_connected = FALSE;
291         GVariant *variant = NULL;
292         gchar *key = NULL;
293
294         while (g_variant_iter_loop(array, "{sv}", &key, &variant)) {
295                 if (g_strcmp0(key, "State") != 0)
296                         continue;
297
298                 if (g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)) {
299                         const gchar *state = NULL;
300
301                         state = g_variant_get_string(variant, NULL);
302                         if (g_strcmp0(state, "ready") == 0 ||
303                             g_strcmp0(state, "online") == 0)
304                                 is_connected = TRUE;
305                 }
306
307                 g_free(key);
308                 g_variant_unref(variant);
309                 break;
310         }
311
312         return is_connected;
313 }
314
315 static void __get_connection_info(GDBusConnection *connection,
316                                 stc_connection_s *conn, const char *object_path)
317 {
318         GVariant *message = NULL;
319         GVariantIter *iter = NULL;
320         GVariant *variant = NULL;
321         gchar *key = NULL;
322
323         if (object_path == NULL) {
324                 STC_LOGI("Object path is NULL, so information not available.");
325                 return;
326         }
327
328         message = stc_manager_gdbus_call_sync(connection,
329                                               CONNMAN_SERVICE,
330                                               object_path,
331                                               CONNMAN_SERVICE_INTERFACE,
332                                               "GetProperties", NULL);
333         if (message == NULL) {
334                 STC_LOGE("Failed to get services informations"); //LCOV_EXCL_LINE
335                 goto done; //LCOV_EXCL_LINE
336         }
337
338         g_variant_get(message, "(a{sv})", &iter);
339         if (iter == NULL) {
340                 STC_LOGE("Profile %s doesn't exist", object_path); //LCOV_EXCL_LINE
341                 goto done; //LCOV_EXCL_LINE
342         }
343
344         while (g_variant_iter_loop(iter, "{sv}", &key, &variant)) {
345                 if (g_strcmp0(key, "Ethernet") == 0) {
346                         GVariantIter *iter1 = NULL;
347                         GVariant *variant1 = NULL;
348                         gchar *key1 = NULL;
349
350                         g_variant_get(variant, "a{sv}", &iter1);
351                         if (iter1 == NULL)
352                                 continue; //LCOV_EXCL_LINE
353
354                         while (g_variant_iter_loop(iter1, "{sv}", &key1,
355                                                    &variant1)) {
356                                 if (g_strcmp0(key1, "Interface") == 0) {
357                                         const gchar *value =
358                                                 g_variant_get_string(variant1,
359                                                                      NULL);
360                                         conn->ifname = g_strdup(value);
361                                 }
362                         }
363
364                         g_variant_iter_free(iter1);
365
366                 } else if (g_strcmp0(key, "Roaming") == 0) {
367                         gboolean roaming = 0;
368
369                         if (g_variant_is_of_type(variant,
370                                                  G_VARIANT_TYPE_BOOLEAN)) {
371                                 roaming = g_variant_get_boolean(variant);
372                                 conn->roaming = roaming;
373                         }
374                 }
375         }
376
377 done:
378         if (iter)
379                 g_variant_iter_free(iter);
380
381         if (message)
382                 g_variant_unref(message);
383
384         return;
385 }
386
387 static stc_error_e __get_connected_profiles(GDBusConnection *connection)
388 {
389         GVariant *message = NULL;
390         GVariantIter *iter = NULL;
391         GVariantIter *next;
392         gchar *object_path;
393         stc_connection_s *conn;
394         gboolean default_conn = TRUE;
395
396         message = stc_manager_gdbus_call_sync(connection,
397                                               CONNMAN_SERVICE,
398                                               CONNMAN_MANAGER_PATH,
399                                               CONNMAN_MANAGER_INTERFACE,
400                                               "GetServices", NULL);
401         if (message == NULL) {
402                 STC_LOGE("Failed to get profiles"); //LCOV_EXCL_LINE
403                 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
404         }
405
406         g_slist_free_full(g_connection_list, __conn_list_free);
407
408         g_variant_get(message, "(a(oa{sv}))", &iter);
409         while (g_variant_iter_loop(iter, "(oa{sv})", &object_path, &next)) {
410                 if (object_path == NULL)
411                         continue; //LCOV_EXCL_LINE
412
413                 if (__is_cellular_profile(object_path) &&
414                     !__is_cellular_internet_profile(object_path))
415                         continue;
416
417                 if (__is_connected(next) == TRUE) {
418                         conn = MALLOC0(stc_connection_s, 1);
419                         if (conn == NULL)
420                                 continue;
421
422                         conn->path = g_strdup(object_path);
423                         conn->roaming = FALSE;
424
425                         if (__is_cellular_profile(conn->path)) {
426                                 conn->type = STC_IFACE_DATACALL;
427                                 __telephony_update_default_modem_subscriber_id(connection, conn);
428                         } else if (__is_wifi_profile(conn->path)) {
429                                 conn->type = STC_IFACE_WIFI;
430                         } else if (__is_ethernet_profile(conn->path)) {
431                                 conn->type = STC_IFACE_WIRED;
432                         } else if (__is_bluetooth_profile(conn->path)) {
433                                 conn->type = STC_IFACE_BLUETOOTH;
434                         } else {
435                                 conn->type = STC_IFACE_UNKNOWN;
436                         }
437
438                         __get_connection_info(connection, conn, conn->path);
439                         __print_connection_info(conn);
440
441                         if (default_conn == TRUE) {
442                                 g_default_connection = conn;
443                                 default_conn = FALSE;
444                         }
445
446                         g_connection_list = g_slist_append(g_connection_list, conn);
447
448                         g_free(object_path);
449                         g_variant_iter_free(next);
450                         continue;
451                 }
452         }
453
454         g_variant_iter_free(iter);
455         g_variant_unref(message);
456
457         g_slist_foreach(g_connection_list, __update_monitor_by_conn, NULL);
458         stc_firewall_update();
459
460         return STC_ERROR_NONE;
461 }
462
463 static stc_error_e __get_default_connection(GDBusConnection *connection)
464 {
465         GVariant *message = NULL;
466         GVariantIter *iter = NULL;
467         GVariantIter *next;
468         gchar *object_path;
469
470         message = stc_manager_gdbus_call_sync(connection,
471                                               CONNMAN_SERVICE,
472                                               CONNMAN_MANAGER_PATH,
473                                               CONNMAN_MANAGER_INTERFACE,
474                                               "GetServices", NULL);
475         if (message == NULL) {
476                 STC_LOGE("Failed to get profiles"); //LCOV_EXCL_LINE
477                 return STC_ERROR_FAIL; //LCOV_EXCL_LINE
478         }
479
480         g_variant_get(message, "(a(oa{sv}))", &iter);
481         while (g_variant_iter_loop(iter, "(oa{sv})", &object_path, &next)) {
482                 if (object_path == NULL)
483                         continue; //LCOV_EXCL_LINE
484
485                 if (__is_cellular_profile(object_path) &&
486                     !__is_cellular_internet_profile(object_path))
487                         continue;
488
489                 if (__is_connected(next) == TRUE) {
490                         GSList *comp = g_slist_find_custom(g_connection_list,
491                                                                 object_path, __conn_list_comp);
492                         if (comp && comp->data)
493                                 g_default_connection = comp->data;
494
495                         break;
496                 }
497         }
498
499         g_variant_iter_free(iter);
500         g_variant_unref(message);
501
502         return STC_ERROR_NONE;
503 }
504
505 static void __append_connected_profile(GDBusConnection *connection,
506                                 const char *path)
507 {
508         stc_connection_s *conn;
509
510         conn = MALLOC0(stc_connection_s, 1);
511         if (conn == NULL)
512                 return;
513
514         conn->path = g_strdup(path);
515         conn->roaming = FALSE;
516
517         if (__is_cellular_profile(conn->path)) {
518                 conn->type = STC_IFACE_DATACALL;
519                 __telephony_update_default_modem_subscriber_id(connection, conn);
520         } else if (__is_wifi_profile(conn->path)) {
521                 conn->type = STC_IFACE_WIFI;
522         } else if (__is_ethernet_profile(conn->path)) {
523                 conn->type = STC_IFACE_WIRED;
524         } else if (__is_bluetooth_profile(conn->path)) {
525                 conn->type = STC_IFACE_BLUETOOTH;
526         } else {
527                 conn->type = STC_IFACE_UNKNOWN;
528         }
529
530         __get_connection_info(connection, conn, conn->path);
531         __print_connection_info(conn);
532
533         g_connection_list = g_slist_append(g_connection_list, conn);
534
535         stc_monitor_add_by_connection(conn);
536         stc_firewall_update();
537
538         __get_default_connection(connection);
539 }
540
541 static void __remove_disconnected_profile(GDBusConnection *connection,
542                                 stc_connection_s *conn)
543 {
544         __print_connection_info(conn);
545
546         stc_monitor_remove_by_connection(conn);
547
548         g_connection_list = g_slist_remove(g_connection_list, conn);
549
550         __get_default_connection(connection);
551
552         FREE(conn->path);
553         FREE(conn->ifname);
554         FREE(conn->tether_iface.ifname);
555         FREE(conn);
556 }
557
558 static void __vconf_key_callback(keynode_t *node, void *user_data)
559 {
560         int vconf_key;
561
562         if (node == NULL) {
563                 STC_LOGE("Invalid parameter");
564                 return;
565         }
566
567         if (g_default_connection == NULL)
568                 return;
569
570         if (vconf_keynode_get_type(node) != VCONF_TYPE_INT) {
571                 STC_LOGE("Invalid vconf key type");
572                 return;
573         }
574
575         vconf_key = vconf_keynode_get_int(node);
576
577         /* Check the tethering type */
578         switch (vconf_key) {
579         case VCONFKEY_MOBILE_HOTSPOT_MODE_USB:
580                 STC_LOGI("Hotspot mode USB type !");
581                 g_default_connection->tether_state = TRUE;
582                 g_default_connection->tether_iface.ifname = g_strdup(TETHERING_USB_IF);
583                 g_default_connection->tether_iface.type = STC_IFACE_USB;
584                 break;
585         case VCONFKEY_MOBILE_HOTSPOT_MODE_WIFI:
586                 STC_LOGI("Hotspot mode Wi-Fi type !");
587                 g_default_connection->tether_state = TRUE;
588                 g_default_connection->tether_iface.ifname = g_strdup(TETHERING_WIFI_IF);
589                 g_default_connection->tether_iface.type = STC_IFACE_WIFI;
590                 break;
591         case VCONFKEY_MOBILE_HOTSPOT_MODE_BT:
592                 STC_LOGI("Hotspot mode Bluetooth type !");
593                 g_default_connection->tether_state = TRUE;
594                 g_default_connection->tether_iface.ifname = g_strdup(TETHERING_BT_IF);
595                 g_default_connection->tether_iface.type = STC_IFACE_BLUETOOTH;
596                 break;
597         case VCONFKEY_MOBILE_HOTSPOT_MODE_P2P:
598                 STC_LOGI("Hotspot mode P2P type !");
599                 g_default_connection->tether_state = TRUE;
600                 g_default_connection->tether_iface.ifname = g_strdup(TETHERING_P2P_IF);
601                 g_default_connection->tether_iface.type = STC_IFACE_P2P;
602                 break;
603         case VCONFKEY_MOBILE_HOTSPOT_MODE_NONE:
604                 STC_LOGI("Hotspot mode none");
605                 g_default_connection->tether_state = FALSE;
606                 break;
607         default:
608                 STC_LOGE("Unknown Hotspot mode type !");
609                 break;
610         }
611
612         /* add monitoring for tethering if active found */
613         if (g_default_connection->tether_state == TRUE && g_default_connection->tether_iface.ifname) {
614                 __print_tether_connection_info();
615                 stc_monitor_update_by_connection(&g_default_connection);
616                 stc_firewall_update();
617                 STC_LOGI("Data monitoring started for tethering iface !");
618                 return;
619         }
620
621         /* remove monitoring for tethering if in-active found */
622         if (g_default_connection->tether_state == FALSE && g_default_connection->tether_iface.ifname) {
623                 stc_monitor_update_by_connection(&g_default_connection);
624                 g_free(g_default_connection->tether_iface.ifname);
625                 g_default_connection->tether_iface.ifname = NULL;
626                 g_default_connection->tether_iface.type = STC_IFACE_UNKNOWN;
627                 STC_LOGI("Data monitoring stopped for tethering iface !");
628                 return;
629         }
630 }
631
632 static void _service_signal_cb(GDBusConnection *connection,
633                                const gchar *name, const gchar *path,
634                                const gchar *interface, const gchar *sig,
635                                GVariant *param, gpointer user_data)
636 {
637         gchar *sigvalue = NULL;
638         GVariant *variant = NULL;
639         stc_s *stc = (stc_s *)stc_get_manager();
640         ret_msg_if(stc == NULL, "failed to get stc data");
641
642         if (path == NULL || param == NULL)
643                 goto done;
644
645         g_variant_get(param, "(sv)", &sigvalue, &variant);
646         if (sigvalue == NULL)
647                 goto done;
648
649         if (g_strcmp0(sig, CONNMAN_SIGNAL_PROPERTY_CHANGED) != 0)
650                 goto done;
651
652         if (g_strcmp0(sigvalue, "State") == 0 &&
653             g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)) {
654                 const gchar *state = NULL;
655
656                 state = g_variant_get_string(variant, NULL);
657                 if (g_strcmp0(state, "ready") == 0 ||
658                     g_strcmp0(state, "online") == 0) {
659                         GSList *comp = g_slist_find_custom(g_connection_list,
660                                                                 path, __conn_list_comp);
661                         if (!comp)
662                                 __append_connected_profile(stc->connection, path);
663                 } else if (g_strcmp0(state, "idle") == 0 ||
664                         g_strcmp0(state, "disconnect") == 0) {
665                         GSList *comp = g_slist_find_custom(g_connection_list,
666                                                                 path, __conn_list_comp);
667                         if (comp && comp->data)
668                                 __remove_disconnected_profile(stc->connection, comp->data);
669                 }
670         } else if (g_strcmp0(sigvalue, "Roaming") == 0) {
671                 //LCOV_EXCL_START
672                 GSList *comp = g_slist_find_custom(g_connection_list,
673                                                         path, __conn_list_comp);
674
675                 if (comp) {
676                         stc_connection_s *conn = comp->data;
677                         gboolean roaming = 0;
678
679                         if (g_variant_is_of_type(variant, G_VARIANT_TYPE_BOOLEAN)) {
680                                 roaming = g_variant_get_boolean(variant);
681                                 conn->roaming = roaming;
682                         }
683                 }
684                 //LCOV_EXCL_STOP
685         } else {
686                 ;//Do nothing
687         }
688 done:
689         if (sigvalue)
690                 g_free(sigvalue);
691
692         if (variant)
693                 g_variant_unref(variant);
694
695         return;
696 }
697
698 stc_error_e stc_plugin_monitor_connection_init(stc_s *stc)
699 {
700         int ret;
701         ret_value_msg_if(stc == NULL, STC_ERROR_INVALID_PARAMETER, "failed to get stc data");
702
703         __get_connected_profiles(stc->connection);
704         g_connection_sub_id =
705                 stc_manager_gdbus_subscribe_signal(stc->connection,
706                                                    CONNMAN_SERVICE,
707                                                    CONNMAN_SERVICE_INTERFACE,
708                                                    CONNMAN_SIGNAL_PROPERTY_CHANGED,
709                                                    NULL, NULL,
710                                                    G_DBUS_SIGNAL_FLAGS_NONE,
711                                                    _service_signal_cb,
712                                                    NULL, NULL);
713
714         ret = vconf_notify_key_changed(VCONFKEY_MOBILE_HOTSPOT_MODE, __vconf_key_callback, NULL);
715         if (ret < 0)
716                 STC_LOGE("vconf_notify_key_changed failed: %d", ret);
717
718         STC_LOGI("Successfully subscribed connman [%s] signal", CONNMAN_SIGNAL_PROPERTY_CHANGED);
719         return STC_ERROR_NONE;
720 }
721
722 stc_error_e stc_plugin_monitor_connection_deinit(stc_s *stc)
723 {
724         ret_value_msg_if(stc == NULL, STC_ERROR_INVALID_PARAMETER, "failed to get stc data");
725
726         stc_manager_gdbus_unsubscribe_signal(stc->connection,
727                                              g_connection_sub_id);
728
729         g_slist_free_full(g_connection_list, __conn_list_free);
730
731         return STC_ERROR_NONE;
732 }
733
734 GSList *stc_get_connection_list(void)
735 {
736         return g_connection_list;
737 }