Merge "Corrected and optimized usage of fork and waitpid." into tizen
[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, "imsi")) {
117                 gsize len = 0;
118                 rule->imsi = g_variant_dup_string(value, &len);
119                 STC_LOGD("imsi: [%s]", rule->imsi);
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         g_variant_builder_add(builder, "{sv}", "app_id",
171                               g_variant_new_string(info->app_id));
172
173         g_variant_builder_add(builder, "{sv}", "ifname",
174                               g_variant_new_string(info->ifname));
175
176         g_variant_builder_add(builder, "{sv}", "imsi",
177                               g_variant_new_string(info->imsi));
178
179         g_variant_builder_add(builder, "{sv}", "iftype",
180                               g_variant_new_uint16(info->iftype));
181
182         if (info->interval != NULL) {
183                 g_variant_builder_add(builder, "{sv}", "interval_to",
184                                       g_variant_new_uint64(info->interval->to));
185
186                 g_variant_builder_add(builder, "{sv}", "interval_from",
187                                       g_variant_new_uint64(info->interval->from));
188         }
189
190         g_variant_builder_add(builder, "{sv}", "cnt_out_bytes",
191                               g_variant_new_int64(info->cnt.out_bytes));
192
193         g_variant_builder_add(builder, "{sv}", "cnt_in_bytes",
194                               g_variant_new_int64(info->cnt.in_bytes));
195
196         g_variant_builder_add(builder, "{sv}", "roaming",
197                               g_variant_new_uint16(info->roaming));
198
199         g_variant_builder_add(builder, "{sv}", "hw_net_protocol_type",
200                               g_variant_new_uint16(info->hw_net_protocol_type));
201
202         g_variant_builder_add(builder, "{sv}", "ground",
203                               g_variant_new_uint16(info->ground));
204
205         __STC_LOG_FUNC_EXIT__;
206 }
207
208 stc_cb_ret_e __table_statistics_foreach_app_cb(const table_statistics_info *info,
209                                                void *user_data)
210 {
211         __STC_LOG_FUNC_ENTER__;
212         GVariantBuilder *builder = (GVariantBuilder *)user_data;
213         GVariantBuilder sub_builder;
214
215         if (!info || !builder) {
216                 __STC_LOG_FUNC_EXIT__;
217                 return STC_CANCEL;
218         }
219
220         g_variant_builder_init(&sub_builder, G_VARIANT_TYPE("a{sv}"));
221         __stc_statistics_app_info_builder_add(&sub_builder, info);
222         __stc_statistics_print_app_info(info);
223         g_variant_builder_add_value(builder,
224                                     g_variant_builder_end(&sub_builder));
225
226         __STC_LOG_FUNC_EXIT__;
227         return STC_CONTINUE;
228 }
229
230 stc_cb_ret_e __table_statistics_per_app_cb(const table_statistics_info *info,
231                                            void *user_data)
232 {
233         __STC_LOG_FUNC_ENTER__;
234         GVariantBuilder *builder = (GVariantBuilder *)user_data;
235
236         if (!info || !builder) {
237                 __STC_LOG_FUNC_EXIT__;
238                 return STC_CANCEL;
239         }
240
241         __stc_statistics_app_info_builder_add(builder, info);
242         __stc_statistics_print_app_info(info);
243
244         __STC_LOG_FUNC_EXIT__;
245         return STC_CONTINUE;
246 }
247
248 gboolean handle_statistics_get_all(StcStatistics *object,
249                                    GDBusMethodInvocation *invocation,
250                                    GVariant *select_rule,
251                                    void *user_data)
252 {
253         __STC_LOG_FUNC_ENTER__;
254         table_statistics_select_rule rule = {0, };
255         const time_t cur_time = time(0);
256         const time_t epoch = 0;
257         GVariantBuilder *builder = NULL;
258         GVariant *return_parameters = NULL;
259         stc_error_e ret;
260
261         /* Total statistics since epoch */
262         rule.from = epoch;
263         rule.to = cur_time;
264         rule.iftype = STC_IFACE_ALL;
265
266         if (select_rule != NULL) {
267                 DEBUG_GDBUS_VARIANT("Selection rule: ", select_rule);
268                 GVariantIter *iter = NULL;
269
270                 g_variant_get(select_rule, "a{sv}", &iter);
271                 if (iter != NULL) {
272                         stc_manager_gdbus_dict_foreach(iter,
273                                                        __stc_extract_select_rule,
274                                                        &rule);
275                         g_variant_iter_free(iter);
276                 }
277         } else {
278                 STC_LOGD("No selection rule, using default selection rule.");
279         }
280
281         builder = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
282
283         ret = table_statistics_foreach_app(&rule,
284                                            __table_statistics_foreach_app_cb,
285                                            builder);
286         if (ret < STC_ERROR_NONE) {
287                 g_variant_builder_unref(builder);
288                 STC_STATISTICS_DBUS_REPLY_ERROR(invocation, ret);
289                 __STC_LOG_FUNC_EXIT__;
290                 return TRUE;
291         }
292
293         return_parameters = g_variant_new("(iaa{sv})", STC_ERROR_NONE, builder);
294         g_variant_builder_unref(builder);
295
296         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
297         STC_DBUS_REPLY(invocation, return_parameters);
298
299         __STC_LOG_FUNC_EXIT__;
300         return TRUE;
301 }
302
303 gboolean handle_statistics_init(StcStatistics *object,
304                                GDBusMethodInvocation *invocation)
305 {
306         __STC_LOG_FUNC_ENTER__;
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         /* Total statistics since epoch */
330         rule.from = epoch;
331         rule.to = cur_time;
332         rule.iftype = STC_IFACE_ALL;
333
334         if (select_rule != NULL) {
335                 DEBUG_GDBUS_VARIANT("Selection rule: ", select_rule);
336                 GVariantIter *iter = NULL;
337
338                 g_variant_get(select_rule, "a{sv}", &iter);
339                 if (iter != NULL) {
340                         stc_manager_gdbus_dict_foreach(iter,
341                                                        __stc_extract_select_rule,
342                                                        &rule);
343                         g_variant_iter_free(iter);
344                 }
345         } else {
346                 STC_LOGD("No selection rule, using default selection rule.");
347         }
348
349         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
350
351         ret = table_statistics_per_app(app_id, &rule,
352                                        __table_statistics_per_app_cb,
353                                        builder);
354         if (ret < STC_ERROR_NONE) {
355                 g_variant_builder_unref(builder);
356                 STC_STATISTICS_DBUS_REPLY_ERROR(invocation, ret);
357                 __STC_LOG_FUNC_EXIT__;
358                 return TRUE;
359         }
360
361         return_parameters = g_variant_new("(ia{sv})", STC_ERROR_NONE, builder);
362         g_variant_builder_unref(builder);
363
364         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
365         STC_DBUS_REPLY(invocation, return_parameters);
366
367         __STC_LOG_FUNC_EXIT__;
368         return TRUE;
369 }
370
371 gboolean handle_statistics_reset(StcStatistics *object,
372                                  GDBusMethodInvocation *invocation,
373                                  GVariant *reset_rule,
374                                  void *user_data)
375 {
376         __STC_LOG_FUNC_ENTER__;
377         table_statistics_reset_rule rule = {0, };
378         GVariant *return_parameters = NULL;
379         stc_error_e ret;
380
381         if (reset_rule != NULL) {
382                 DEBUG_GDBUS_VARIANT("Selection rule: ", reset_rule);
383                 GVariantIter *iter = NULL;
384
385                 g_variant_get(reset_rule, "a{sv}", &iter);
386                 if (iter != NULL) {
387                         stc_manager_gdbus_dict_foreach(iter,
388                                                        __stc_extract_reset_rule,
389                                                        &rule);
390                         g_variant_iter_free(iter);
391                 }
392         } else {
393                 STC_LOGD("No selection rule, using default selection rule.");
394         }
395
396         ret = table_statistics_reset(&rule);
397         if (ret < STC_ERROR_NONE) {
398                 STC_STATISTICS_DBUS_REPLY_ERROR(invocation, ret);
399                 goto handle_error;
400         }
401
402         return_parameters = g_variant_new("(i)", STC_ERROR_NONE);
403
404         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
405         STC_DBUS_REPLY(invocation, return_parameters);
406
407 handle_error:
408         FREE(rule.app_id);
409         FREE(rule.imsi);
410         FREE(rule.interval);
411         __STC_LOG_FUNC_EXIT__;
412         return TRUE;
413 }