Added firewall feature
[platform/core/connectivity/stc-manager.git] / src / stc-statistics.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-db.h"
18 #include "table-statistics.h"
19 #include "stc-statistics.h"
20 #include "stc-manager-gdbus.h"
21
22 #define STATISTICS_DBUS_ERROR_NAME "net.stc.statistics.Error.Failed"
23
24 #define STC_STATISTICS_DBUS_REPLY_ERROR(invocation, err_num) \
25         g_dbus_method_invocation_return_dbus_error((invocation), \
26                                                    STATISTICS_DBUS_ERROR_NAME, \
27                                                    stc_err_strs[-(err_num)])
28
29 static const gchar *stc_err_strs[] = {
30         "ERROR_NONE",
31         "FAIL",
32         "DB_FAILED",
33         "OUT_OF_MEMORY",
34         "INVALID_PARAMETER",
35         "NO_DATA",
36         "ALREADY_DATA",
37         "UNINITIALIZED",
38         "PERMISSION_DENIED",
39         "NOTIMPL"
40 };
41
42 void __stc_statistics_print_app_info(const table_statistics_info *info)
43 {
44         if (!info)
45                 return;
46
47         STC_LOGD("========== App data (Statistics) ==========");
48         STC_LOGD("app_id   : [%s]", info->app_id ? info->app_id : "NULL");
49         STC_LOGD("ifname   : [%s]", info->ifname ? info->ifname : "NULL");
50         STC_LOGD("Sent     : [%lld] bytes", info->cnt.out_bytes);
51         STC_LOGD("Received : [%lld] bytes", info->cnt.in_bytes);
52         STC_LOGD("===========================================");
53 }
54
55 void __stc_extract_select_rule(const char *key, GVariant *value,
56                                void *user_data)
57 {
58         __STC_LOG_FUNC_ENTER__;
59
60         table_statistics_select_rule *rule =
61                 (table_statistics_select_rule *) user_data;
62         if (rule == NULL) {
63                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
64                 return; //LCOV_EXCL_LINE
65         }
66
67         if (!g_strcmp0(key, "from")) {
68                 rule->from = g_variant_get_uint64(value);
69                 STC_LOGD("from: [%lu]", rule->from);
70
71         } else if (!g_strcmp0(key, "to")) {
72                 rule->to = g_variant_get_uint64(value);
73                 STC_LOGD("to: [%lu]", rule->to);
74
75         } else if (!g_strcmp0(key, "iftype")) {
76                 rule->iftype = g_variant_get_uint16(value);
77                 STC_LOGD("iftype: [%u]", (unsigned int) rule->iftype);
78
79         } else {
80                 STC_LOGD("Unknown select rule"); //LCOV_EXCL_LINE
81         }
82
83         __STC_LOG_FUNC_EXIT__;
84 }
85
86 void __stc_extract_reset_rule(const char *key, GVariant *value,
87                                void *user_data)
88 {
89         __STC_LOG_FUNC_ENTER__;
90
91         table_statistics_reset_rule *rule =
92                 (table_statistics_reset_rule *) user_data;
93         if (rule == NULL) {
94                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
95                 return; //LCOV_EXCL_LINE
96         }
97
98         if (!g_strcmp0(key, "app_id")) {
99                 gsize len = 0;
100                 rule->app_id = g_variant_dup_string(value, &len);
101                 STC_LOGD("app_id: [%s]", rule->app_id);
102
103         } else if (!g_strcmp0(key, "subscriber_id")) {
104                 gsize len = 0;
105                 rule->subscriber_id = g_variant_dup_string(value, &len);
106                 STC_LOGD("subscriber_id: [%s]", rule->subscriber_id);
107
108         } else if (!g_strcmp0(key, "iftype")) {
109                 rule->iftype = g_variant_get_uint16(value);
110                 STC_LOGD("iftype: [%u]", (unsigned int) rule->iftype);
111
112         } else if (!g_strcmp0(key, "from")) {
113                 if (!(rule->interval)) {
114                         rule->interval = MALLOC0(stc_db_tm_interval_s, 1); //LCOV_EXCL_LINE
115                         if (!(rule->interval)) { //LCOV_EXCL_LINE
116                                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
117                                 return; //LCOV_EXCL_LINE
118                         }
119                 }
120
121                 rule->interval->from = g_variant_get_uint64(value);
122                 STC_LOGD("from: [%lu]", rule->interval->from);
123
124         } else if (!g_strcmp0(key, "to")) {
125                 if (!(rule->interval)) {
126                         rule->interval = MALLOC0(stc_db_tm_interval_s, 1); //LCOV_EXCL_LINE
127                         if (!(rule->interval)) { //LCOV_EXCL_LINE
128                                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
129                                 return; //LCOV_EXCL_LINE
130                         }
131                 }
132
133                 rule->interval->to = g_variant_get_uint64(value);
134                 STC_LOGD("to: [%lu]", rule->interval->to);
135
136         } else {
137                 STC_LOGD("Unknown reset rule"); //LCOV_EXCL_LINE
138         }
139
140         __STC_LOG_FUNC_EXIT__;
141 }
142
143 void __stc_statistics_app_info_builder_add(GVariantBuilder *builder,
144                                            const table_statistics_info *info)
145 {
146         __STC_LOG_FUNC_ENTER__;
147
148         if (!builder || !info) {
149                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
150                 return; //LCOV_EXCL_LINE
151         }
152
153         if (info->app_id)
154                 g_variant_builder_add(builder, "{sv}", "app_id",
155                                       g_variant_new_string(info->app_id));
156
157         if (info->ifname)
158                 g_variant_builder_add(builder, "{sv}", "ifname",
159                                       g_variant_new_string(info->ifname));
160
161         g_variant_builder_add(builder, "{sv}", "subscriber_id",
162                               g_variant_new_string(info->subscriber_id));
163
164         g_variant_builder_add(builder, "{sv}", "iftype",
165                               g_variant_new_uint16(info->iftype));
166
167         if (info->interval != NULL) {
168                 g_variant_builder_add(builder, "{sv}", "interval_to",
169                                       g_variant_new_uint64(info->interval->to));
170
171                 g_variant_builder_add(builder, "{sv}", "interval_from",
172                                       g_variant_new_uint64(info->interval->from));
173         }
174
175         g_variant_builder_add(builder, "{sv}", "cnt_out_bytes",
176                               g_variant_new_int64(info->cnt.out_bytes));
177
178         g_variant_builder_add(builder, "{sv}", "cnt_in_bytes",
179                               g_variant_new_int64(info->cnt.in_bytes));
180
181         g_variant_builder_add(builder, "{sv}", "roaming",
182                               g_variant_new_uint16(info->roaming));
183
184         g_variant_builder_add(builder, "{sv}", "hw_net_protocol_type",
185                               g_variant_new_uint16(info->hw_net_protocol_type));
186
187         g_variant_builder_add(builder, "{sv}", "ground",
188                               g_variant_new_uint16(info->ground));
189
190         __STC_LOG_FUNC_EXIT__;
191 }
192
193 stc_cb_ret_e __table_statistics_foreach_app_cb(const table_statistics_info *info,
194                                                void *user_data)
195 {
196         __STC_LOG_FUNC_ENTER__;
197         GVariantBuilder *builder = (GVariantBuilder *)user_data;
198         GVariantBuilder sub_builder;
199
200         if (!info || !builder) {
201                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
202                 return STC_CANCEL; //LCOV_EXCL_LINE
203         }
204
205         g_variant_builder_init(&sub_builder, G_VARIANT_TYPE("a{sv}"));
206         __stc_statistics_app_info_builder_add(&sub_builder, info);
207         __stc_statistics_print_app_info(info);
208         g_variant_builder_add_value(builder,
209                                     g_variant_builder_end(&sub_builder));
210
211         __STC_LOG_FUNC_EXIT__;
212         return STC_CONTINUE;
213 }
214
215 stc_cb_ret_e __table_statistics_per_app_cb(const table_statistics_info *info,
216                                            void *user_data)
217 {
218         __STC_LOG_FUNC_ENTER__;
219         GVariantBuilder *builder = (GVariantBuilder *)user_data;
220         GVariantBuilder sub_builder;
221
222         if (!info || !builder) {
223                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
224                 return STC_CANCEL; //LCOV_EXCL_LINE
225         }
226
227         g_variant_builder_init(&sub_builder, G_VARIANT_TYPE("a{sv}"));
228         __stc_statistics_app_info_builder_add(&sub_builder, info);
229         __stc_statistics_print_app_info(info);
230         g_variant_builder_add_value(builder,
231                                     g_variant_builder_end(&sub_builder));
232
233         __STC_LOG_FUNC_EXIT__;
234         return STC_CONTINUE;
235 }
236
237 gboolean handle_statistics_get_all(StcStatistics *object,
238                                    GDBusMethodInvocation *invocation,
239                                    GVariant *select_rule,
240                                    void *user_data)
241 {
242         __STC_LOG_FUNC_ENTER__;
243         table_statistics_select_rule rule = {0, };
244         const time_t cur_time = time(0);
245         const time_t epoch = 0;
246         GVariantBuilder *builder = NULL;
247         GVariant *return_parameters = NULL;
248         stc_error_e ret;
249
250         /* Total statistics since epoch */
251         rule.from = epoch;
252         rule.to = cur_time;
253         rule.iftype = STC_IFACE_ALL;
254
255         if (select_rule != NULL) {
256                 DEBUG_GDBUS_VARIANT("Selection rule: ", select_rule);
257                 GVariantIter *iter = NULL;
258
259                 g_variant_get(select_rule, "a{sv}", &iter);
260                 if (iter != NULL) {
261                         stc_manager_gdbus_dict_foreach(iter,
262                                                        __stc_extract_select_rule,
263                                                        &rule);
264                         g_variant_iter_free(iter);
265                 }
266         } else {
267                 STC_LOGD("No selection rule, using default selection rule."); //LCOV_EXCL_LINE
268         }
269
270         builder = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
271
272         ret = table_statistics_foreach_app(&rule,
273                                            __table_statistics_foreach_app_cb,
274                                            builder);
275         if (ret < STC_ERROR_NONE) {
276                 g_variant_builder_unref(builder); //LCOV_EXCL_LINE
277                 STC_STATISTICS_DBUS_REPLY_ERROR(invocation, ret); //LCOV_EXCL_LINE
278                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
279                 return TRUE; //LCOV_EXCL_LINE
280         }
281
282         return_parameters = g_variant_new("(iaa{sv})", STC_ERROR_NONE, builder);
283         g_variant_builder_unref(builder);
284
285         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
286         STC_DBUS_REPLY(invocation, return_parameters);
287
288         __STC_LOG_FUNC_EXIT__;
289         return TRUE;
290 }
291
292 gboolean handle_statistics_init(StcStatistics *object,
293                                GDBusMethodInvocation *invocation)
294 {
295         __STC_LOG_FUNC_ENTER__;
296
297         STC_LOGI("stc statistics initialized");
298         stc_statistics_complete_init(object, invocation);
299
300         __STC_LOG_FUNC_EXIT__;
301         return TRUE;
302 }
303
304 gboolean handle_statistics_get(StcStatistics *object,
305                                GDBusMethodInvocation *invocation,
306                                const gchar *app_id,
307                                GVariant *select_rule,
308                                void *user_data)
309 {
310         __STC_LOG_FUNC_ENTER__;
311         table_statistics_select_rule rule = {0, };
312         const time_t cur_time = time(0);
313         const time_t epoch = 0;
314         GVariantBuilder *builder = NULL;
315         GVariant *return_parameters = NULL;
316         stc_error_e ret;
317
318         /* Total statistics since epoch */
319         rule.from = epoch;
320         rule.to = cur_time;
321         rule.iftype = STC_IFACE_ALL;
322
323         if (select_rule != NULL) {
324                 DEBUG_GDBUS_VARIANT("Selection rule: ", select_rule);
325                 GVariantIter *iter = NULL;
326
327                 g_variant_get(select_rule, "a{sv}", &iter);
328                 if (iter != NULL) {
329                         stc_manager_gdbus_dict_foreach(iter,
330                                                        __stc_extract_select_rule,
331                                                        &rule);
332                         g_variant_iter_free(iter);
333                 }
334         } else {
335                 STC_LOGD("No selection rule, using default selection rule."); //LCOV_EXCL_LINE
336         }
337
338         builder = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
339
340         ret = table_statistics_per_app(app_id, &rule,
341                                        __table_statistics_per_app_cb,
342                                        builder);
343         if (ret < STC_ERROR_NONE) {
344                 g_variant_builder_unref(builder); //LCOV_EXCL_LINE
345                 STC_STATISTICS_DBUS_REPLY_ERROR(invocation, ret); //LCOV_EXCL_LINE
346                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
347                 return TRUE; //LCOV_EXCL_LINE
348         }
349
350         return_parameters = g_variant_new("(iaa{sv})", STC_ERROR_NONE, builder);
351         g_variant_builder_unref(builder);
352
353         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
354         STC_DBUS_REPLY(invocation, return_parameters);
355
356         __STC_LOG_FUNC_EXIT__;
357         return TRUE;
358 }
359
360 gboolean handle_statistics_reset(StcStatistics *object,
361                                  GDBusMethodInvocation *invocation,
362                                  GVariant *reset_rule,
363                                  void *user_data)
364 {
365         __STC_LOG_FUNC_ENTER__;
366         table_statistics_reset_rule rule = {0, };
367         GVariant *return_parameters = NULL;
368         stc_error_e ret;
369
370         if (reset_rule != NULL) {
371                 DEBUG_GDBUS_VARIANT("Selection rule: ", reset_rule);
372                 GVariantIter *iter = NULL;
373
374                 g_variant_get(reset_rule, "a{sv}", &iter);
375                 if (iter != NULL) {
376                         stc_manager_gdbus_dict_foreach(iter,
377                                                        __stc_extract_reset_rule,
378                                                        &rule);
379                         g_variant_iter_free(iter);
380                 }
381         } else {
382                 STC_LOGD("No selection rule, using default selection rule."); //LCOV_EXCL_LINE
383         }
384
385         ret = table_statistics_reset(&rule);
386         if (ret < STC_ERROR_NONE) {
387                 STC_STATISTICS_DBUS_REPLY_ERROR(invocation, ret); //LCOV_EXCL_LINE
388                 goto handle_error; //LCOV_EXCL_LINE
389         }
390
391         return_parameters = g_variant_new("(i)", STC_ERROR_NONE);
392
393         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
394         STC_DBUS_REPLY(invocation, return_parameters);
395
396 handle_error:
397         FREE(rule.app_id);
398         FREE(rule.subscriber_id);
399         FREE(rule.interval);
400         __STC_LOG_FUNC_EXIT__;
401         return TRUE;
402 }