Modified properly data type
[platform/core/connectivity/stc-manager.git] / src / stc-restriction.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-restrictions.h"
19 #include "stc-restriction.h"
20 #include "stc-manager-gdbus.h"
21 #include "stc-monitor.h"
22
23 #define RESTRICTION_DBUS_ERROR_NAME "net.stc.restriction.Error.Failed"
24
25 #define STC_RESTRICTION_DBUS_REPLY_ERROR(invocation, err_num) \
26         g_dbus_method_invocation_return_dbus_error((invocation), \
27                                                    RESTRICTION_DBUS_ERROR_NAME, \
28                                                    stc_err_strs[-(err_num)])
29
30 static const gchar *stc_err_strs[] = {
31         "ERROR_NONE",
32         "FAIL",
33         "DB_FAILED",
34         "OUT_OF_MEMORY",
35         "INVALID_PARAMETER",
36         "NO_DATA",
37         "UNINITIALIZED",
38         "NOTIMPL"
39 };
40
41 void __initialize_rstn_rule(table_restrictions_info *rule)
42 {
43         rule->app_id = NULL;
44         rule->ifname = NULL;
45         rule->iftype = STC_IFACE_ALL;
46         rule->rst_state = STC_RESTRICTION_REMOVED;
47         rule->rcv_limit = 0;
48         rule->send_limit = 0;
49         rule->rcv_warn_limit = 0;
50         rule->send_warn_limit = 0;
51         rule->roaming = STC_ROAMING_DISABLE;
52         rule->imsi = NULL;
53 }
54
55 gboolean __validate_rstn_rule(table_restrictions_info *rule,
56                               enum traffic_restriction_type rst_type)
57 {
58         __STC_LOG_FUNC_ENTER__;
59
60         if (rule == NULL) {
61                 __STC_LOG_FUNC_EXIT__;
62                 return FALSE;
63         }
64
65         if (rst_type <= RST_UNDEFINDED || rst_type >= RST_MAX_VALUE) {
66                 __STC_LOG_FUNC_EXIT__;
67                 return FALSE;
68         }
69
70         if (rule->iftype <= STC_IFACE_UNKNOWN ||
71             rule->iftype >= STC_IFACE_LAST_ELEM) {
72                 __STC_LOG_FUNC_EXIT__;
73                 return FALSE;
74         }
75
76         if (rule->roaming >= STC_ROAMING_LAST_ELEM) {
77                 __STC_LOG_FUNC_EXIT__;
78                 return FALSE;
79         }
80
81         if (rule->imsi == NULL) {
82                 __STC_LOG_FUNC_EXIT__;
83                 return FALSE;
84         }
85
86         if (rule->app_id == NULL) {
87                 __STC_LOG_FUNC_EXIT__;
88                 return FALSE;
89         }
90
91         __STC_LOG_FUNC_EXIT__;
92         return TRUE;
93 }
94
95 void __stc_restriction_app_info_builder_add(GVariantBuilder *builder,
96                                             const table_restrictions_info *info)
97 {
98         __STC_LOG_FUNC_ENTER__;
99
100         if (!builder || !info) {
101                 __STC_LOG_FUNC_EXIT__;
102                 return;
103         }
104
105         g_variant_builder_add(builder, "{sv}", "app_id",
106                               g_variant_new_string(info->app_id));
107
108         g_variant_builder_add(builder, "{sv}", "ifname",
109                               g_variant_new_string(info->ifname));
110
111         g_variant_builder_add(builder, "{sv}", "iftype",
112                               g_variant_new_uint16(info->iftype));
113
114         g_variant_builder_add(builder, "{sv}", "rst_state",
115                               g_variant_new_uint16(info->rst_state));
116
117         g_variant_builder_add(builder, "{sv}", "rcv_limit",
118                               g_variant_new_int64(info->rcv_limit));
119
120         g_variant_builder_add(builder, "{sv}", "send_limit",
121                               g_variant_new_int64(info->send_limit));
122
123         g_variant_builder_add(builder, "{sv}", "rcv_warn_limit",
124                               g_variant_new_int64(info->rcv_warn_limit));
125
126         g_variant_builder_add(builder, "{sv}", "send_warn_limit",
127                               g_variant_new_int64(info->send_warn_limit));
128
129         g_variant_builder_add(builder, "{sv}", "roaming",
130                               g_variant_new_uint16(info->roaming));
131
132         g_variant_builder_add(builder, "{sv}", "imsi",
133                               g_variant_new_string(info->imsi));
134
135         __STC_LOG_FUNC_EXIT__;
136 }
137
138 stc_cb_ret_e __table_restrictions_foreach_app_cb(const table_restrictions_info *info,
139                                                  void *user_data)
140 {
141         __STC_LOG_FUNC_ENTER__;
142         GVariantBuilder *builder = (GVariantBuilder *)user_data;
143         GVariantBuilder sub_builder;
144
145         if (!info || !builder) {
146                 __STC_LOG_FUNC_EXIT__;
147                 return STC_CANCEL;
148         }
149
150         g_variant_builder_init(&sub_builder, G_VARIANT_TYPE("a{sv}"));
151         __stc_restriction_app_info_builder_add(&sub_builder, info);
152
153         g_variant_builder_add_value(builder,
154                                     g_variant_builder_end(&sub_builder));
155
156         __STC_LOG_FUNC_EXIT__;
157         return STC_CONTINUE;
158 }
159
160 stc_cb_ret_e __table_restrictions_per_app_cb(const table_restrictions_info *info,
161                                              void *user_data)
162 {
163         __STC_LOG_FUNC_ENTER__;
164         GVariantBuilder *builder = (GVariantBuilder *)user_data;
165
166         if (!info || !builder) {
167                 __STC_LOG_FUNC_EXIT__;
168                 return STC_CANCEL;
169         }
170
171         __stc_restriction_app_info_builder_add(builder, info);
172
173         __STC_LOG_FUNC_EXIT__;
174         return STC_CONTINUE;
175 }
176
177 static void __stc_extract_restriction_rule(const char *key, GVariant *value,
178                                            void *user_data)
179 {
180         __STC_LOG_FUNC_ENTER__;
181
182         table_restrictions_info *rule =
183                 (table_restrictions_info *) user_data;
184         if (rule == NULL) {
185                 __STC_LOG_FUNC_EXIT__;
186                 return;
187         }
188
189         if (!g_strcmp0(key, "app_id")) {
190                 guint str_length;
191                 const gchar *str = g_variant_get_string(value, &str_length);
192                 rule->app_id = g_strdup(str);
193                 STC_LOGD("app_id: [%s]", (unsigned int) rule->app_id);
194
195         } else if (!g_strcmp0(key, "ifname")) {
196                 guint str_length;
197                 const gchar *str = g_variant_get_string(value, &str_length);
198                 rule->ifname = g_strdup(str);
199                 STC_LOGD("ifname: [%s]", rule->ifname);
200
201         } else if (!g_strcmp0(key, "iftype")) {
202                 rule->iftype = g_variant_get_uint16(value);
203                 STC_LOGD("iftype: [%u]", (unsigned int) rule->iftype);
204
205         } else if (!g_strcmp0(key, "rcv_limit")) {
206                 rule->rcv_limit = g_variant_get_uint64(value);
207                 STC_LOGD("rcv_limit: [%lld]", rule->rcv_limit);
208
209         } else if (!g_strcmp0(key, "send_limit")) {
210                 rule->send_limit = g_variant_get_uint64(value);
211                 STC_LOGD("send_limit: [%lld]", rule->send_limit);
212
213         } else if (!g_strcmp0(key, "rcv_warn_limit")) {
214                 rule->rcv_warn_limit = g_variant_get_uint64(value);
215                 STC_LOGD("rcv_warn_limit: [%lld]", rule->rcv_warn_limit);
216
217         } else if (!g_strcmp0(key, "send_warn_limit")) {
218                 rule->send_warn_limit = g_variant_get_uint64(value);
219                 STC_LOGD("send_warn_limit: [%lld]", rule->send_warn_limit);
220
221         } else if (!g_strcmp0(key, "roaming")) {
222                 rule->roaming = g_variant_get_uint16(value);
223                 STC_LOGD("roaming: [%u]", rule->roaming);
224
225         } else if (!g_strcmp0(key, "imsi")) {
226                 guint str_length;
227                 const gchar *str = g_variant_get_string(value, &str_length);
228                 rule->imsi = g_strdup(str);
229                 STC_LOGD("imsi: [%s]", rule->imsi);
230
231         } else {
232                 STC_LOGD("Unknown select rule");
233         }
234
235         __STC_LOG_FUNC_EXIT__;
236 }
237
238 gboolean handle_restriction_set(StcRestriction *object,
239                                 GDBusMethodInvocation *invocation,
240                                 GVariant *parameters,
241                                 void *user_data)
242 {
243         __STC_LOG_FUNC_ENTER__;
244         GVariantIter *iter = NULL;
245         table_restrictions_info rule;
246
247         memset(&rule, 0, sizeof(table_restrictions_info));
248         __initialize_rstn_rule(&rule);
249
250         g_variant_get(parameters, "a{sv}", &iter);
251         if (iter != NULL) {
252                 stc_manager_gdbus_dict_foreach(iter,
253                                                __stc_extract_restriction_rule,
254                                                &rule);
255                 g_variant_iter_free(iter);
256         }
257
258         rule.rst_state = STC_RESTRICTION_REMOVED;
259
260         if (__validate_rstn_rule(&rule, RST_SET) == FALSE) {
261                 STC_RESTRICTION_DBUS_REPLY_ERROR(invocation,
262                                                  STC_ERROR_INVALID_PARAMETER);
263                 __STC_LOG_FUNC_EXIT__;
264                 return TRUE;
265         }
266
267         table_restrictions_update(&rule);
268         /* update restriction rule in runtime structure */
269         stc_monitor_rstns_tree_add(&rule);
270
271         STC_DBUS_REPLY_ERROR_NONE(invocation);
272         __STC_LOG_FUNC_EXIT__;
273         return TRUE;
274 }
275
276 gboolean handle_restriction_exclude(StcRestriction *object,
277                                     GDBusMethodInvocation *invocation,
278                                     GVariant *parameters,
279                                     void *user_data)
280 {
281         __STC_LOG_FUNC_ENTER__;
282         GVariantIter *iter = NULL;
283         table_restrictions_info rule;
284
285         memset(&rule, 0, sizeof(table_restrictions_info));
286         __initialize_rstn_rule(&rule);
287
288         g_variant_get(parameters, "a{sv}", &iter);
289         if (iter != NULL) {
290                 stc_manager_gdbus_dict_foreach(iter,
291                                                __stc_extract_restriction_rule,
292                                                &rule);
293                 g_variant_iter_free(iter);
294         }
295
296         rule.rst_state = STC_RESTRICTION_EXCLUDED;
297
298         if (__validate_rstn_rule(&rule, RST_EXCLUDE) == FALSE) {
299                 STC_RESTRICTION_DBUS_REPLY_ERROR(invocation,
300                                                  STC_ERROR_INVALID_PARAMETER);
301                 __STC_LOG_FUNC_EXIT__;
302                 return TRUE;
303         }
304
305         table_restrictions_update(&rule);
306         /* update restriction rule in runtime structure */
307         stc_monitor_rstns_tree_add(&rule);
308
309         STC_DBUS_REPLY_ERROR_NONE(invocation);
310         __STC_LOG_FUNC_EXIT__;
311         return TRUE;
312 }
313
314 gboolean handle_restriction_remove(StcRestriction *object,
315                                    GDBusMethodInvocation *invocation,
316                                    GVariant *parameters,
317                                    void *user_data)
318 {
319         __STC_LOG_FUNC_ENTER__;
320         GVariantIter *iter = NULL;
321         table_restrictions_info rule;
322
323         memset(&rule, 0, sizeof(table_restrictions_info));
324         __initialize_rstn_rule(&rule);
325
326         g_variant_get(parameters, "a{sv}", &iter);
327         if (iter != NULL) {
328                 stc_manager_gdbus_dict_foreach(iter,
329                                                __stc_extract_restriction_rule,
330                                                &rule);
331                 g_variant_iter_free(iter);
332         }
333
334         if (__validate_rstn_rule(&rule, RST_UNSET) == FALSE) {
335                 STC_RESTRICTION_DBUS_REPLY_ERROR(invocation,
336                                                  STC_ERROR_INVALID_PARAMETER);
337                 __STC_LOG_FUNC_EXIT__;
338                 return TRUE;
339         }
340
341         table_restrictions_delete(rule.app_id, rule.iftype, rule.imsi);
342         /* remove restriction rule from runtime structure */
343         stc_monitor_rstns_tree_remove(&rule);
344
345         STC_DBUS_REPLY_ERROR_NONE(invocation);
346         __STC_LOG_FUNC_EXIT__;
347         return TRUE;
348 }
349
350 gboolean handle_restriction_get(StcRestriction *object,
351                                 GDBusMethodInvocation *invocation,
352                                 const gchar *app_id,
353                                 void *user_data)
354 {
355         __STC_LOG_FUNC_ENTER__;
356         GVariantBuilder *builder = NULL;
357         GVariant *return_parameters = NULL;
358         stc_error_e ret;
359
360         builder = g_variant_builder_new(G_VARIANT_TYPE("a{sv}"));
361
362         ret = table_restrictions_per_app(app_id,
363                                          __table_restrictions_per_app_cb,
364                                          builder);
365         if (ret < STC_ERROR_NONE) {
366                 g_variant_builder_unref(builder);
367                 STC_RESTRICTION_DBUS_REPLY_ERROR(invocation, ret);
368                 __STC_LOG_FUNC_EXIT__;
369                 return TRUE;
370         }
371
372         return_parameters = g_variant_new("(ia{sv})", STC_ERROR_NONE, builder);
373         g_variant_builder_unref(builder);
374
375         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
376         STC_DBUS_REPLY(invocation, return_parameters);
377         __STC_LOG_FUNC_EXIT__;
378         return TRUE;
379 }
380
381 gboolean handle_restriction_get_all(StcRestriction *object,
382                                     GDBusMethodInvocation *invocation,
383                                     void *user_data)
384 {
385         __STC_LOG_FUNC_ENTER__;
386         GVariantBuilder *builder = NULL;
387         GVariant *return_parameters = NULL;
388         stc_error_e ret;
389
390         builder = g_variant_builder_new(G_VARIANT_TYPE("aa{sv}"));
391
392         ret = table_restrictions_foreach(__table_restrictions_foreach_app_cb,
393                                          builder);
394         if (ret < STC_ERROR_NONE) {
395                 g_variant_builder_unref(builder);
396                 STC_RESTRICTION_DBUS_REPLY_ERROR(invocation, ret);
397                 __STC_LOG_FUNC_EXIT__;
398                 return TRUE;
399         }
400
401         return_parameters = g_variant_new("(iaa{sv})", STC_ERROR_NONE, builder);
402         g_variant_builder_unref(builder);
403
404         DEBUG_GDBUS_VARIANT("Return parameters: ", return_parameters);
405         STC_DBUS_REPLY(invocation, return_parameters);
406         __STC_LOG_FUNC_EXIT__;
407         return TRUE;
408 }
409
410 gboolean handle_restriction_get_state(StcRestriction *object,
411                                       GDBusMethodInvocation *invocation,
412                                       const gchar *app_id,
413                                       int iftype,
414                                       void *user_data)
415 {
416         __STC_LOG_FUNC_ENTER__;
417         GVariant *return_parameters = NULL;
418         stc_restriction_state_e state = STC_RESTRICTION_UNKNOWN;
419         stc_error_e ret;
420
421         ret = table_restrictions_get_restriction_state(app_id, iftype, &state);
422         if (ret < STC_ERROR_NONE) {
423                 STC_RESTRICTION_DBUS_REPLY_ERROR(invocation, ret);
424                 __STC_LOG_FUNC_EXIT__;
425                 return TRUE;
426         }
427
428         return_parameters = g_variant_new("(ii)", STC_ERROR_NONE, state);
429         STC_DBUS_REPLY(invocation, return_parameters);
430         __STC_LOG_FUNC_EXIT__;
431         return TRUE;
432 }