Initialize smart traffic control manager package
[platform/core/connectivity/stc-manager.git] / src / monitor / stc-default-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 "stc-monitor.h"
18 #include "stc-default-connection.h"
19
20 #define CONNMAN_SERVICE                          "net.connman"
21 #define CONNMAN_PATH                             "/net/connman"
22
23 #define CONNMAN_MANAGER_PATH                     "/"
24 #define CONNMAN_MANAGER_INTERFACE                CONNMAN_SERVICE ".Manager"
25 #define CONNMAN_SERVICE_INTERFACE                CONNMAN_SERVICE ".Service"
26
27 #define CONNMAN_CELLULAR_SERVICE_PROFILE_PREFIX  CONNMAN_PATH "/service/cellular_"
28 #define CONNMAN_WIFI_SERVICE_PROFILE_PREFIX      CONNMAN_PATH "/service/wifi_"
29 #define CONNMAN_ETHERNET_SERVICE_PROFILE_PREFIX  CONNMAN_PATH "/service/ethernet_"
30 #define CONNMAN_BLUETOOTH_SERVICE_PROFILE_PREFIX CONNMAN_PATH "/service/bluetooth_"
31
32 #define CONNMAN_SIGNAL_PROPERTY_CHANGED          "PropertyChanged"
33
34 default_connection_s g_default_connection;
35 guint g_default_connection_sub_id = 0;
36
37 static void __print_default_connection_info(void)
38 {
39         STC_LOGI("============= default connection info ============");
40         STC_LOGI("path    [%s]", g_default_connection.path);
41         STC_LOGI("type    [%d]", g_default_connection.type);
42         STC_LOGI("ifname  [%s]", g_default_connection.ifname);
43         STC_LOGI("roaming [%u]", g_default_connection.roaming ? TRUE : FALSE);
44         STC_LOGI("==================================================");
45 }
46
47 static void __reset_default_connection_data(void)
48 {
49         FREE(g_default_connection.path);
50         FREE(g_default_connection.ifname);
51         g_default_connection.type = STC_IFACE_UNKNOWN;
52         g_default_connection.roaming = FALSE;
53 }
54
55 static gboolean __is_cellular_internet_profile(const char *profile)
56 {
57         const char internet_suffix[] = "_1";
58
59         if (profile == NULL)
60                 return FALSE;
61
62         if (g_str_has_prefix(profile, CONNMAN_CELLULAR_SERVICE_PROFILE_PREFIX)
63             == TRUE) {
64                 char *suffix = strrchr(profile, '_');
65                 if (g_strcmp0(suffix, internet_suffix) == 0)
66                         return TRUE;
67         }
68
69         return FALSE;
70 }
71
72 static gboolean __is_cellular_profile(const char *profile)
73 {
74         if (profile == NULL)
75                 return FALSE;
76
77         return g_str_has_prefix(profile,
78                                 CONNMAN_CELLULAR_SERVICE_PROFILE_PREFIX);
79 }
80
81 static gboolean __is_wifi_profile(const char *profile)
82 {
83         if (profile == NULL)
84                 return FALSE;
85
86         return g_str_has_prefix(profile, CONNMAN_WIFI_SERVICE_PROFILE_PREFIX);
87 }
88
89 static gboolean __is_ethernet_profile(const char *profile)
90 {
91         if (profile == NULL)
92                 return FALSE;
93
94         return g_str_has_prefix(profile,
95                                 CONNMAN_ETHERNET_SERVICE_PROFILE_PREFIX);
96 }
97
98 static gboolean __is_bluetooth_profile(const char *profile)
99 {
100         if (profile == NULL)
101                 return FALSE;
102
103         return g_str_has_prefix(profile,
104                                 CONNMAN_BLUETOOTH_SERVICE_PROFILE_PREFIX);
105 }
106
107 static gboolean __is_connected(GVariantIter *array)
108 {
109         gboolean is_connected = FALSE;
110         GVariant *variant = NULL;
111         gchar *key = NULL;
112
113         while (g_variant_iter_loop(array, "{sv}", &key, &variant)) {
114                 if (g_strcmp0(key, "State") != 0)
115                         continue;
116
117                 if (g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)) {
118                         const gchar *state = NULL;
119
120                         state = g_variant_get_string(variant, NULL);
121                         if (g_strcmp0(state, "ready") == 0 ||
122                             g_strcmp0(state, "online") == 0)
123                                 is_connected = TRUE;
124                 }
125
126                 g_free(key);
127                 g_variant_unref(variant);
128                 break;
129         }
130
131         return is_connected;
132 }
133
134 static void __get_default_connection_info(GDBusConnection *connection,
135                                           const char *object_path)
136 {
137         GVariant *message = NULL;
138         GVariantIter *iter = NULL;
139         GVariant *variant = NULL;
140         gchar *key = NULL;
141
142         if (object_path == NULL) {
143                 STC_LOGE("Object path is NULL");
144                 return;
145         }
146
147         message = stc_manager_gdbus_call_sync(connection,
148                                               CONNMAN_SERVICE,
149                                               object_path,
150                                               CONNMAN_SERVICE_INTERFACE,
151                                               "GetProperties", NULL);
152         if (message == NULL) {
153                 STC_LOGE("Failed to get services informations");
154                 goto done;
155         }
156
157         g_variant_get(message, "(a{sv})", &iter);
158         if (iter == NULL) {
159                 STC_LOGE("Profile %s doesn't exist", object_path);
160                 goto done;
161         }
162
163         while (g_variant_iter_loop(iter, "{sv}", &key, &variant)) {
164                 if (g_strcmp0(key, "Ethernet") == 0) {
165                         GVariantIter *iter1 = NULL;
166                         GVariant *variant1 = NULL;
167                         gchar *key1 = NULL;
168
169                         g_variant_get(variant, "a{sv}", &iter1);
170                         if (iter1 == NULL)
171                                 continue;
172
173                         while (g_variant_iter_loop(iter1, "{sv}", &key1,
174                                                    &variant1)) {
175                                 if (g_strcmp0(key1, "Interface") == 0) {
176                                         const gchar *value =
177                                                 g_variant_get_string(variant1,
178                                                                      NULL);
179                                         g_default_connection.ifname =
180                                                 g_strdup(value);
181                                 }
182                         }
183
184                         g_variant_iter_free(iter1);
185
186                 } else if (g_strcmp0(key, "Roaming") == 0) {
187                         gboolean roaming = 0;
188
189                         if (g_variant_is_of_type(variant,
190                                                  G_VARIANT_TYPE_BOOLEAN)) {
191                                 roaming = g_variant_get_boolean(variant);
192                                 g_default_connection.roaming = roaming;
193                         }
194                 }
195         }
196
197 done:
198         if (iter)
199                 g_variant_iter_free(iter);
200
201         if (message)
202                 g_variant_unref(message);
203
204         return;
205 }
206
207 static stc_error_e __get_default_profile(GDBusConnection *connection)
208 {
209         GVariant *message = NULL;
210         GVariantIter *iter = NULL;
211         GVariantIter *next;
212         gchar *object_path;
213
214         message = stc_manager_gdbus_call_sync(connection,
215                                               CONNMAN_SERVICE,
216                                               CONNMAN_MANAGER_PATH,
217                                               CONNMAN_MANAGER_INTERFACE,
218                                               "GetServices", NULL);
219         if (message == NULL) {
220                 STC_LOGE("Failed to get profiles");
221                 return STC_ERROR_FAIL;
222         }
223
224         g_variant_get(message, "(a(oa{sv}))", &iter);
225         while (g_variant_iter_loop(iter, "(oa{sv})", &object_path, &next)) {
226                 if (object_path == NULL)
227                         continue;
228
229                 if (__is_cellular_profile(object_path) &&
230                     !__is_cellular_internet_profile(object_path))
231                         continue;
232
233                 if (__is_connected(next) == TRUE) {
234                         /* reset old default connection data */
235                         FREE(g_default_connection.path);
236                         FREE(g_default_connection.ifname);
237                         g_default_connection.type = STC_IFACE_UNKNOWN;
238                         g_default_connection.roaming = FALSE;
239
240                         g_default_connection.path = g_strdup(object_path);
241                         g_free(object_path);
242                         g_variant_iter_free(next);
243                         break;
244                 }
245         }
246
247         g_variant_iter_free(iter);
248         g_variant_unref(message);
249
250         if (__is_cellular_profile(g_default_connection.path))
251                 g_default_connection.type = STC_IFACE_DATACALL;
252         else if (__is_wifi_profile(g_default_connection.path))
253                 g_default_connection.type = STC_IFACE_WIFI;
254         else if (__is_ethernet_profile(g_default_connection.path))
255                 g_default_connection.type = STC_IFACE_WIRED;
256         else if (__is_bluetooth_profile(g_default_connection.path))
257                 g_default_connection.type = STC_IFACE_BLUETOOTH;
258         else
259                 g_default_connection.type = STC_IFACE_UNKNOWN;
260
261         __get_default_connection_info(connection, g_default_connection.path);
262
263         __print_default_connection_info();
264
265         stc_monitor_update_rstn_by_default_connection(&g_default_connection);
266
267         return STC_ERROR_NONE;
268 }
269
270 static void _service_signal_cb(GDBusConnection *conn,
271                                const gchar *name, const gchar *path,
272                                const gchar *interface, const gchar *sig,
273                                GVariant *param, gpointer user_data)
274 {
275         gchar *sigvalue = NULL;
276         GVariant *variant = NULL;
277         stc_s *stc = (stc_s *)stc_get_manager();
278         ret_msg_if(stc == NULL, "failed to get stc data");
279
280         if (path == NULL || param == NULL)
281                 goto done;
282
283         g_variant_get(param, "(sv)", &sigvalue, &variant);
284         if (sigvalue == NULL)
285                 goto done;
286
287         if (g_strcmp0(sig, CONNMAN_SIGNAL_PROPERTY_CHANGED) != 0)
288                 goto done;
289
290         if (g_strcmp0(sigvalue, "State") == 0 &&
291             g_variant_is_of_type(variant, G_VARIANT_TYPE_STRING)) {
292                 const gchar *state = NULL;
293
294                 state = g_variant_get_string(variant, NULL);
295                 if (g_strcmp0(state, "ready") == 0 ||
296                     g_strcmp0(state, "online") == 0) {
297                         if (g_strcmp0(g_default_connection.path, path)) {
298                                 __reset_default_connection_data();
299                                 __get_default_profile(stc->connection);
300                         }
301                 } else {
302                         if (g_strcmp0(g_default_connection.path, path) == 0) {
303                                 __reset_default_connection_data();
304                                 __get_default_profile(stc->connection);
305                         }
306                 }
307         } else if (g_strcmp0(sigvalue, "Roaming") == 0) {
308                 if (g_strcmp0(g_default_connection.path, path) == 0) {
309                         gboolean roaming = 0;
310
311                         if (g_variant_is_of_type(variant,
312                                                  G_VARIANT_TYPE_BOOLEAN)) {
313                                 roaming = g_variant_get_boolean(variant);
314                                 g_default_connection.roaming = roaming;
315                         }
316                 }
317         } else {
318                 ;//Do nothing
319         }
320 done:
321         if (sigvalue)
322                 g_free(sigvalue);
323
324         if (variant)
325                 g_variant_unref(variant);
326
327         return;
328 }
329
330 stc_error_e stc_default_connection_monitor_init(stc_s *stc)
331 {
332         ret_value_msg_if(stc == NULL, STC_ERROR_INVALID_PARAMETER, "failed to get stc data");
333
334         __get_default_profile(stc->connection);
335         g_default_connection_sub_id =
336                 stc_manager_gdbus_subscribe_signal(stc->connection,
337                                                    CONNMAN_SERVICE,
338                                                    CONNMAN_SERVICE_INTERFACE,
339                                                    CONNMAN_SIGNAL_PROPERTY_CHANGED,
340                                                    NULL, NULL,
341                                                    G_DBUS_SIGNAL_FLAGS_NONE,
342                                                    _service_signal_cb,
343                                                    NULL, NULL);
344
345         STC_LOGI("Successfully subscribed connman [%s] signal", CONNMAN_SIGNAL_PROPERTY_CHANGED);
346         return STC_ERROR_NONE;
347 }
348
349 stc_error_e stc_default_connection_monitor_deinit(stc_s *stc)
350 {
351         ret_value_msg_if(stc == NULL, STC_ERROR_INVALID_PARAMETER, "failed to get stc data");
352
353         stc_manager_gdbus_unsubscribe_signal(stc->connection,
354                                              g_default_connection_sub_id);
355         FREE(g_default_connection.path);
356         FREE(g_default_connection.ifname);
357         return STC_ERROR_NONE;
358 }
359
360 stc_iface_type_e stc_default_connection_get_type(void)
361 {
362         return g_default_connection.type;
363 }
364
365 gchar *stc_default_connection_get_ifname(void)
366 {
367         return g_strdup(g_default_connection.ifname);
368 }
369
370 gboolean stc_default_connection_get_roaming(void)
371 {
372         return g_default_connection.roaming;
373 }
374
375 default_connection_s *stc_get_default_connection(void)
376 {
377         return &g_default_connection;
378 }