Add support of app_id in GetAll method call on statistics interface
[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 if (!g_strcmp0(key, "app_id")) {
80                 gsize length = 0;
81                 rule->app_id = g_variant_dup_string(value, &length);
82                 STC_LOGD("app_id: [%s]", rule->app_id);
83
84         } else {
85                 STC_LOGD("Unknown select rule"); //LCOV_EXCL_LINE
86         }
87
88         __STC_LOG_FUNC_EXIT__;
89 }
90
91 void __stc_extract_reset_rule(const char *key, GVariant *value,
92                                void *user_data)
93 {
94         __STC_LOG_FUNC_ENTER__;
95
96         table_statistics_reset_rule *rule =
97                 (table_statistics_reset_rule *) user_data;
98         if (rule == NULL) {
99                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
100                 return; //LCOV_EXCL_LINE
101         }
102
103         if (!g_strcmp0(key, "app_id")) {
104                 gsize len = 0;
105                 rule->app_id = g_variant_dup_string(value, &len);
106                 STC_LOGD("app_id: [%s]", rule->app_id);
107
108         } else if (!g_strcmp0(key, "subscriber_id")) {
109                 gsize len = 0;
110                 rule->subscriber_id = g_variant_dup_string(value, &len);
111                 STC_LOGD("subscriber_id: [%s]", rule->subscriber_id);
112
113         } else if (!g_strcmp0(key, "iftype")) {
114                 rule->iftype = g_variant_get_uint16(value);
115                 STC_LOGD("iftype: [%u]", (unsigned int) rule->iftype);
116
117         } else if (!g_strcmp0(key, "from")) {
118                 if (!(rule->interval)) {
119                         rule->interval = MALLOC0(stc_db_tm_interval_s, 1); //LCOV_EXCL_LINE
120                         if (!(rule->interval)) { //LCOV_EXCL_LINE
121                                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
122                                 return; //LCOV_EXCL_LINE
123                         }
124                 }
125
126                 rule->interval->from = g_variant_get_uint64(value);
127                 STC_LOGD("from: [%lu]", rule->interval->from);
128
129         } else if (!g_strcmp0(key, "to")) {
130                 if (!(rule->interval)) {
131                         rule->interval = MALLOC0(stc_db_tm_interval_s, 1); //LCOV_EXCL_LINE
132                         if (!(rule->interval)) { //LCOV_EXCL_LINE
133                                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
134                                 return; //LCOV_EXCL_LINE
135                         }
136                 }
137
138                 rule->interval->to = g_variant_get_uint64(value);
139                 STC_LOGD("to: [%lu]", rule->interval->to);
140
141         } else {
142                 STC_LOGD("Unknown reset rule"); //LCOV_EXCL_LINE
143         }
144
145         __STC_LOG_FUNC_EXIT__;
146 }
147
148 void __stc_statistics_app_info_builder_add(GVariantBuilder *builder,
149                                            const table_statistics_info *info)
150 {
151         __STC_LOG_FUNC_ENTER__;
152
153         if (!builder || !info) {
154                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
155                 return; //LCOV_EXCL_LINE
156         }
157
158         if (info->app_id)
159                 g_variant_builder_add(builder, "{sv}", "app_id",
160                                       g_variant_new_string(info->app_id));
161
162         if (info->ifname)
163                 g_variant_builder_add(builder, "{sv}", "ifname",
164                                       g_variant_new_string(info->ifname));
165
166         g_variant_builder_add(builder, "{sv}", "subscriber_id",
167                               g_variant_new_string(info->subscriber_id));
168
169         g_variant_builder_add(builder, "{sv}", "iftype",
170                               g_variant_new_uint16(info->iftype));
171
172         if (info->interval != NULL) {
173                 g_variant_builder_add(builder, "{sv}", "interval_to",
174                                       g_variant_new_uint64(info->interval->to));
175
176                 g_variant_builder_add(builder, "{sv}", "interval_from",
177                                       g_variant_new_uint64(info->interval->from));
178         }
179
180         g_variant_builder_add(builder, "{sv}", "cnt_out_bytes",
181                               g_variant_new_int64(info->cnt.out_bytes));
182
183         g_variant_builder_add(builder, "{sv}", "cnt_in_bytes",
184                               g_variant_new_int64(info->cnt.in_bytes));
185
186         g_variant_builder_add(builder, "{sv}", "roaming",
187                               g_variant_new_uint16(info->roaming));
188
189         g_variant_builder_add(builder, "{sv}", "hw_net_protocol_type",
190                               g_variant_new_uint16(info->hw_net_protocol_type));
191
192         g_variant_builder_add(builder, "{sv}", "ground",
193                               g_variant_new_uint16(info->ground));
194
195         __STC_LOG_FUNC_EXIT__;
196 }
197
198 stc_cb_ret_e __table_statistics_foreach_app_cb(const table_statistics_info *info,
199                                                void *user_data)
200 {
201         __STC_LOG_FUNC_ENTER__;
202         GVariantBuilder *builder = (GVariantBuilder *)user_data;
203         GVariantBuilder sub_builder;
204
205         if (!info || !builder) {
206                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
207                 return STC_CANCEL; //LCOV_EXCL_LINE
208         }
209
210         g_variant_builder_init(&sub_builder, G_VARIANT_TYPE("a{sv}"));
211         __stc_statistics_app_info_builder_add(&sub_builder, info);
212         __stc_statistics_print_app_info(info);
213         g_variant_builder_add_value(builder,
214                                     g_variant_builder_end(&sub_builder));
215
216         __STC_LOG_FUNC_EXIT__;
217         return STC_CONTINUE;
218 }
219
220 stc_cb_ret_e __table_statistics_per_app_cb(const table_statistics_info *info,
221                                            void *user_data)
222 {
223         __STC_LOG_FUNC_ENTER__;
224         GVariantBuilder *builder = (GVariantBuilder *)user_data;
225         GVariantBuilder sub_builder;
226
227         if (!info || !builder) {
228                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
229                 return STC_CANCEL; //LCOV_EXCL_LINE
230         }
231
232         g_variant_builder_init(&sub_builder, G_VARIANT_TYPE("a{sv}"));
233         __stc_statistics_app_info_builder_add(&sub_builder, info);
234         __stc_statistics_print_app_info(info);
235         g_variant_builder_add_value(builder,
236                                     g_variant_builder_end(&sub_builder));
237
238         __STC_LOG_FUNC_EXIT__;
239         return STC_CONTINUE;
240 }
241
242 gboolean handle_statistics_get_all(StcStatistics *object,
243                                    GDBusMethodInvocation *invocation,
244                                    GVariant *select_rule,
245                                    void *user_data)
246 {
247         __STC_LOG_FUNC_ENTER__;
248         table_statistics_select_rule rule = {0, };
249         const time_t cur_time = time(0);
250         const time_t epoch = 0;
251         GVariantBuilder *builder = NULL;
252         GVariant *return_parameters = NULL;
253         stc_error_e ret;
254
255         stc_set_keep_alive(TRUE);
256
257         /* Total statistics since epoch */
258         rule.from = epoch;
259         rule.to = cur_time;
260         rule.iftype = STC_IFACE_ALL;
261
262         if (select_rule != NULL) {
263                 DEBUG_GDBUS_VARIANT("Selection rule: ", select_rule);
264                 GVariantIter *iter = NULL;
265
266                 g_variant_get(select_rule, "a{sv}", &iter);
267                 if (iter != NULL) {
268                         stc_manager_gdbus_dict_foreach(iter,
269                                                        __stc_extract_select_rule,
270                                                        &rule);
271                         g_variant_iter_free(iter);
272                 }
273         } else {
274                 STC_LOGD("No selection rule, using default selection rule."); //LCOV_EXCL_LINE
275         }
276
277         builder = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
278
279         ret = table_statistics_foreach_app(&rule,
280                                            __table_statistics_foreach_app_cb,
281                                            builder);
282         if (ret < STC_ERROR_NONE) {
283                 g_variant_builder_unref(builder); //LCOV_EXCL_LINE
284                 STC_STATISTICS_DBUS_REPLY_ERROR(invocation, ret); //LCOV_EXCL_LINE
285                 g_free(rule.app_id);
286                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
287                 return TRUE; //LCOV_EXCL_LINE
288         }
289
290         return_parameters = g_variant_new("(iaa{sv})", STC_ERROR_NONE, builder);
291         g_variant_builder_unref(builder);
292
293         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
294         STC_DBUS_REPLY(invocation, return_parameters);
295
296         g_free(rule.app_id);
297         __STC_LOG_FUNC_EXIT__;
298         return TRUE;
299 }
300
301 gboolean handle_statistics_init(StcStatistics *object,
302                                 GDBusMethodInvocation *invocation)
303 {
304         __STC_LOG_FUNC_ENTER__;
305
306         stc_set_keep_alive(TRUE);
307
308         STC_LOGI("stc statistics initialized");
309         stc_statistics_complete_init(object, invocation);
310
311         __STC_LOG_FUNC_EXIT__;
312         return TRUE;
313 }
314
315 gboolean handle_statistics_get(StcStatistics *object,
316                                GDBusMethodInvocation *invocation,
317                                const gchar *app_id,
318                                GVariant *select_rule,
319                                void *user_data)
320 {
321         __STC_LOG_FUNC_ENTER__;
322         table_statistics_select_rule rule = {0, };
323         const time_t cur_time = time(0);
324         const time_t epoch = 0;
325         GVariantBuilder *builder = NULL;
326         GVariant *return_parameters = NULL;
327         stc_error_e ret;
328
329         stc_set_keep_alive(TRUE);
330
331         /* Total statistics since epoch */
332         rule.from = epoch;
333         rule.to = cur_time;
334         rule.iftype = STC_IFACE_ALL;
335
336         if (select_rule != NULL) {
337                 DEBUG_GDBUS_VARIANT("Selection rule: ", select_rule);
338                 GVariantIter *iter = NULL;
339
340                 g_variant_get(select_rule, "a{sv}", &iter);
341                 if (iter != NULL) {
342                         stc_manager_gdbus_dict_foreach(iter,
343                                                        __stc_extract_select_rule,
344                                                        &rule);
345                         g_variant_iter_free(iter);
346                 }
347         } else {
348                 STC_LOGD("No selection rule, using default selection rule."); //LCOV_EXCL_LINE
349         }
350
351         builder = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
352
353         ret = table_statistics_per_app(app_id, &rule,
354                                        __table_statistics_per_app_cb,
355                                        builder);
356         if (ret < STC_ERROR_NONE) {
357                 g_variant_builder_unref(builder); //LCOV_EXCL_LINE
358                 STC_STATISTICS_DBUS_REPLY_ERROR(invocation, ret); //LCOV_EXCL_LINE
359                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
360                 return TRUE; //LCOV_EXCL_LINE
361         }
362
363         return_parameters = g_variant_new("(iaa{sv})", STC_ERROR_NONE, builder);
364         g_variant_builder_unref(builder);
365
366         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
367         STC_DBUS_REPLY(invocation, return_parameters);
368
369         __STC_LOG_FUNC_EXIT__;
370         return TRUE;
371 }
372
373 gboolean handle_statistics_reset(StcStatistics *object,
374                                  GDBusMethodInvocation *invocation,
375                                  GVariant *reset_rule,
376                                  void *user_data)
377 {
378         __STC_LOG_FUNC_ENTER__;
379         table_statistics_reset_rule rule = {0, };
380         GVariant *return_parameters = NULL;
381         stc_error_e ret;
382
383         stc_set_keep_alive(TRUE);
384
385         if (reset_rule != NULL) {
386                 DEBUG_GDBUS_VARIANT("Selection rule: ", reset_rule);
387                 GVariantIter *iter = NULL;
388
389                 g_variant_get(reset_rule, "a{sv}", &iter);
390                 if (iter != NULL) {
391                         stc_manager_gdbus_dict_foreach(iter,
392                                                        __stc_extract_reset_rule,
393                                                        &rule);
394                         g_variant_iter_free(iter);
395                 }
396         } else {
397                 STC_LOGD("No selection rule, using default selection rule."); //LCOV_EXCL_LINE
398         }
399
400         ret = table_statistics_reset(&rule);
401         if (ret < STC_ERROR_NONE) {
402                 STC_STATISTICS_DBUS_REPLY_ERROR(invocation, ret); //LCOV_EXCL_LINE
403                 goto handle_error; //LCOV_EXCL_LINE
404         }
405
406         return_parameters = g_variant_new("(i)", STC_ERROR_NONE);
407
408         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
409         STC_DBUS_REPLY(invocation, return_parameters);
410
411 handle_error:
412         FREE(rule.app_id);
413         FREE(rule.subscriber_id);
414         FREE(rule.interval);
415         __STC_LOG_FUNC_EXIT__;
416         return TRUE;
417 }