From: hyunuktak Date: Wed, 11 Jul 2018 09:11:42 +0000 (+0900) Subject: Added data limits monitoring for daily, weekly and monthly X-Git-Tag: accepted/tizen/unified/20180717.063039~2 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;ds=sidebyside;h=1b21d2dd6e6a51192bad23b595cebdbd810bffd2;p=platform%2Fcore%2Fconnectivity%2Fstc-manager.git Added data limits monitoring for daily, weekly and monthly Change-Id: Ibc94757d36210c9167ebe4ddb7c36053d13f60fd Signed-off-by: hyunuktak --- diff --git a/data/traffic_db.sql b/data/traffic_db.sql index 1444598..cd06f8d 100644 --- a/data/traffic_db.sql +++ b/data/traffic_db.sql @@ -24,7 +24,11 @@ CREATE TABLE IF NOT EXISTS restrictions ( roaming INT, subscriber_id TEXT NOT NULL, data_limit BIGINT, - data_warn_limit BIGINT + data_warn_limit BIGINT, + monthly_limit BIGINT, + weekly_limit BIGINT, + daily_limit BIGINT, + month_start_date INT ); CREATE INDEX IF NOT EXISTS restrictions_index ON restrictions (binpath, iftype, ifname); @@ -32,5 +36,13 @@ CREATE INDEX IF NOT EXISTS restrictions_index ON restrictions (binpath, iftype, CREATE TABLE IF NOT EXISTS counters ( restriction_id INTEGER NOT NULL, data_counter BIGINT, + warn_counter BIGINT, + monthly_counter BIGINT, + weekly_counter BIGINT, + daily_counter BIGINT, + month_start_date INT, + month_start_ts BIGINT, + week_start_ts BIGINT, + day_start_ts BIGINT, PRIMARY KEY (restriction_id) ); diff --git a/packaging/stc-manager.spec b/packaging/stc-manager.spec index 9fe0c3c..bcad233 100644 --- a/packaging/stc-manager.spec +++ b/packaging/stc-manager.spec @@ -1,6 +1,6 @@ Name: stc-manager Summary: STC(Smart Traffic Control) manager -Version: 0.0.69 +Version: 0.0.70 Release: 0 Group: Network & Connectivity/Other License: Apache-2.0 diff --git a/src/database/include/table-counters.h b/src/database/include/table-counters.h index a0ef60d..5faff83 100644 --- a/src/database/include/table-counters.h +++ b/src/database/include/table-counters.h @@ -20,6 +20,14 @@ typedef struct { uint64_t restriction_id; int64_t data_counter; + int64_t warn_counter; + int64_t monthly_counter; + int64_t weekly_counter; + int64_t daily_counter; + int32_t month_start_date; + int64_t month_start_ts; + int64_t week_start_ts; + int64_t day_start_ts; } table_counters_info; typedef stc_cb_ret_e(*table_counters_info_cb)(const table_counters_info *info, @@ -30,7 +38,10 @@ stc_error_e table_counters_get(uint64_t restriction_id, stc_error_e table_counters_update_counters(const table_counters_info *info); -stc_error_e table_counters_insert(const table_counters_info *info); +stc_error_e table_counters_get_timestamps(uint64_t restriction_id, + table_counters_info *info); + +stc_error_e table_counters_update_timestamps(const table_counters_info *info); stc_error_e table_counters_delete(uint64_t restriction_id); diff --git a/src/database/include/table-restrictions.h b/src/database/include/table-restrictions.h index 77793d1..ea36988 100644 --- a/src/database/include/table-restrictions.h +++ b/src/database/include/table-restrictions.h @@ -26,6 +26,10 @@ typedef struct { stc_roaming_type_e roaming; int64_t data_limit; int64_t data_warn_limit; + int64_t monthly_limit; + int64_t weekly_limit; + int64_t daily_limit; + int month_start_date; uint64_t restriction_id; } table_restrictions_info; diff --git a/src/database/tables/table-counters.c b/src/database/tables/table-counters.c index 11c99a4..9aec545 100644 --- a/src/database/tables/table-counters.c +++ b/src/database/tables/table-counters.c @@ -26,13 +26,30 @@ #define DELETE_COUNTER "DELETE FROM counters WHERE restriction_id=?" -#define SELECT_COUNTER "SELECT data_counter FROM counters WHERE restriction_id=?" +#define SELECT_RESTRICTION_ID "SELECT restriction_id FROM counters " \ + " WHERE restriction_id = ?" -#define INSERT_COUNTER "INSERT INTO counters (restriction_id, data_counter) " \ - " VALUES (?, ?)" +#define SELECT_COUNTER "SELECT data_counter, warn_counter, monthly_counter, weekly_counter, daily_counter " \ + " FROM counters WHERE restriction_id = ?" -#define UPDATE_COUNTER "REPLACE INTO counters (restriction_id, data_counter) " \ - " VALUES (?, ?)" +#define UPDATE_COUNTER "UPDATE counters " \ + " SET data_counter = ?, warn_counter = ?, monthly_counter = ?, weekly_counter = ?, daily_counter = ? " \ + " WHERE restriction_id = ?" + +#define INSERT_COUNTER "INSERT INTO counters " \ + " (restriction_id, data_counter, warn_counter, monthly_counter, weekly_counter, daily_counter) " \ + " VALUES (?, ?, ?, ?, ?, ?)" + +#define SELECT_TIMESTAMP "SELECT month_start_date, month_start_ts, week_start_ts, day_start_ts " \ + " FROM counters WHERE restriction_id = ?" + +#define UPDATE_TIMESTAMP "UPDATE counters " \ + " SET month_start_date = ?, month_start_ts = ?, week_start_ts = ?, day_start_ts = ? " \ + " WHERE restriction_id = ?" + +#define INSERT_TIMESTAMP "INSERT INTO counters " \ + " (restriction_id, month_start_date, month_start_ts, week_start_ts, day_start_ts) " \ + " VALUES (?, ?, ?, ?, ?)" static void __finalize_delete(void); @@ -73,6 +90,21 @@ static void __finalize_update(void); } \ } while (0) +static void __finalize_insert(void); + +#define PREPARE_INSERT(stm, query) do { \ + rc = sqlite3_prepare_v2(db, query, -1, &stm, NULL); \ + if (rc != SQLITE_OK) { \ + stm = NULL; \ + __finalize_insert(); \ + STC_LOGE("Failed to prepare \"%s\"query" \ + , query); \ + return rc; \ + } \ + } while (0) + + + #define FINALIZE(stm) do { \ if (stm) { \ sqlite3_finalize(stm); \ @@ -81,8 +113,13 @@ static void __finalize_update(void); } while (0) static sqlite3_stmt *delete_counter; +static sqlite3_stmt *select_restriction_id; static sqlite3_stmt *select_counter; static sqlite3_stmt *update_counter; +static sqlite3_stmt *insert_counter; +static sqlite3_stmt *select_timestamp; +static sqlite3_stmt *update_timestamp; +static sqlite3_stmt *insert_timestamp; static int __prepare_delete(sqlite3 *db) { @@ -123,6 +160,8 @@ static int __prepare_select(sqlite3 *db) } PREPARE_SELECT(select_counter, SELECT_COUNTER); + PREPARE_SELECT(select_timestamp, SELECT_TIMESTAMP); + PREPARE_SELECT(select_restriction_id, SELECT_RESTRICTION_ID); initialized = 1; __STC_LOG_FUNC_EXIT__; @@ -134,6 +173,8 @@ static void __finalize_select(void) __STC_LOG_FUNC_ENTER__; FINALIZE(select_counter); + FINALIZE(select_timestamp); + FINALIZE(select_restriction_id); __STC_LOG_FUNC_EXIT__; } @@ -150,6 +191,7 @@ static int __prepare_update(sqlite3 *db) } PREPARE_UPDATE(update_counter, UPDATE_COUNTER); + PREPARE_UPDATE(update_timestamp, UPDATE_TIMESTAMP); initialized = 1; __STC_LOG_FUNC_EXIT__; @@ -161,10 +203,74 @@ static void __finalize_update(void) __STC_LOG_FUNC_ENTER__; FINALIZE(update_counter); + FINALIZE(update_timestamp); + + __STC_LOG_FUNC_EXIT__; +} + +static int __prepare_insert(sqlite3 *db) +{ + __STC_LOG_FUNC_ENTER__; + int rc; + static int initialized; + + if (initialized) { + __STC_LOG_FUNC_EXIT__; //LCOV_EXCL_LINE + return SQLITE_OK; //LCOV_EXCL_LINE + } + + PREPARE_INSERT(insert_counter, INSERT_COUNTER); + PREPARE_INSERT(insert_timestamp, INSERT_TIMESTAMP); + + initialized = 1; + __STC_LOG_FUNC_EXIT__; + return rc; +} + +static void __finalize_insert(void) +{ + __STC_LOG_FUNC_ENTER__; + + FINALIZE(insert_counter); + FINALIZE(insert_timestamp); __STC_LOG_FUNC_EXIT__; } +static bool __table_counters_is_entry_present(uint64_t restriction_id) +{ + bool ret = FALSE; + int rc; + uint64_t l_restriction_id = -1; + sqlite3_stmt *stmt = select_restriction_id; + + if (sqlite3_bind_int(stmt, 1, restriction_id) != SQLITE_OK) { + ret = FALSE; + __STC_LOG_FUNC_EXIT__; + goto handle_error; + } + + rc = sqlite3_step(stmt); + + switch (rc) { + case SQLITE_DONE: + break; + case SQLITE_ROW: + l_restriction_id = sqlite3_column_int64(stmt, 0); + STC_LOGD("restriction id [%llu]", l_restriction_id); + ret = TRUE; + break; + case SQLITE_ERROR: + default: + STC_LOGE("Failed to get restriction id : %s", + sqlite3_errmsg(stc_db_get_database())); + } + +handle_error: + sqlite3_reset(stmt); + return ret; +} + stc_error_e table_counters_get(uint64_t restriction_id, table_counters_info *info) { @@ -188,6 +294,10 @@ stc_error_e table_counters_get(uint64_t restriction_id, break; case SQLITE_ROW: info->data_counter = sqlite3_column_int64(stmt, 0); + info->warn_counter = sqlite3_column_int64(stmt, 1); + info->monthly_counter = sqlite3_column_int64(stmt, 2); + info->weekly_counter = sqlite3_column_int64(stmt, 3); + info->daily_counter = sqlite3_column_int64(stmt, 4); STC_LOGD("rstn_id [%llu] data_counters [%lld] bytes", restriction_id, info->data_counter); @@ -198,6 +308,7 @@ stc_error_e table_counters_get(uint64_t restriction_id, sqlite3_errmsg(stc_db_get_database())); error_code = STC_ERROR_DB_FAILED; + __STC_LOG_FUNC_EXIT__; } //LCOV_EXCL_STOP } while (rc == SQLITE_ROW); @@ -218,8 +329,15 @@ stc_error_e table_counters_update_counters(const table_counters_info *info) goto handle_error; } + if (__table_counters_is_entry_present(info->restriction_id) == FALSE) + stmt = insert_counter; + DB_ACTION(sqlite3_bind_int64(stmt, 1, info->restriction_id)); DB_ACTION(sqlite3_bind_int64(stmt, 2, info->data_counter)); + DB_ACTION(sqlite3_bind_int64(stmt, 3, info->warn_counter)); + DB_ACTION(sqlite3_bind_int64(stmt, 4, info->monthly_counter)); + DB_ACTION(sqlite3_bind_int64(stmt, 5, info->weekly_counter)); + DB_ACTION(sqlite3_bind_int64(stmt, 6, info->daily_counter)); if (sqlite3_step(stmt) != SQLITE_DONE) { STC_LOGE("Failed to update counter: %s\n", @@ -238,6 +356,90 @@ handle_error: } //LCOV_EXCL_STOP +stc_error_e table_counters_get_timestamps(uint64_t restriction_id, + table_counters_info *info) +{ + stc_error_e error_code = STC_ERROR_NONE; + sqlite3_stmt *stmt = select_timestamp; + int rc; + + if (info == NULL) { + __STC_LOG_FUNC_EXIT__; + goto handle_error; + } + + info->restriction_id = restriction_id; + + DB_ACTION(sqlite3_bind_int64(stmt, 1, restriction_id)); + + do { + rc = sqlite3_step(stmt); + + //LCOV_EXCL_START + switch (rc) { + case SQLITE_DONE: + break; + case SQLITE_ROW: + info->month_start_date = sqlite3_column_int(stmt, 0); + info->month_start_ts = sqlite3_column_int64(stmt, 1); + info->week_start_ts = sqlite3_column_int64(stmt, 2); + info->day_start_ts = sqlite3_column_int64(stmt, 3); + + STC_LOGD("rstn_id [%llu] month_start_date [%d], " + "month_start_ts [%lld], week_start_ts [%lld], " + "day_start_ts [%lld]", restriction_id, + info->month_start_date, info->month_start_ts, + info->week_start_ts, info->day_start_ts); + break; + case SQLITE_ERROR: + default: + STC_LOGE("Failed to enumerate counters: %s\n", + sqlite3_errmsg(stc_db_get_database())); + + error_code = STC_ERROR_DB_FAILED; + __STC_LOG_FUNC_EXIT__; + } + //LCOV_EXCL_STOP + } while (rc == SQLITE_ROW); + +handle_error: + sqlite3_reset(stmt); + return error_code; +} + +//LCOV_EXCL_START +stc_error_e table_counters_update_timestamps(const table_counters_info *info) +{ + stc_error_e error_code = STC_ERROR_NONE; + sqlite3_stmt *stmt = update_timestamp; + + if (__table_counters_is_entry_present(info->restriction_id) == FALSE) + stmt = insert_timestamp; + + DB_ACTION(sqlite3_bind_int64(stmt, 1, info->restriction_id)); + DB_ACTION(sqlite3_bind_int(stmt, 2, info->month_start_date)); + DB_ACTION(sqlite3_bind_int64(stmt, 3, info->month_start_ts)); + DB_ACTION(sqlite3_bind_int64(stmt, 4, info->week_start_ts)); + DB_ACTION(sqlite3_bind_int64(stmt, 5, info->day_start_ts)); + + if (sqlite3_step(stmt) != SQLITE_DONE) { + STC_LOGE("Failed to update timestamps: %s\n", + sqlite3_errmsg(stc_db_get_database())); + error_code = STC_ERROR_DB_FAILED; + __STC_LOG_FUNC_EXIT__; + goto handle_error; + } + + STC_LOGD("Timestamps updated for restriction_id [%llu]", + info->restriction_id); + +handle_error: + sqlite3_reset(stmt); + return error_code; +} +//LCOV_EXCL_STOP + + stc_error_e table_counters_delete(uint64_t restriction_id) { stc_error_e error_code = STC_ERROR_NONE; @@ -273,6 +475,7 @@ stc_error_e table_counters_prepare(sqlite3 *db) DB_ACTION(__prepare_delete(db)); DB_ACTION(__prepare_select(db)); DB_ACTION(__prepare_update(db)); + DB_ACTION(__prepare_insert(db)); handle_error: __STC_LOG_FUNC_EXIT__; @@ -285,5 +488,6 @@ void table_counters_finalize(void) __finalize_delete(); __finalize_select(); __finalize_update(); + __finalize_insert(); __STC_LOG_FUNC_EXIT__; } diff --git a/src/database/tables/table-restrictions.c b/src/database/tables/table-restrictions.c index 12fa67d..bbbede0 100755 --- a/src/database/tables/table-restrictions.c +++ b/src/database/tables/table-restrictions.c @@ -31,11 +31,13 @@ /* SELECT statements */ #define SELECT_RESTRICTIONS "SELECT binpath, data_limit, " \ " iftype, rstn_type, roaming, ifname, subscriber_id, " \ - " data_warn_limit, restriction_id FROM restrictions" + " data_warn_limit, monthly_limit, weekly_limit, daily_limit, month_start_date, " \ + " restriction_id FROM restrictions" #define SELECT_RESTRICTIONS_PER_APP "SELECT binpath, data_limit, " \ " iftype, rstn_type, roaming, ifname, subscriber_id, " \ - " data_warn_limit, restriction_id " \ + " data_warn_limit, monthly_limit, weekly_limit, daily_limit, month_start_date, " \ + " restriction_id " \ " FROM restrictions INDEXED BY restrictions_index " \ " WHERE binpath = ?" @@ -54,14 +56,16 @@ /* UPDATE statement */ #define UPDATE_NET_RESTRICTIONS "UPDATE restrictions " \ " SET binpath = ?, data_limit = ?, iftype = ?, rstn_type = ?, " \ - " roaming = ?, ifname = ?, subscriber_id = ?, data_warn_limit = ? " \ + " roaming = ?, ifname = ?, subscriber_id = ?, data_warn_limit = ?, " \ + " monthly_limit = ?, weekly_limit = ?, daily_limit = ? " \ " WHERE restriction_id = ?" /* INSERT statement */ #define INSERT_NET_RESTRICTIONS "INSERT INTO restrictions " \ " (binpath, data_limit, iftype, rstn_type, " \ - " roaming, ifname, subscriber_id, data_warn_limit) " \ - " VALUES (?, ?, ?, ?, ?, ?, ?, ?)" + " roaming, ifname, subscriber_id, data_warn_limit, " \ + " monthly_limit, weekly_limit, daily_limit, month_start_date) " \ + " VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" static void __finalize_delete(void); @@ -291,7 +295,10 @@ stc_error_e table_restrictions_per_app(const gchar* app_id, data.ifname = (char *)sqlite3_column_text(stmt, 5); data.subscriber_id = (char *)sqlite3_column_text(stmt, 6); data.data_warn_limit = sqlite3_column_int64(stmt, 7); - data.restriction_id = sqlite3_column_int64(stmt, 8); + data.monthly_limit = sqlite3_column_int64(stmt, 8); + data.weekly_limit = sqlite3_column_int64(stmt, 9); + data.daily_limit = sqlite3_column_int64(stmt, 10); + data.restriction_id = sqlite3_column_int64(stmt, 11); if (restriction_cb(&data, user_data) == STC_CANCEL) rc = SQLITE_DONE; //LCOV_EXCL_LINE @@ -339,7 +346,11 @@ stc_error_e table_restrictions_foreach(const table_restrictions_info_cb restrict data.ifname = (char *)sqlite3_column_text(stmt, 5); data.subscriber_id = (char *)sqlite3_column_text(stmt, 6); data.data_warn_limit = sqlite3_column_int64(stmt, 7); - data.restriction_id = sqlite3_column_int64(stmt, 8); + data.monthly_limit = sqlite3_column_int64(stmt, 8); + data.weekly_limit = sqlite3_column_int64(stmt, 9); + data.daily_limit = sqlite3_column_int64(stmt, 10); + data.month_start_date = sqlite3_column_int(stmt, 11); + data.restriction_id = sqlite3_column_int64(stmt, 12); if (restriction_cb(&data, user_data) == STC_CANCEL) rc = SQLITE_DONE; //LCOV_EXCL_LINE @@ -524,9 +535,14 @@ stc_error_e table_restrictions_update(table_restrictions_info *info) DB_ACTION(sqlite3_bind_text(stmt, 7, info->subscriber_id ? info->subscriber_id : "", -1, SQLITE_TRANSIENT)); DB_ACTION(sqlite3_bind_int64(stmt, 8, info->data_warn_limit)); + DB_ACTION(sqlite3_bind_int64(stmt, 9, info->monthly_limit)); + DB_ACTION(sqlite3_bind_int64(stmt, 10, info->weekly_limit)); + DB_ACTION(sqlite3_bind_int64(stmt, 11, info->daily_limit)); if (info->restriction_id) - DB_ACTION(sqlite3_bind_int64(stmt, 9, info->restriction_id)); + DB_ACTION(sqlite3_bind_int64(stmt, 12, info->restriction_id)); + else + DB_ACTION(sqlite3_bind_int64(stmt, 12, info->month_start_date)); if (sqlite3_step(stmt) != SQLITE_DONE) { STC_LOGE("Failed to set network restriction: %s\n", //LCOV_EXCL_LINE diff --git a/src/database/tables/table-statistics.c b/src/database/tables/table-statistics.c index 436c55d..6355f60 100755 --- a/src/database/tables/table-statistics.c +++ b/src/database/tables/table-statistics.c @@ -605,8 +605,7 @@ stc_error_e table_statistics_insert(stc_db_classid_iftype_key *stat_key, SQLITE_STATIC)); DB_ACTION(sqlite3_bind_int(stmt, 2, stat->rcv_count)); DB_ACTION(sqlite3_bind_int(stmt, 3, stat->snd_count)); - DB_ACTION(sqlite3_bind_int64(stmt, 4, - (sqlite3_int64)(last_touch_time))); + DB_ACTION(sqlite3_bind_int64(stmt, 4, (sqlite3_int64)last_touch_time)); DB_ACTION(sqlite3_bind_int(stmt, 5, (int)(stat_key->iftype))); DB_ACTION(sqlite3_bind_int(stmt, 6, (int)(stat->is_roaming))); DB_ACTION(sqlite3_bind_int(stmt, 7, (int)hw_net_protocol_type)); diff --git a/src/helper/helper-nfacct-rule.c b/src/helper/helper-nfacct-rule.c index 1a2d188..90364d3 100755 --- a/src/helper/helper-nfacct-rule.c +++ b/src/helper/helper-nfacct-rule.c @@ -249,7 +249,7 @@ static nfacct_rule_direction convert_to_iotype(int type) static stc_iface_type_e convert_to_iftype(int type) { return (type < STC_IFACE_LAST_ELEM && - type > STC_IFACE_UNKNOWN) ? type : STC_IFACE_UNKNOWN; + type > STC_IFACE_UNKNOWN) ? type : STC_IFACE_UNKNOWN; } bool recreate_counter_by_name(char *cnt_name, nfacct_rule_s *cnt) diff --git a/src/monitor/include/stc-monitor.h b/src/monitor/include/stc-monitor.h index a102ea3..3414c06 100644 --- a/src/monitor/include/stc-monitor.h +++ b/src/monitor/include/stc-monitor.h @@ -29,6 +29,19 @@ #define CONTR_TIMER_INTERVAL 1 /** + * @brief enumeration for data limit types + */ +typedef enum { + STC_RSTN_LIMIT_TYPE_DATA_WARN, + STC_RSTN_LIMIT_TYPE_DATA, + STC_RSTN_LIMIT_TYPE_MONTHLY, + STC_RSTN_LIMIT_TYPE_WEEKLY, + STC_RSTN_LIMIT_TYPE_DAILY, + STC_RSTN_LIMIT_TYPE_MAX +} stc_rstn_limit_type_e; + + +/** * @brief key for processes tree */ typedef struct { @@ -80,12 +93,14 @@ typedef struct { uint32_t classid; stc_rstn_state_e rstn_state; stc_rstn_type_e rstn_type; - int64_t data_limit; - int64_t data_warn_limit; - int64_t data_counter; - gboolean data_limit_reached; - gboolean warn_limit_crossed_notified; - gboolean rstn_limit_crossed_notified; + + int64_t counter[STC_RSTN_LIMIT_TYPE_MAX]; + int64_t limit[STC_RSTN_LIMIT_TYPE_MAX]; + int32_t limit_exceeded; + int32_t limit_notified; + + int month_start_date; + time_t month_start_ts; } stc_rstn_value_s; /** @@ -101,6 +116,10 @@ typedef struct { GTree *apps; /**< monitored applications */ gboolean apps_tree_updated; guint background_state; + time_t last_month_ts; + time_t last_week_ts; + time_t last_day_ts; + int month_start_date; } stc_system_s; /** diff --git a/src/monitor/include/stc-time.h b/src/monitor/include/stc-time.h new file mode 100644 index 0000000..d331bce --- /dev/null +++ b/src/monitor/include/stc-time.h @@ -0,0 +1,24 @@ +/* + * Copyright (c) 2017 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#ifndef __STC_MANAGER_TIME_H__ +#define __STC_MANAGER_TIME_H__ + +time_t stc_time_get_day_start(time_t now); +time_t stc_time_get_week_start(time_t now); +time_t stc_time_get_month_start(time_t now, int month_start_date); + +#endif /* __STC_MANAGER_TIME_H__ */ diff --git a/src/monitor/stc-monitor.c b/src/monitor/stc-monitor.c index 9db1cfb..4210441 100755 --- a/src/monitor/stc-monitor.c +++ b/src/monitor/stc-monitor.c @@ -28,13 +28,23 @@ #include "table-statistics.h" #include "table-counters.h" #include "stc-monitor.h" +#include "stc-time.h" #include "stc-manager-plugin-appstatus.h" #include "stc-manager-plugin-exception.h" +#define GRANULARITY 10 #define MAX_INT_LENGTH 128 #define VCONFKEY_STC_BACKGROUND_STATE "db/stc/background_state" typedef struct { + time_t now; + time_t month_start_ts; + time_t week_start_ts; + time_t day_start_ts; + int is_updated; +} reset_time_limits_context_s; + +typedef struct { stc_app_key_s *app_key; stc_process_key_s *proc_key; gboolean entry_removed; @@ -43,7 +53,7 @@ typedef struct { typedef struct { struct nfacct_rule *counter; int64_t bytes; - gboolean data_limit_reached; + gboolean data_limit_exceeded; } classid_bytes_context_s; static stc_system_s *g_system = NULL; @@ -478,16 +488,31 @@ static void __print_rstn(stc_rstn_key_s *rstn_key, stc_rstn_value_s *rstn_value) STC_LOGI("rstn info => rstn_id [%llu], " "app_id [%s], classid [%u], ifname [%s], " "iftype [%d], rstn_state [%d], rstn_type [%d], " - "limit [ (%lld) bytes], " + "month_start_date [%d], limit [ (%lld) bytes], " "warn_limit [ (%lld) bytes], " - "counter [ (%lld) bytes], " + "monthly_limit [ (%lld) bytes], " + "weekly_limit [ (%lld) bytes], " + "daily_limit [ (%lld) bytes], " + "data_counter [ (%lld) bytes], " + "warn_counter [ (%lld) bytes], " + "monthly_counter [ (%lld) bytes], " + "weekly_counter [ (%lld) bytes], " + "daily_counter [ (%lld) bytes], " "roaming [%d], subscriber_id [%s]", rstn_value->restriction_id, rstn_key->app_id, rstn_value->classid , rstn_key->ifname, rstn_key->iftype, rstn_value->rstn_state, rstn_value->rstn_type, - rstn_value->data_limit, - rstn_value->data_warn_limit, - rstn_value->data_counter, + rstn_value->month_start_date, + rstn_value->limit[STC_RSTN_LIMIT_TYPE_DATA], + rstn_value->limit[STC_RSTN_LIMIT_TYPE_DATA_WARN], + rstn_value->limit[STC_RSTN_LIMIT_TYPE_MONTHLY], + rstn_value->limit[STC_RSTN_LIMIT_TYPE_WEEKLY], + rstn_value->limit[STC_RSTN_LIMIT_TYPE_DAILY], + rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA], + rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN], + rstn_value->counter[STC_RSTN_LIMIT_TYPE_MONTHLY], + rstn_value->counter[STC_RSTN_LIMIT_TYPE_WEEKLY], + rstn_value->counter[STC_RSTN_LIMIT_TYPE_DAILY], rstn_key->roaming, rstn_key->subscriber_id); } @@ -583,11 +608,36 @@ static void __del_iptables_rule(int64_t classid, nfacct_rule_intend intend, __del_ip6tables_out(&counter); } +typedef struct { + time_t month_start_ts; + time_t week_start_ts; + time_t day_start_ts; + int64_t monthly_stat; + int64_t weekly_stat; + int64_t daily_stat; +} cumulative_data_s; + +static stc_cb_ret_e __statistics_info_cb(const table_statistics_info *info, + void *user_data) +{ + cumulative_data_s *stat = (cumulative_data_s *)user_data; + int64_t counters = 0; + + counters = info->cnt.in_bytes + info->cnt.out_bytes; + + stat->monthly_stat += counters; + if (stat->week_start_ts <= info->interval->from) + stat->weekly_stat += counters; + if (stat->day_start_ts <= info->interval->from) + stat->daily_stat += counters; + + return STC_CONTINUE; +} + static void __process_restriction(enum traffic_restriction_type rstn_type, stc_rstn_key_s *rstn_key, stc_rstn_value_s *rstn_value, void *data) { - int64_t effective_data_limit, effective_data_warn_limit; default_connection_s *old_connection = (default_connection_s *)data; default_connection_s *connection = NULL; @@ -610,52 +660,85 @@ static void __process_restriction(enum traffic_restriction_type rstn_type, if (rstn_value->classid <= STC_UNKNOWN_CLASSID) return; - effective_data_limit = rstn_value->data_limit; - effective_data_warn_limit = rstn_value->data_warn_limit; - - if (rstn_type == RST_SET) { - /* TODO: Change this to runtime memory */ + switch (rstn_type) { + case RST_SET: + { + int i; table_counters_info info; + int64_t effective_limit[STC_RSTN_LIMIT_TYPE_MAX] = { 0, }; memset(&info, 0, sizeof(table_counters_info)); - table_counters_get(rstn_value->restriction_id, &info); - - effective_data_limit -= info.data_counter; - effective_data_warn_limit -= info.data_counter; - - if (effective_data_limit < 0) { - effective_data_limit = 0; //LCOV_EXCL_LINE - rstn_value->data_limit_reached = TRUE; //LCOV_EXCL_LINE + rstn_value->limit_exceeded = 0; + + if ((rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA] == 0 && + rstn_value->limit[STC_RSTN_LIMIT_TYPE_DATA] >= 0) || + (rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN] == 0 && + rstn_value->limit[STC_RSTN_LIMIT_TYPE_DATA_WARN] >= 0) || + (rstn_value->counter[STC_RSTN_LIMIT_TYPE_MONTHLY] == 0 && + rstn_value->limit[STC_RSTN_LIMIT_TYPE_MONTHLY] >= 0) || + (rstn_value->counter[STC_RSTN_LIMIT_TYPE_WEEKLY] == 0 && + rstn_value->limit[STC_RSTN_LIMIT_TYPE_WEEKLY] >= 0) || + (rstn_value->counter[STC_RSTN_LIMIT_TYPE_DAILY] == 0 && + rstn_value->limit[STC_RSTN_LIMIT_TYPE_DAILY] >= 0)) { + table_counters_get(rstn_value->restriction_id, &info); + + time_t current_time = 0; + cumulative_data_s stat; + table_statistics_select_rule rule; + + memset(&stat, 0, sizeof(cumulative_data_s)); + stat.month_start_ts = rstn_value->month_start_ts; + stat.week_start_ts = g_system->last_week_ts; + stat.week_start_ts = g_system->last_day_ts; + + memset(&rule, 0, sizeof(table_statistics_select_rule)); + rule.from = rstn_value->month_start_ts; + time(¤t_time); + rule.to = current_time; + rule.iftype = rstn_key->iftype; + rule.granularity = GRANULARITY; + + table_statistics_per_app(rstn_key->app_id, &rule, __statistics_info_cb, &stat); + + rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA] = info.data_counter; + rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN] = info.warn_counter; + rstn_value->counter[STC_RSTN_LIMIT_TYPE_MONTHLY] = info.monthly_counter + stat.monthly_stat; + rstn_value->counter[STC_RSTN_LIMIT_TYPE_WEEKLY] = info.weekly_counter + stat.weekly_stat; + rstn_value->counter[STC_RSTN_LIMIT_TYPE_DAILY] = info.daily_counter + stat.daily_stat; } - if (effective_data_warn_limit < 0) - effective_data_warn_limit = 0; //LCOV_EXCL_LINE + for (i = 0; i < STC_RSTN_LIMIT_TYPE_MAX; i++) { + if (rstn_value->limit[i] >= 0) { + effective_limit[i] = rstn_value->limit[i] - rstn_value->counter[i]; - STC_LOGD("datausage [%lld] bytes", info.data_counter); - } + if (effective_limit[i] < 0) + rstn_value->limit_exceeded |= (1 << i); + } + } - STC_LOGD("rstn_id [%llu], effective_data_limit [%lld] bytes, " - "effective_data_warn_limit [%lld] bytes", - rstn_value->restriction_id, effective_data_limit, - effective_data_warn_limit); + STC_LOGD("rstn_id [%llu], datausage [%llu] bytes", + rstn_value->restriction_id, info.data_counter); - switch (rstn_type) { - case RST_SET: - if (effective_data_limit <= 0) - __add_iptables_rule(rstn_value->classid, NFACCT_BLOCK, - rstn_key->iftype); + if (rstn_value->limit_exceeded != 0 && + rstn_value->limit_exceeded != (1 << STC_RSTN_LIMIT_TYPE_DATA_WARN)) { + __add_iptables_rule(rstn_value->classid, NFACCT_BLOCK, rstn_key->iftype); + } rstn_value->rstn_state = STC_RSTN_STATE_ACTIVATED; - rstn_value->data_limit_reached = FALSE; - break; + } + break; case RST_EXCLUDE: __add_iptables_rule(rstn_value->classid, NFACCT_ALLOW, rstn_key->iftype); rstn_value->rstn_state = STC_RSTN_STATE_ACTIVATED; - rstn_value->data_limit_reached = TRUE; + rstn_value->limit_exceeded = 0; + rstn_value->limit_notified = 0; break; case RST_UNSET: + { + int i; + if (rstn_value->classid == STC_TETHERING_APP_CLASSID) __del_iptables_rule(rstn_value->classid, NFACCT_BLOCK, rstn_key->iftype); @@ -664,8 +747,14 @@ static void __process_restriction(enum traffic_restriction_type rstn_type, rstn_key->iftype); rstn_value->rstn_state = STC_RSTN_STATE_DEACTIVATED; - rstn_value->data_limit_reached = FALSE; - break; + rstn_value->limit_exceeded = 0; + rstn_value->limit_notified = 0; + + for (i = 0; i < STC_RSTN_LIMIT_TYPE_MAX; i++) + if (rstn_value->limit[i] >= 0) + rstn_value->counter[i] = 0; + } + break; default: ;//Do Nothing } @@ -796,79 +885,121 @@ static stc_error_e __close_and_reopen_contr_sock(stc_system_s *system) return STC_ERROR_NONE; } +static void __action_when_rstn_limit_exceeded(stc_rstn_limit_type_e limit_type, + stc_rstn_key_s *rstn_key, + stc_rstn_value_s *rstn_value, + classid_bytes_context_s *context) +{ + gboolean rv; + char iftype[MAX_INT_LENGTH]; + char byte[MAX_INT_LENGTH]; + const char *signal_name; + stc_s *stc = (stc_s *)stc_get_manager(); + + if (stc == NULL) { + STC_LOGE("Failed to get stc data"); + return; + } + + switch (limit_type) { + case STC_RSTN_LIMIT_TYPE_DATA_WARN: + { + signal_name = "WarnThresholdCrossed"; + + snprintf(iftype, MAX_INT_LENGTH, "%d", rstn_key->iftype); + snprintf(byte, MAX_INT_LENGTH, "%lld", rstn_value->limit[limit_type]); + stc_plugin_appstatus_send_warn_message("warn threshold crossed", + "warning_noti", + rstn_key->app_id, + iftype, byte); + } + break; + case STC_RSTN_LIMIT_TYPE_DATA: + case STC_RSTN_LIMIT_TYPE_MONTHLY: + case STC_RSTN_LIMIT_TYPE_WEEKLY: + case STC_RSTN_LIMIT_TYPE_DAILY: + { + signal_name = "RestrictionThresholdCrossed"; + + /* block immediately */ + context->counter->intend = NFACCT_BLOCK; + __del_iptables_in(context->counter); + __del_iptables_out(context->counter); + __add_iptables_in(context->counter); + __add_iptables_out(context->counter); + + __del_ip6tables_in(context->counter); + __del_ip6tables_out(context->counter); + __add_ip6tables_in(context->counter); + __add_ip6tables_out(context->counter); + context->counter->intend = NFACCT_COUNTER; + + rstn_value->limit_exceeded |= (1 << limit_type); + + snprintf(iftype, MAX_INT_LENGTH, "%d", rstn_key->iftype); + snprintf(byte, MAX_INT_LENGTH, "%lld", rstn_value->limit[limit_type]); + stc_plugin_appstatus_send_restriction_message("restriction threshold crossed", + "restriction_noti", + rstn_key->app_id, + iftype, byte); + } + break; + default: + break; + } + + /* emit signal */ + rv = stc_manager_dbus_emit_signal(stc->connection, + STC_DBUS_SERVICE_RESTRICTION_PATH, + STC_DBUS_INTERFACE_RESTRICTION, + signal_name, + g_variant_new("(si)", + rstn_key->app_id, + rstn_key->iftype)); + + if (rv == TRUE) + rstn_value->limit_notified |= (1 << limit_type); +} + static gboolean __rstn_counter_update(stc_rstn_key_s *rstn_key, stc_rstn_value_s *rstn_value, classid_bytes_context_s *context) { + int i; switch (context->counter->iotype) { case NFACCT_COUNTER_IN: case NFACCT_COUNTER_OUT: - rstn_value->data_counter += context->bytes; - - if (rstn_value->data_counter >= rstn_value->data_warn_limit && - rstn_value->warn_limit_crossed_notified == FALSE) { - - gboolean rv; - char iftype[MAX_INT_LENGTH]; - char byte[MAX_INT_LENGTH]; - stc_s *stc = (stc_s *)stc_get_manager(); - ret_value_msg_if(stc == NULL, FALSE, "failed to get stc data"); - - /* emit signal */ - rv = stc_manager_dbus_emit_signal(stc->connection, - STC_DBUS_SERVICE_RESTRICTION_PATH, - STC_DBUS_INTERFACE_RESTRICTION, - "WarnThresholdCrossed", - g_variant_new("(si)", rstn_key->app_id, rstn_key->iftype)); - if (rv == TRUE) - rstn_value->warn_limit_crossed_notified = TRUE; - - snprintf(iftype, MAX_INT_LENGTH, "%d", rstn_key->iftype); - snprintf(byte, MAX_INT_LENGTH, "%lld", rstn_value->data_warn_limit); - stc_plugin_appstatus_send_warn_message("warn threshold crossed", - "warning_noti", - rstn_key->app_id, - iftype, byte); + if ((rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA] == 0 && + rstn_value->limit[STC_RSTN_LIMIT_TYPE_DATA] >= 0) || + (rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN] == 0 && + rstn_value->limit[STC_RSTN_LIMIT_TYPE_DATA_WARN] >= 0) || + (rstn_value->counter[STC_RSTN_LIMIT_TYPE_MONTHLY] == 0 && + rstn_value->limit[STC_RSTN_LIMIT_TYPE_MONTHLY] >= 0) || + (rstn_value->counter[STC_RSTN_LIMIT_TYPE_WEEKLY] == 0 && + rstn_value->limit[STC_RSTN_LIMIT_TYPE_WEEKLY] >= 0) || + (rstn_value->counter[STC_RSTN_LIMIT_TYPE_DAILY] == 0 && + rstn_value->limit[STC_RSTN_LIMIT_TYPE_DAILY] >= 0)) { + table_counters_info info; + memset(&info, 0, sizeof(table_counters_info)); + table_counters_get(rstn_value->restriction_id, &info); + + rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA] = info.data_counter; + rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN] = info.warn_counter; + rstn_value->counter[STC_RSTN_LIMIT_TYPE_MONTHLY] = info.monthly_counter; + rstn_value->counter[STC_RSTN_LIMIT_TYPE_WEEKLY] = info.weekly_counter; + rstn_value->counter[STC_RSTN_LIMIT_TYPE_DAILY] = info.daily_counter; } - if (rstn_value->data_counter >= rstn_value->data_limit && - rstn_value->rstn_limit_crossed_notified == FALSE) { - - gboolean rv; - char iftype[MAX_INT_LENGTH]; - char byte[MAX_INT_LENGTH]; - stc_s *stc = (stc_s *)stc_get_manager(); - ret_value_msg_if(stc == NULL, FALSE, "failed to get stc data"); - - /* block immediately */ - context->counter->intend = NFACCT_BLOCK; - __del_iptables_in(context->counter); - __del_iptables_out(context->counter); - __add_iptables_in(context->counter); - __add_iptables_out(context->counter); - - __del_ip6tables_in(context->counter); - __del_ip6tables_out(context->counter); - __add_ip6tables_in(context->counter); - __add_ip6tables_out(context->counter); - context->counter->intend = NFACCT_COUNTER; - - rstn_value->data_limit_reached = TRUE; - - /* emit signal */ - rv = stc_manager_dbus_emit_signal(stc->connection, - STC_DBUS_SERVICE_RESTRICTION_PATH, - STC_DBUS_INTERFACE_RESTRICTION, - "RestrictionThresholdCrossed", - g_variant_new("(si)", rstn_key->app_id, rstn_key->iftype)); - if (rv == TRUE) - rstn_value->rstn_limit_crossed_notified = TRUE; - - snprintf(iftype, MAX_INT_LENGTH, "%d", rstn_key->iftype); - snprintf(byte, MAX_INT_LENGTH, "%lld", rstn_value->data_limit); - stc_plugin_appstatus_send_restriction_message("restriction threshold crossed", - "restriction_noti", rstn_key->app_id, - iftype, byte); + for (i = 0; i < STC_RSTN_LIMIT_TYPE_MAX; i++) { + if (rstn_value->limit[i] >= 0 && + !(rstn_value->limit_notified & (1 << i))) { + rstn_value->counter[i] += context->bytes; + if (rstn_value->limit[i] <= rstn_value->counter[i]) + __action_when_rstn_limit_exceeded(i, + rstn_key, + rstn_value, + context); + } } g_system->rstns_tree_updated = TRUE; @@ -919,8 +1050,8 @@ static gboolean __rstn_counter_update_foreach_classid(gpointer key, if (context->counter->intend != NFACCT_COUNTER) goto try_next_callback; - if (rstn_value->data_limit_reached == TRUE) { - context->data_limit_reached = TRUE; //LCOV_EXCL_LINE + if (rstn_value->limit_exceeded == TRUE) { + context->data_limit_exceeded = TRUE; //LCOV_EXCL_LINE goto try_next_callback; //LCOV_EXCL_LINE } @@ -1014,7 +1145,10 @@ static gboolean __update_app_statistics(gpointer key, gpointer value, static gboolean __flush_apps_stats_to_database(gpointer user_data) { time_t current_time = 0; - time(¤t_time); + stc_s *stc = stc_get_manager(); + + if (stc && stc->carg) + current_time = stc->carg->last_run_time; if (g_system->apps_tree_updated == FALSE) return G_SOURCE_REMOVE; @@ -1037,7 +1171,11 @@ static gboolean __update_counter_statistics(gpointer key, gpointer value, stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value; table_counters_info info = { .restriction_id = rstn_value->restriction_id, - .data_counter = rstn_value->data_counter + .data_counter = rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA], + .warn_counter = rstn_value->counter[STC_RSTN_LIMIT_TYPE_DATA_WARN], + .monthly_counter = rstn_value->counter[STC_RSTN_LIMIT_TYPE_MONTHLY], + .weekly_counter = rstn_value->counter[STC_RSTN_LIMIT_TYPE_WEEKLY], + .daily_counter = rstn_value->counter[STC_RSTN_LIMIT_TYPE_DAILY] }; table_counters_update_counters(&info); @@ -1047,7 +1185,11 @@ static gboolean __update_counter_statistics(gpointer key, gpointer value, static gboolean __flush_rstns_counter_to_database(gpointer user_data) { - time_t current_time = time(0); + time_t current_time = 0; + stc_s *stc = stc_get_manager(); + + if (stc && stc->carg) + current_time = stc->carg->last_run_time; if (g_system->rstns_tree_updated == FALSE) return G_SOURCE_REMOVE; @@ -1136,9 +1278,146 @@ try_next_callback: return FALSE; } +static gboolean __reset_time_counter_foreach_rstn(gpointer key, + gpointer value, + gpointer data) +{ + stc_rstn_key_s *rstn_key = (stc_rstn_key_s *)key; + stc_rstn_value_s *rstn_value = (stc_rstn_value_s *)value; + reset_time_limits_context_s *context = (reset_time_limits_context_s *)data; + int i; + time_t now_month_start_ts; + + if (rstn_value->month_start_date == 0) { + table_counters_info info; + memset(&info, 0, sizeof(table_counters_info)); + table_counters_get_timestamps(rstn_value->restriction_id, &info); + + if (info.month_start_date == 0) + rstn_value->month_start_date = 1; + else + rstn_value->month_start_date = info.month_start_date; + rstn_value->month_start_ts = info.month_start_ts; + } + + now_month_start_ts = + stc_time_get_month_start(context->now, + rstn_value->month_start_date); + + if (rstn_value->month_start_ts != now_month_start_ts) { + rstn_value->month_start_ts = now_month_start_ts; + context->month_start_ts = now_month_start_ts; + context->is_updated |= (1 << STC_RSTN_LIMIT_TYPE_MONTHLY); + } + + if (context->is_updated) { + table_counters_info info; + memset(&info, 0, sizeof(table_counters_info)); + + info.restriction_id = rstn_value->restriction_id; + info.month_start_date = rstn_value->month_start_date; + info.month_start_ts = rstn_value->month_start_ts; + info.week_start_ts = context->week_start_ts; + info.day_start_ts = context->day_start_ts; + + table_counters_update_timestamps(&info); + } + + for (i = STC_RSTN_LIMIT_TYPE_MONTHLY; i < STC_RSTN_LIMIT_TYPE_MAX; i++) { + + if ((context->is_updated) & (1 << i)) { + /* reset limit */ + rstn_value->counter[i] = 0; + + if (rstn_value->limit_exceeded & (1 << i)) { + /* remove iptables rule */ + char *default_ifname = stc_default_connection_get_ifname(); + struct nfacct_rule counter; + stc_s *stc = stc_get_manager(); + if (stc == NULL) { + STC_LOGE("Can't get stc data"); + g_free(default_ifname); + goto try_next_callback; + } + + if (!stc->carg) { + stc->carg = MALLOC0(counter_arg_s, 1); + if (stc->carg == NULL) { + g_free(default_ifname); + goto try_next_callback; + } + + stc->carg->sock = + stc_monitor_get_counter_socket(); + } + + counter.carg = stc->carg; + counter.classid = rstn_value->classid; + counter.intend = NFACCT_BLOCK; + counter.iftype = rstn_key->iftype; + g_strlcpy(counter.ifname, default_ifname, + MAX_IFACE_LENGTH); + + g_free(default_ifname); + + /* iptables rule */ + __del_iptables_in(&counter); + __del_iptables_out(&counter); + + /* ip6tables rule */ + __del_ip6tables_in(&counter); + __del_ip6tables_out(&counter); + + rstn_value->rstn_state = STC_RSTN_STATE_DEACTIVATED; + rstn_value->limit_exceeded &= ~(1 << i); + rstn_value->limit_notified &= ~(1 << i); + } + } + } + +try_next_callback: + return FALSE; +} + +static void __reset_time_counters_if_required(void) +{ + reset_time_limits_context_s context; + + if (g_system == NULL) { + STC_LOGE("stc monitor not initialized!"); + return; + } + + context.now = time(NULL); + context.week_start_ts = stc_time_get_week_start(context.now); + context.day_start_ts = stc_time_get_day_start(context.now); + context.is_updated = 0; + + if (g_system->last_week_ts != context.week_start_ts) { + g_system->last_week_ts = context.week_start_ts; + context.is_updated |= (1 << STC_RSTN_LIMIT_TYPE_WEEKLY); + } + + if (g_system->last_day_ts != context.day_start_ts) { + g_system->last_day_ts = context.day_start_ts; + context.is_updated |= (1 << STC_RSTN_LIMIT_TYPE_DAILY); + } + + if (g_system->rstns) { + g_tree_foreach(g_system->rstns, + __reset_time_counter_foreach_rstn, + &context); + if (context.is_updated) + STC_LOGD("Counter reset completed month_start [%ld], week_start [%ld], day_start [%ld]", + context.month_start_ts, g_system->last_week_ts, g_system->last_day_ts); + } +} + static void __fill_nfacct_result(char *cnt_name, int64_t bytes, struct counter_arg *carg) { + __reset_time_counters_if_required(); + struct nfacct_rule counter = { .carg = carg, .name = {0}, @@ -1149,7 +1428,7 @@ static void __fill_nfacct_result(char *cnt_name, int64_t bytes, classid_bytes_context_s context = { .counter = &counter, .bytes = bytes, - .data_limit_reached = FALSE, + .data_limit_exceeded = FALSE, }; if (!recreate_counter_by_name(cnt_name, &counter)) { @@ -1272,6 +1551,8 @@ static gboolean __process_contr_reply(GIOChannel *source, goto out; stc->carg->ans_len = ret; + stc->carg->last_run_time = time(NULL); + __process_network_counter(ans, stc->carg); g_idle_add(__flush_apps_stats_to_database, NULL); @@ -1400,10 +1681,9 @@ static stc_error_e __rstn_tree_remove(stc_rstn_key_s *key) return STC_ERROR_NO_DATA; //LCOV_EXCL_LINE } - __remove_restriction(key, lookup_value, NULL); - /* remove counter also */ table_counters_delete(lookup_value->restriction_id); + __remove_restriction(key, lookup_value, NULL); if (!g_tree_remove(g_system->rstns, key)) { STC_LOGD("key not found"); //LCOV_EXCL_LINE @@ -1450,11 +1730,17 @@ static stc_error_e __rstn_tree_add(stc_rstn_key_s *key, rstn_value->rstn_state = value->rstn_state; rstn_value->rstn_type = value->rstn_type; rstn_value->classid = value->classid; - rstn_value->data_limit = value->data_limit; - rstn_value->data_warn_limit = value->data_warn_limit; - rstn_value->data_counter = 0; - rstn_value->warn_limit_crossed_notified = FALSE; - rstn_value->rstn_limit_crossed_notified = FALSE; + + int i; + for (i = 0; i < STC_RSTN_LIMIT_TYPE_MAX; i++) { + rstn_value->limit[i] = value->limit[i]; + rstn_value->counter[i] = 0; + } + + rstn_value->limit_exceeded = 0; + rstn_value->limit_notified = 0; + rstn_value->month_start_date = value->month_start_date; + rstn_value->month_start_ts = value->month_start_ts; if (debug == TRUE) __add_restriction_debug(key, rstn_value, NULL); @@ -1491,8 +1777,11 @@ static stc_cb_ret_e __insert_restriction_cb(const table_restrictions_info *info, else value.classid = STC_UNKNOWN_CLASSID; - value.data_limit = info->data_limit; - value.data_warn_limit = info->data_warn_limit; + value.limit[STC_RSTN_LIMIT_TYPE_DATA] = info->data_limit; + value.limit[STC_RSTN_LIMIT_TYPE_DATA_WARN] = info->data_warn_limit; + value.limit[STC_RSTN_LIMIT_TYPE_MONTHLY] = info->monthly_limit; + value.limit[STC_RSTN_LIMIT_TYPE_WEEKLY] = info->weekly_limit; + value.limit[STC_RSTN_LIMIT_TYPE_DAILY] = info->daily_limit; if (__rstn_tree_add(&key, &value, FALSE) != STC_ERROR_NONE) ret = STC_CANCEL; @@ -1992,8 +2281,14 @@ stc_error_e stc_monitor_rstns_tree_add(const table_restrictions_info *info) __process_update_background(); //LCOV_EXCL_LINE } - value.data_limit = info->data_limit; - value.data_warn_limit = info->data_warn_limit; + value.limit[STC_RSTN_LIMIT_TYPE_DATA] = info->data_limit; + value.limit[STC_RSTN_LIMIT_TYPE_DATA_WARN] = info->data_warn_limit; + value.limit[STC_RSTN_LIMIT_TYPE_MONTHLY] = info->monthly_limit; + value.limit[STC_RSTN_LIMIT_TYPE_WEEKLY] = info->weekly_limit; + value.limit[STC_RSTN_LIMIT_TYPE_DAILY] = info->daily_limit; + value.month_start_date = info->month_start_date; + value.month_start_ts = stc_time_get_month_start(time(NULL), + info->month_start_date); ret = __rstn_tree_add(&key, &value, TRUE); diff --git a/src/monitor/stc-time.c b/src/monitor/stc-time.c new file mode 100644 index 0000000..750b43d --- /dev/null +++ b/src/monitor/stc-time.c @@ -0,0 +1,104 @@ +/* + * Copyright (c) 2016 Samsung Electronics Co., Ltd. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include + +#define SEC_IN_DAY 24 * 60 * 60 +#define SEC_IN_WEEK 7 * SEC_IN_DAY + +time_t stc_time_get_day_start(time_t now) +{ + struct tm *curr; + + curr = localtime(&now); + + curr->tm_sec = 0; + curr->tm_min = 0; + curr->tm_hour = 0; + + return mktime(curr); +} + +time_t stc_time_get_week_start(time_t now) +{ + struct tm *curr; + int days; + + curr = localtime(&now); + + curr->tm_sec = 0; + curr->tm_min = 0; + curr->tm_hour = 0; + + if (curr->tm_wday > 1) + days = curr->tm_wday - 1; + else + days = 1 - curr->tm_wday; + + return (mktime(curr) - (days * SEC_IN_DAY)); +} + +time_t stc_time_get_month_start(time_t now, int month_start_date) +{ + struct tm *curr; + bool is_leap_year; + + curr = localtime(&now); + + curr->tm_sec = 0; + curr->tm_min = 0; + curr->tm_hour = 0; + + if (curr->tm_mday < month_start_date) { + curr->tm_mon--; + if (curr->tm_mon < 0) { + curr->tm_mon = 11; + curr->tm_year--; + } + } + + is_leap_year = ((curr->tm_year + 1900) % 4 ? 0 : 1); + curr->tm_mday = month_start_date; + + switch (month_start_date) { + case 29: + case 30: + if (curr->tm_mon == 1 && !is_leap_year) + curr->tm_mday = 28; + + else if (curr->tm_mon == 1 && is_leap_year) + curr->tm_mday = 29; + + break; + case 31: + if (curr->tm_mon == 1 && !is_leap_year) + curr->tm_mday = 28; + + else if (curr->tm_mon == 1 && is_leap_year) + curr->tm_mday = 29; + + else if (curr->tm_mon == 3 || curr->tm_mon == 5 || + curr->tm_mon == 8 || curr->tm_mon == 10) + curr->tm_mday = 30; + + break; + default: + ;//Do Nothing + }; + + return mktime(curr); +} diff --git a/src/stc-manager-gdbus.c b/src/stc-manager-gdbus.c index ddad1ef..672909b 100644 --- a/src/stc-manager-gdbus.c +++ b/src/stc-manager-gdbus.c @@ -457,7 +457,7 @@ void stc_manager_gdbus_dict_foreach(GVariantIter *iter, dbus_dict_cb cb, } while (g_variant_iter_loop(iter, "{sv}", &key, &value)) { - DEBUG_GDBUS_KEY_VALUE(key, value); + /* DEBUG_GDBUS_KEY_VALUE(key, value); */ if (key && cb) cb(key, value, user_data); } diff --git a/src/stc-restriction.c b/src/stc-restriction.c index d4353ea..2f44459 100644 --- a/src/stc-restriction.c +++ b/src/stc-restriction.c @@ -46,8 +46,11 @@ void __initialize_rstn_rule(table_restrictions_info *rule) rule->ifname = NULL; rule->iftype = STC_IFACE_ALL; rule->rstn_type = STC_RSTN_TYPE_UNKNOWN; - rule->data_limit = 0; - rule->data_warn_limit = 0; + rule->data_limit = -1; + rule->data_warn_limit = -1; + rule->monthly_limit = -1; + rule->weekly_limit = -1; + rule->daily_limit = -1; rule->roaming = STC_ROAMING_DISABLE; rule->subscriber_id = NULL; } @@ -114,6 +117,18 @@ void __stc_restriction_app_info_builder_add(GVariantBuilder *builder, g_variant_builder_add(builder, "{sv}", "data_warn_limit", g_variant_new_int64(info->data_warn_limit)); + g_variant_builder_add(builder, "{sv}", "month_start_date", + g_variant_new_int32(info->month_start_date)); + + g_variant_builder_add(builder, "{sv}", "monthly_limit", + g_variant_new_int64(info->monthly_limit)); + + g_variant_builder_add(builder, "{sv}", "weekly_limit", + g_variant_new_int64(info->weekly_limit)); + + g_variant_builder_add(builder, "{sv}", "daily_limit", + g_variant_new_int64(info->daily_limit)); + g_variant_builder_add(builder, "{sv}", "roaming", g_variant_new_uint16(info->roaming)); @@ -165,8 +180,6 @@ stc_cb_ret_e __table_restrictions_per_app_cb(const table_restrictions_info *info static void __stc_extract_restriction_rule(const char *key, GVariant *value, void *user_data) { - __STC_LOG_FUNC_ENTER__; - table_restrictions_info *rule = (table_restrictions_info *) user_data; if (rule == NULL) { @@ -198,6 +211,22 @@ static void __stc_extract_restriction_rule(const char *key, GVariant *value, rule->data_warn_limit = g_variant_get_int64(value); STC_LOGD("data_warn_limit: [%lld]", rule->data_warn_limit); + } else if (!g_strcmp0(key, "month_start_date")) { + rule->month_start_date = g_variant_get_int32(value); + STC_LOGD("month_start_date: [%d]", rule->month_start_date); + + } else if (!g_strcmp0(key, "monthly_limit")) { + rule->monthly_limit = g_variant_get_int64(value); + STC_LOGD("monthly_limit: [%lld]", rule->monthly_limit); + + } else if (!g_strcmp0(key, "weekly_limit")) { + rule->weekly_limit = g_variant_get_int64(value); + STC_LOGD("weekly_limit: [%lld]", rule->weekly_limit); + + } else if (!g_strcmp0(key, "daily_limit")) { + rule->daily_limit = g_variant_get_int64(value); + STC_LOGD("daily_limit: [%lld]", rule->daily_limit); + } else if (!g_strcmp0(key, "roaming")) { rule->roaming = g_variant_get_uint16(value); STC_LOGD("roaming: [%u]", rule->roaming); @@ -208,15 +237,13 @@ static void __stc_extract_restriction_rule(const char *key, GVariant *value, rule->subscriber_id = g_strdup(str); STC_LOGD("subscriber_id: [%s]", rule->subscriber_id); - } else if (!g_strcmp0(key, "type")) { + } else if (!g_strcmp0(key, "rstn_type")) { rule->rstn_type = g_variant_get_uint16(value); STC_LOGD("type: [%u]", (unsigned int) rule->rstn_type); } else { STC_LOGD("Unknown select rule"); //LCOV_EXCL_LINE } - - __STC_LOG_FUNC_EXIT__; } gboolean handle_restriction_set(StcRestriction *object,