#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 == NULL,current->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; } // 添加一个 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) { // 以只写模式打开文件并截断到0字节 int 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; }