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