Merge "Return errors to caller" into tizen_5.5
[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 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"); //LCOV_EXCL_LINE
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__; //LCOV_EXCL_LINE
104                 return; //LCOV_EXCL_LINE
105         }
106
107         if (!g_strcmp0(key, "app_id")) {
108                 gsize len = 0;
109                 rule->app_id = g_variant_dup_string(value, &len);
110                 STC_LOGD("app_id: [%s]", rule->app_id);
111
112         } else if (!g_strcmp0(key, "subscriber_id")) {
113                 gsize len = 0;
114                 rule->subscriber_id = g_variant_dup_string(value, &len);
115                 STC_LOGD("subscriber_id: [%s]", rule->subscriber_id);
116
117         } else if (!g_strcmp0(key, "iftype")) {
118                 rule->iftype = g_variant_get_uint16(value);
119                 STC_LOGD("iftype: [%u]", (unsigned int) rule->iftype);
120
121         } else if (!g_strcmp0(key, "from")) {
122                 if (!(rule->interval)) {
123                         rule->interval = MALLOC0(stc_db_tm_interval_s, 1); //LCOV_EXCL_LINE
124                         if (!(rule->interval)) { //LCOV_EXCL_LINE
125                                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
126                                 return; //LCOV_EXCL_LINE
127                         }
128                 }
129
130                 rule->interval->from = g_variant_get_uint64(value);
131                 STC_LOGD("from: [%lu]", rule->interval->from);
132
133         } else if (!g_strcmp0(key, "to")) {
134                 if (!(rule->interval)) {
135                         rule->interval = MALLOC0(stc_db_tm_interval_s, 1); //LCOV_EXCL_LINE
136                         if (!(rule->interval)) { //LCOV_EXCL_LINE
137                                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
138                                 return; //LCOV_EXCL_LINE
139                         }
140                 }
141
142                 rule->interval->to = g_variant_get_uint64(value);
143                 STC_LOGD("to: [%lu]", rule->interval->to);
144
145         } else {
146                 STC_LOGD("Unknown reset rule"); //LCOV_EXCL_LINE
147         }
148
149         __STC_LOG_FUNC_EXIT__;
150 }
151
152 void __stc_statistics_app_info_builder_add(GVariantBuilder *builder,
153                                            const table_statistics_info *info)
154 {
155         __STC_LOG_FUNC_ENTER__;
156
157         if (!builder || !info) {
158                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
159                 return; //LCOV_EXCL_LINE
160         }
161
162         if (info->app_id)
163                 g_variant_builder_add(builder, "{sv}", "app_id",
164                                       g_variant_new_string(info->app_id));
165
166         if (info->ifname)
167                 g_variant_builder_add(builder, "{sv}", "ifname",
168                                       g_variant_new_string(info->ifname));
169
170         g_variant_builder_add(builder, "{sv}", "subscriber_id",
171                               g_variant_new_string(info->subscriber_id));
172
173         g_variant_builder_add(builder, "{sv}", "iftype",
174                               g_variant_new_uint16(info->iftype));
175
176         if (info->interval != NULL) {
177                 g_variant_builder_add(builder, "{sv}", "interval_to",
178                                       g_variant_new_uint64(info->interval->to));
179
180                 g_variant_builder_add(builder, "{sv}", "interval_from",
181                                       g_variant_new_uint64(info->interval->from));
182         }
183
184         g_variant_builder_add(builder, "{sv}", "cnt_out_bytes",
185                               g_variant_new_int64(info->cnt.out_bytes));
186
187         g_variant_builder_add(builder, "{sv}", "cnt_in_bytes",
188                               g_variant_new_int64(info->cnt.in_bytes));
189
190         g_variant_builder_add(builder, "{sv}", "roaming",
191                               g_variant_new_uint16(info->roaming));
192
193         g_variant_builder_add(builder, "{sv}", "hw_net_protocol_type",
194                               g_variant_new_uint16(info->hw_net_protocol_type));
195
196         g_variant_builder_add(builder, "{sv}", "ground",
197                               g_variant_new_uint16(info->ground));
198
199         __STC_LOG_FUNC_EXIT__;
200 }
201
202 stc_cb_ret_e __table_statistics_foreach_app_cb(const table_statistics_info *info,
203                                                void *user_data)
204 {
205         __STC_LOG_FUNC_ENTER__;
206         GVariantBuilder *builder = (GVariantBuilder *)user_data;
207         GVariantBuilder sub_builder;
208
209         if (!info || !builder) {
210                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
211                 return STC_CANCEL; //LCOV_EXCL_LINE
212         }
213
214         g_variant_builder_init(&sub_builder, G_VARIANT_TYPE("a{sv}"));
215         __stc_statistics_app_info_builder_add(&sub_builder, info);
216         __stc_statistics_print_app_info(info);
217         g_variant_builder_add_value(builder,
218                                     g_variant_builder_end(&sub_builder));
219
220         __STC_LOG_FUNC_EXIT__;
221         return STC_CONTINUE;
222 }
223
224 stc_cb_ret_e __table_statistics_per_app_cb(const table_statistics_info *info,
225                                            void *user_data)
226 {
227         __STC_LOG_FUNC_ENTER__;
228         GVariantBuilder *builder = (GVariantBuilder *)user_data;
229         GVariantBuilder sub_builder;
230
231         if (!info || !builder) {
232                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
233                 return STC_CANCEL; //LCOV_EXCL_LINE
234         }
235
236         g_variant_builder_init(&sub_builder, G_VARIANT_TYPE("a{sv}"));
237         __stc_statistics_app_info_builder_add(&sub_builder, info);
238         __stc_statistics_print_app_info(info);
239         g_variant_builder_add_value(builder,
240                                     g_variant_builder_end(&sub_builder));
241
242         __STC_LOG_FUNC_EXIT__;
243         return STC_CONTINUE;
244 }
245
246 gboolean handle_statistics_get_all(StcStatistics *object,
247                                    GDBusMethodInvocation *invocation,
248                                    GVariant *select_rule,
249                                    void *user_data)
250 {
251         __STC_LOG_FUNC_ENTER__;
252         table_statistics_select_rule rule = {0, };
253         const time_t cur_time = time(0);
254         const time_t epoch = 0;
255         GVariantBuilder *builder = NULL;
256         GVariant *return_parameters = NULL;
257         stc_error_e ret;
258
259         stc_set_keep_alive(TRUE);
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."); //LCOV_EXCL_LINE
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); //LCOV_EXCL_LINE
288                 STC_STATISTICS_DBUS_REPLY_ERROR(invocation, ret); //LCOV_EXCL_LINE
289                 g_free(rule.app_id);
290                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
291                 return TRUE; //LCOV_EXCL_LINE
292         }
293
294         return_parameters = g_variant_new("(iaa{sv})", STC_ERROR_NONE, builder);
295         g_variant_builder_unref(builder);
296
297         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
298         STC_DBUS_REPLY(invocation, return_parameters);
299
300         g_free(rule.app_id);
301         __STC_LOG_FUNC_EXIT__;
302         return TRUE;
303 }
304
305 gboolean handle_statistics_init(StcStatistics *object,
306                                 GDBusMethodInvocation *invocation)
307 {
308         __STC_LOG_FUNC_ENTER__;
309
310         stc_set_keep_alive(TRUE);
311
312         STC_LOGI("stc statistics initialized");
313         stc_statistics_complete_init(object, invocation);
314
315         __STC_LOG_FUNC_EXIT__;
316         return TRUE;
317 }
318
319 gboolean handle_statistics_get(StcStatistics *object,
320                                GDBusMethodInvocation *invocation,
321                                const gchar *app_id,
322                                GVariant *select_rule,
323                                void *user_data)
324 {
325         __STC_LOG_FUNC_ENTER__;
326         table_statistics_select_rule rule = {0, };
327         const time_t cur_time = time(0);
328         const time_t epoch = 0;
329         GVariantBuilder *builder = NULL;
330         GVariant *return_parameters = NULL;
331         stc_error_e ret;
332
333         stc_set_keep_alive(TRUE);
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."); //LCOV_EXCL_LINE
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); //LCOV_EXCL_LINE
362                 STC_STATISTICS_DBUS_REPLY_ERROR(invocation, ret); //LCOV_EXCL_LINE
363                 g_free(rule.app_id);
364                 __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE
365                 return TRUE; //LCOV_EXCL_LINE
366         }
367
368         return_parameters = g_variant_new("(iaa{sv})", STC_ERROR_NONE, builder);
369         g_variant_builder_unref(builder);
370
371         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
372         STC_DBUS_REPLY(invocation, return_parameters);
373
374         g_free(rule.app_id);
375         __STC_LOG_FUNC_EXIT__;
376         return TRUE;
377 }
378
379 gboolean handle_statistics_reset(StcStatistics *object,
380                                  GDBusMethodInvocation *invocation,
381                                  GVariant *reset_rule,
382                                  void *user_data)
383 {
384         __STC_LOG_FUNC_ENTER__;
385         table_statistics_reset_rule rule = {0, };
386         GVariant *return_parameters = NULL;
387         stc_error_e ret;
388
389         stc_set_keep_alive(TRUE);
390
391         if (reset_rule != NULL) {
392                 DEBUG_GDBUS_VARIANT("Selection rule: ", reset_rule);
393                 GVariantIter *iter = NULL;
394
395                 g_variant_get(reset_rule, "a{sv}", &iter);
396                 if (iter != NULL) {
397                         stc_manager_gdbus_dict_foreach(iter,
398                                                        __stc_extract_reset_rule,
399                                                        &rule);
400                         g_variant_iter_free(iter);
401                 }
402         } else {
403                 STC_LOGD("No selection rule, using default selection rule."); //LCOV_EXCL_LINE
404         }
405
406         ret = table_statistics_reset(&rule);
407         if (ret < STC_ERROR_NONE) {
408                 STC_STATISTICS_DBUS_REPLY_ERROR(invocation, ret); //LCOV_EXCL_LINE
409                 goto handle_error; //LCOV_EXCL_LINE
410         }
411
412         return_parameters = g_variant_new("(i)", STC_ERROR_NONE);
413
414         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
415         STC_DBUS_REPLY(invocation, return_parameters);
416
417 handle_error:
418         FREE(rule.app_id);
419         FREE(rule.subscriber_id);
420         FREE(rule.interval);
421         __STC_LOG_FUNC_EXIT__;
422         return TRUE;
423 }