Files
DenyIP/cache.c
2025-04-23 11:41:06 +08:00

257 lines
7.0 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
#include "cache.h"
struct ip_cache_node *ip_cache_head = NULL; // 缓存链表的头节点
int cache_size = 0; // 当前缓存中的 IP 数量
// 将新 IP 添加到缓存,若缓存过大则移除最早的 IP
void add_ip_to_cache(const char *ip)
{
// 如果缓存大小超过限制,移除最早的 IP
if (cache_size >= MAX_CACHE_SIZE) {
struct ip_cache_node *current = ip_cache_head;
struct ip_cache_node *prev = NULL;
// 找到链表的最后一个节点
while (current->next != NULL) {
prev = current;
current = current->next;
}
// 移除最后一个节点(最早的 IP
if (prev != NULL) {
prev->next = NULL;
} else {
ip_cache_head = NULL;
}
free(current);
cache_size--;
}
// 创建新的缓存节点并添加到链表头部
struct ip_cache_node *new_node = (struct ip_cache_node *)malloc(sizeof(struct ip_cache_node));
if (new_node == NULL) {
perror("malloc");
return;
}
strncpy(new_node->ip, ip, INET_ADDRSTRLEN);
new_node->timestamp = time(NULL); // 记录当前时间
new_node->next = ip_cache_head;
ip_cache_head = new_node;
cache_size++;
}
// 检查 IP 是否已在缓存中并是否过期
int is_ip_in_cache(const char *ip)
{
time_t now = time(NULL); // 获取当前时间
struct ip_cache_node *current = ip_cache_head;
struct ip_cache_node *prev = NULL;
if (ip_cache_head == NULL)
return 0; // 如果 ip_cache_head == NULLcurrent->next 可能导致段错误 (Segmentation Fault)。
while (current != NULL) {
// 如果 IP 匹配并且未过期
if (strcmp(current->ip, ip) == 0) {
if (now - current->timestamp <= CACHE_TTL) {
return 1; // IP 在缓存中,且未过期
} else {
// 如果过期,从链表中移除这个节点
if (prev == NULL) {
ip_cache_head = current->next;
} else {
prev->next = current->next;
}
free(current);
cache_size--;
return 0; // IP 过期,不再缓存
}
}
prev = current;
current = current->next;
}
return 0; // IP 不在缓存中
}
// 清理缓存链表,释放所有节点的内存
void free_ip_cache()
{
struct ip_cache_node *current = ip_cache_head;
while (current != NULL) {
struct ip_cache_node *next = current->next;
free(current);
current = next;
}
ip_cache_head = NULL;
cache_size = 0;
}
char cn_ip[MAXIPSET_][MAXIPLEN] = { 0 };
// 添加一个 IP 到集合(如果已存在则不添加)
int add_cn_ip(char cn_ip[MAXIPSET_][MAXIPLEN], char *ip)
{
if (ip == NULL || strlen(ip) >= MAXIPLEN) {
return -1; // 错误:无效的 IP 地址或过长
}
// 检查是否已存在
for (int i = 0; i < MAXIPSET_; i++) {
if (cn_ip[i][0] != '\0' && strcmp(cn_ip[i], ip) == 0) {
return 1; // IP 已存在,返回特殊代码
}
}
// 查找空位并添加
for (int i = 0; i < MAXIPSET_; i++) {
if (cn_ip[i][0] == '\0') { // 检查是否为空
strcpy(cn_ip[i], ip);
return 0; // 成功添加
}
}
return -1; // 错误:集合已满
}
// 判断给定的IP地址是否在集合中
int is_ip_in_set(char cn_ip[MAXIPSET_][MAXIPLEN], const char *ip)
{
if (ip == NULL) {
return 0; // 错误无效的IP地址指针
}
for (int i = 0; i < MAXIPSET_; i++) {
if (cn_ip[i][0] != '\0' && strcmp(cn_ip[i], ip) == 0) {
return 1; // 找到匹配的IP地址
}
}
return 0; // 没有找到匹配的IP地址
}
// 计算集合中非空IP的数量
int cn_ip_len(char cn_ip[MAXIPSET_][MAXIPLEN])
{
int count = 0; // 用于计数非空IP
for (int i = 0; i < MAXIPSET_; i++) {
if (cn_ip[i][0] != '\0') {
count++; // 非空IP计数
}
}
return count;
}
int truncate_file(const char *path)
{
int fd;
// 以只写模式打开文件并截断到0字节
fd = open(path, O_WRONLY | O_TRUNC);
if (fd == -1) {
perror("truncate_file: Failed to open file");
return -1;
}
// 关闭文件描述符(此时文件已被截断)
close(fd);
return 0;
}
// 安全的清理IP地址集合将所有位置置为空字符串
void clear_ip_set(char cn_ip[MAXIPSET_][MAXIPLEN])
{
if (cn_ip == NULL) {
return; // 如果指针无效,则直接返回
}
for (int i = 0; i < MAXIPSET_; i++) {
memset(cn_ip[i], '\0', MAXIPLEN);
}
return;
}
// 保存字符串到文件
int append_string_to_file(const char *filepath, const char *str)
{
// 检查输入是否为空
if (filepath == NULL || str == NULL) {
fprintf(stderr, "Invalid argument(s).\n");
return -1;
}
// 打开文件以追加模式
FILE *file = fopen(filepath, "a");
if (file == NULL) {
perror("Error opening file");
return -1;
}
// 追加字符串到文件
if (fprintf(file, "%s\n", str) < 0) {
perror("Error writing to file");
fclose(file);
return -1;
}
// 刷新缓冲区确保数据写入磁盘
if (fflush(file) != 0) {
perror("Error flushing file");
fclose(file);
return -1;
}
// 关闭文件
if (fclose(file) != 0) {
perror("Error closing file");
return -1;
}
// 成功返回
return 0;
}
int read_file_to_array(const char *filepath, char cn_ip[MAXIPSET_][MAXIPLEN], int *line_count)
{
// 参数校验
if (filepath == NULL || cn_ip == NULL || line_count == NULL) {
fprintf(stderr, "Invalid argument(s).\n");
return -1;
}
FILE *file = fopen(filepath, "r");
if (file == NULL) {
fprintf(stderr, "Error opening file '%s': %s\n", filepath, strerror(errno));
return -2;
}
int count = 0;
while (fgets(cn_ip[count], MAXIPLEN, file)) {
// 去掉行尾的换行符
size_t len = strlen(cn_ip[count]);
if (len > 0 && cn_ip[count][len - 1] == '\n') {
cn_ip[count][len - 1] = '\0';
}
count++;
if (count >= MAXIPSET_) {
fprintf(stderr, "Exceeded maximum number of lines (%d).\n", MAXIPSET_);
fclose(file);
return -3;
}
}
if (ferror(file)) {
fprintf(stderr, "Error reading file '%s'.\n", filepath);
fclose(file);
return -4;
}
fclose(file);
*line_count = count;
return 0;
}
// 判断文件是否存在,返回 1 表示存在0 表示不存在
int file_exists_access(const char *filepath)
{
if (filepath == NULL) {
fprintf(stderr, "Invalid argument.\n");
return 0;
}
return access(filepath, F_OK) == 0;
}