mirror of
https://github.com/ntop/ntopng.git
synced 2026-05-13 05:51:46 +00:00
257 lines
7.6 KiB
C++
257 lines
7.6 KiB
C++
/*
|
|
*
|
|
* (C) 2013-24 - ntop.org
|
|
*
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify
|
|
* it under the terms of the GNU General Public License as published by
|
|
* the Free Software Foundation; either version 3 of the License, or
|
|
* (at your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful,
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
|
* GNU General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
|
|
*
|
|
*/
|
|
|
|
#include "ntop_includes.h"
|
|
|
|
/* *************************************** */
|
|
|
|
MostVisitedList::MostVisitedList(u_int32_t _max_num_items) {
|
|
if(trace_new_delete) ntop->getTrace()->traceEvent(TRACE_NORMAL, "[new] %s", __FILE__);
|
|
top_data = new (std::nothrow) FrequentStringItems(_max_num_items);
|
|
old_data = shadow_old_data = NULL;
|
|
max_num_items = _max_num_items;
|
|
current_cycle = 0;
|
|
}
|
|
|
|
/* *************************************** */
|
|
|
|
MostVisitedList::~MostVisitedList() {
|
|
if(trace_new_delete) ntop->getTrace()->traceEvent(TRACE_NORMAL, "[delete] %s", __FILE__);
|
|
if (top_data) delete (top_data);
|
|
if (old_data) free(old_data);
|
|
if (shadow_old_data) free(shadow_old_data);
|
|
}
|
|
|
|
/* *************************************** */
|
|
|
|
void MostVisitedList::getCurrentTime(struct tm *t_now) {
|
|
time_t now = time(NULL);
|
|
|
|
memset(t_now, 0, sizeof(*t_now));
|
|
localtime_r(&now, t_now);
|
|
}
|
|
|
|
/* *************************************** */
|
|
|
|
void MostVisitedList::saveOldData(u_int32_t iface_id, char *additional_key_info,
|
|
char *hashkey) {
|
|
char redis_key[64];
|
|
int minute = 0;
|
|
struct tm t_now;
|
|
|
|
// Using a shadow due to a possible segv while freeing
|
|
// old_data and getting stats from lua
|
|
if (shadow_old_data) {
|
|
free(shadow_old_data);
|
|
shadow_old_data = NULL;
|
|
}
|
|
|
|
if (!ntop->getRedis()) return;
|
|
|
|
/* Still no old data collected */
|
|
if (!old_data) {
|
|
old_data = top_data->json();
|
|
return;
|
|
}
|
|
|
|
getCurrentTime(&t_now);
|
|
minute = t_now.tm_min - (t_now.tm_min % 5);
|
|
|
|
snprintf(redis_key, sizeof(redis_key), "%s%s_%d_%d_%d_%d",
|
|
(char *)NTOPNG_CACHE_PREFIX, additional_key_info, iface_id,
|
|
t_now.tm_mday, t_now.tm_hour, minute);
|
|
|
|
/* String like `ntopng.cache.1_17_11_45` */
|
|
/* An other way is to use the localtime_r and compose the string like
|
|
* `ntopng.cache_2_1609761600` */
|
|
|
|
ntop->getRedis()->set(redis_key, old_data, 7200);
|
|
|
|
if (minute == 0 && current_cycle > 0) {
|
|
char hour_done[64];
|
|
int hour = 0;
|
|
|
|
if (t_now.tm_hour == 0)
|
|
hour = 23;
|
|
else
|
|
hour = t_now.tm_hour - 1;
|
|
|
|
/* List key = ntopng.cache.top_sites_hour_done | value = 1_17_11 */
|
|
snprintf(hour_done, sizeof(hour_done), "%d_%d_%d", iface_id, t_now.tm_mday,
|
|
hour);
|
|
|
|
ntop->getRedis()->lpush(hashkey, hour_done, 0);
|
|
|
|
current_cycle = 0;
|
|
} else
|
|
current_cycle++;
|
|
|
|
shadow_old_data = old_data;
|
|
old_data = top_data->json();
|
|
}
|
|
|
|
/* *************************************** */
|
|
|
|
void MostVisitedList::lua(lua_State *vm, char *name, char *old_name) {
|
|
FrequentStringItems *cur_top_data = top_data;
|
|
char *cur_old_data = old_data;
|
|
|
|
if (cur_top_data) {
|
|
char *cur_top_data_json = cur_top_data->json();
|
|
|
|
if (cur_top_data_json) {
|
|
lua_push_str_table_entry(vm, name, cur_top_data_json);
|
|
free(cur_top_data_json);
|
|
}
|
|
}
|
|
|
|
if (cur_old_data) lua_push_str_table_entry(vm, old_name, cur_old_data);
|
|
}
|
|
|
|
/* *************************************** */
|
|
|
|
void MostVisitedList::serializeDeserialize(u_int32_t iface_id,
|
|
bool do_serialize, char *extra_info,
|
|
char *info_subject,
|
|
char *hour_hashkey,
|
|
char *day_hashkey) {
|
|
struct tm t_now;
|
|
char redis_hour_key[64], redis_daily_key[64], redis_key_current_data[64];
|
|
|
|
if (!top_data) return;
|
|
|
|
/* Struct containing the current time */
|
|
getCurrentTime(&t_now);
|
|
|
|
/* Formatting the hour and daily redis key */
|
|
snprintf(redis_hour_key, sizeof(redis_hour_key), "%s%u_%d_%u", extra_info,
|
|
iface_id, t_now.tm_mday, t_now.tm_hour);
|
|
snprintf(redis_daily_key, sizeof(redis_daily_key), "%s%u_%d", extra_info,
|
|
iface_id, t_now.tm_mday);
|
|
|
|
snprintf(redis_key_current_data, sizeof(redis_key_current_data), "%s%s%d_%d",
|
|
(char *)NTOPNG_CACHE_PREFIX, info_subject, iface_id, t_now.tm_mday);
|
|
|
|
/* Serialize the data */
|
|
if (do_serialize) {
|
|
ntop->getRedis()->lpush(hour_hashkey, redis_hour_key, 0);
|
|
ntop->getRedis()->lpush(day_hashkey, redis_daily_key, 0);
|
|
if (top_data->getSize()) {
|
|
/* Serialize the double of the max value */
|
|
char *top_data_json = top_data->json(2 * max_num_items);
|
|
|
|
if (top_data_json) {
|
|
ntop->getRedis()->set(redis_key_current_data, top_data_json, 3600);
|
|
free(top_data_json);
|
|
}
|
|
}
|
|
}
|
|
/* Deserialize the data */
|
|
else {
|
|
ntop->getRedis()->lrem(hour_hashkey, redis_hour_key);
|
|
ntop->getRedis()->lrem(day_hashkey, redis_daily_key);
|
|
deserializeTopData(redis_key_current_data);
|
|
ntop->getRedis()->del(redis_key_current_data);
|
|
}
|
|
}
|
|
|
|
/* *************************************** */
|
|
|
|
void MostVisitedList::deserializeTopData(char *redis_key_current) {
|
|
char *json;
|
|
u_int json_len;
|
|
json_object *j;
|
|
enum json_tokener_error jerr;
|
|
|
|
json_len = ntop->getRedis()->len(redis_key_current);
|
|
if (json_len == 0)
|
|
json_len = CONST_MAX_LEN_REDIS_VALUE;
|
|
else
|
|
json_len += 8; /* Little overhead */
|
|
|
|
if ((json = (char *)malloc(json_len)) == NULL) {
|
|
ntop->getTrace()->traceEvent(TRACE_WARNING, "Not enough memory");
|
|
return;
|
|
}
|
|
|
|
if ((ntop->getRedis()->get(redis_key_current, json, json_len) == -1) ||
|
|
(json[0] == '\0')) {
|
|
free(json);
|
|
return; /* Nothing found */
|
|
}
|
|
|
|
j = json_tokener_parse_verbose(json, &jerr);
|
|
|
|
if (j != NULL) {
|
|
#ifdef DEBUG
|
|
ntop->getTrace()->traceEvent(TRACE_NORMAL, "%s [%u]", json, json_len);
|
|
#endif
|
|
|
|
if (json_object_get_type(j) == json_type_object) {
|
|
struct lh_entry *entry = json_object_get_object(j)->head;
|
|
|
|
for (; entry != NULL; entry = entry->next) {
|
|
char *key = (char *)entry->k;
|
|
struct json_object *val = (struct json_object *)entry->v;
|
|
enum json_type type = json_object_get_type(val);
|
|
|
|
if (type == json_type_int) {
|
|
u_int32_t value = json_object_get_int64(val);
|
|
|
|
#ifdef DEBUG
|
|
ntop->getTrace()->traceEvent(TRACE_NORMAL, "%s = %u", key, value);
|
|
#endif
|
|
|
|
incrVisitedData(key, value);
|
|
}
|
|
}
|
|
} else
|
|
ntop->getTrace()->traceEvent(
|
|
TRACE_WARNING, "Invalid JSON content for key %s", redis_key_current);
|
|
|
|
json_object_put(j); /* Free memory */
|
|
} else
|
|
ntop->getTrace()->traceEvent(TRACE_NORMAL, "Deserialization Error: %s",
|
|
json);
|
|
|
|
free(json);
|
|
}
|
|
|
|
/* *************************************** */
|
|
|
|
void MostVisitedList::resetTopSitesData(u_int32_t iface_id, char *extra_info,
|
|
char *hashkey) {
|
|
char redis_reset_key[256];
|
|
|
|
int minute = 0;
|
|
struct tm t_now;
|
|
|
|
if (!ntop->getRedis()) return;
|
|
|
|
getCurrentTime(&t_now);
|
|
minute = t_now.tm_min - (t_now.tm_min % 5);
|
|
|
|
snprintf(redis_reset_key, sizeof(redis_reset_key), "%s%u_%d_%u_%d",
|
|
extra_info, iface_id, t_now.tm_mday, t_now.tm_hour, minute);
|
|
ntop->getRedis()->lpush(hashkey, redis_reset_key, 0);
|
|
}
|
|
|
|
/* *************************************** */
|