Change to operate in on-demand mode
[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         stc_set_keep_alive(TRUE);
251
252         /* Total statistics since epoch */
253         rule.from = epoch;
254         rule.to = cur_time;
255         rule.iftype = STC_IFACE_ALL;
256
257         if (select_rule != NULL) {
258                 DEBUG_GDBUS_VARIANT("Selection rule: ", select_rule);
259                 GVariantIter *iter = NULL;
260
261                 g_variant_get(select_rule, "a{sv}", &iter);
262                 if (iter != NULL) {
263                         stc_manager_gdbus_dict_foreach(iter,
264                                                        __stc_extract_select_rule,
265                                                        &rule);
266                         g_variant_iter_free(iter);
267                 }
268         } else {
269                 STC_LOGD("No selection rule, using default selection rule."); //LCOV_EXCL_LINE
270         }
271
272         builder = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
273
274         ret = table_statistics_foreach_app(&rule,
275                                            __table_statistics_foreach_app_cb,
276                                            builder);
277         if (ret < STC_ERROR_NONE) {
278                 g_variant_builder_unref(builder); //LCOV_EXCL_LINE
279                 STC_STATISTICS_DBUS_REPLY_ERROR(invocation, ret); //LCOV_EXCL_LINE
280                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
281                 return TRUE; //LCOV_EXCL_LINE
282         }
283
284         return_parameters = g_variant_new("(iaa{sv})", STC_ERROR_NONE, builder);
285         g_variant_builder_unref(builder);
286
287         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
288         STC_DBUS_REPLY(invocation, return_parameters);
289
290         __STC_LOG_FUNC_EXIT__;
291         return TRUE;
292 }
293
294 gboolean handle_statistics_init(StcStatistics *object,
295                                GDBusMethodInvocation *invocation)
296 {
297         __STC_LOG_FUNC_ENTER__;
298
299         stc_set_keep_alive(TRUE);
300
301         STC_LOGI("stc statistics initialized");
302         stc_statistics_complete_init(object, invocation);
303
304         __STC_LOG_FUNC_EXIT__;
305         return TRUE;
306 }
307
308 gboolean handle_statistics_get(StcStatistics *object,
309                                GDBusMethodInvocation *invocation,
310                                const gchar *app_id,
311                                GVariant *select_rule,
312                                void *user_data)
313 {
314         __STC_LOG_FUNC_ENTER__;
315         table_statistics_select_rule rule = {0, };
316         const time_t cur_time = time(0);
317         const time_t epoch = 0;
318         GVariantBuilder *builder = NULL;
319         GVariant *return_parameters = NULL;
320         stc_error_e ret;
321
322         stc_set_keep_alive(TRUE);
323
324         /* Total statistics since epoch */
325         rule.from = epoch;
326         rule.to = cur_time;
327         rule.iftype = STC_IFACE_ALL;
328
329         if (select_rule != NULL) {
330                 DEBUG_GDBUS_VARIANT("Selection rule: ", select_rule);
331                 GVariantIter *iter = NULL;
332
333                 g_variant_get(select_rule, "a{sv}", &iter);
334                 if (iter != NULL) {
335                         stc_manager_gdbus_dict_foreach(iter,
336                                                        __stc_extract_select_rule,
337                                                        &rule);
338                         g_variant_iter_free(iter);
339                 }
340         } else {
341                 STC_LOGD("No selection rule, using default selection rule."); //LCOV_EXCL_LINE
342         }
343
344         builder = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
345
346         ret = table_statistics_per_app(app_id, &rule,
347                                        __table_statistics_per_app_cb,
348                                        builder);
349         if (ret < STC_ERROR_NONE) {
350                 g_variant_builder_unref(builder); //LCOV_EXCL_LINE
351                 STC_STATISTICS_DBUS_REPLY_ERROR(invocation, ret); //LCOV_EXCL_LINE
352                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
353                 return TRUE; //LCOV_EXCL_LINE
354         }
355
356         return_parameters = g_variant_new("(iaa{sv})", STC_ERROR_NONE, builder);
357         g_variant_builder_unref(builder);
358
359         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
360         STC_DBUS_REPLY(invocation, return_parameters);
361
362         __STC_LOG_FUNC_EXIT__;
363         return TRUE;
364 }
365
366 gboolean handle_statistics_reset(StcStatistics *object,
367                                  GDBusMethodInvocation *invocation,
368                                  GVariant *reset_rule,
369                                  void *user_data)
370 {
371         __STC_LOG_FUNC_ENTER__;
372         table_statistics_reset_rule rule = {0, };
373         GVariant *return_parameters = NULL;
374         stc_error_e ret;
375
376         stc_set_keep_alive(TRUE);
377
378         if (reset_rule != NULL) {
379                 DEBUG_GDBUS_VARIANT("Selection rule: ", reset_rule);
380                 GVariantIter *iter = NULL;
381
382                 g_variant_get(reset_rule, "a{sv}", &iter);
383                 if (iter != NULL) {
384                         stc_manager_gdbus_dict_foreach(iter,
385                                                        __stc_extract_reset_rule,
386                                                        &rule);
387                         g_variant_iter_free(iter);
388                 }
389         } else {
390                 STC_LOGD("No selection rule, using default selection rule."); //LCOV_EXCL_LINE
391         }
392
393         ret = table_statistics_reset(&rule);
394         if (ret < STC_ERROR_NONE) {
395                 STC_STATISTICS_DBUS_REPLY_ERROR(invocation, ret); //LCOV_EXCL_LINE
396                 goto handle_error; //LCOV_EXCL_LINE
397         }
398
399         return_parameters = g_variant_new("(i)", STC_ERROR_NONE);
400
401         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
402         STC_DBUS_REPLY(invocation, return_parameters);
403
404 handle_error:
405         FREE(rule.app_id);
406         FREE(rule.subscriber_id);
407         FREE(rule.interval);
408         __STC_LOG_FUNC_EXIT__;
409         return TRUE;
410 }