优化:
添加主要处理函数Processing_IP_addresses(src_ip); 数据处理放到cache.c 暂时未发现Bug
This commit is contained in:
89
cache.c
89
cache.c
@@ -1,5 +1,94 @@
|
||||
#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;
|
||||
|
||||
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 到集合(如果已存在则不添加)
|
||||
|
||||
36
cache.h
36
cache.h
@@ -6,12 +6,44 @@
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
#include <errno.h>
|
||||
#include <time.h>
|
||||
|
||||
#define MAXIPSET_ 256
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <pcap.h>
|
||||
#include <netinet/in.h>
|
||||
#include <arpa/inet.h>
|
||||
#include <netinet/ip.h> // IP header
|
||||
#include <netinet/tcp.h> // TCP header
|
||||
#include <sys/types.h>
|
||||
#include <ctype.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/ipc.h>
|
||||
#include <sys/shm.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <string.h>
|
||||
|
||||
#define MAXIPSET_ 10240
|
||||
#define MAXIPLEN 32
|
||||
|
||||
extern char cn_ip[MAXIPSET_][MAXIPLEN];
|
||||
#define CACHE_TTL 180 // 设定缓存的存活时间为 600 秒 (10 分钟)
|
||||
#define MAX_CACHE_SIZE 100 // 缓存最多存储 100 个 IP 地址
|
||||
extern int cache_size; // 当前缓存中的 IP 数量
|
||||
|
||||
// 定义链表结构,用于缓存 IP 地址
|
||||
struct ip_cache_node {
|
||||
char ip[INET_ADDRSTRLEN]; // 存储 IP 地址
|
||||
time_t timestamp; // 记录缓存时间
|
||||
struct ip_cache_node *next; // 指向下一个节点
|
||||
};
|
||||
|
||||
extern void add_ip_to_cache(const char *ip);
|
||||
extern int is_ip_in_cache(const char *ip);
|
||||
extern void free_ip_cache();
|
||||
|
||||
extern char cn_ip[MAXIPSET_][MAXIPLEN];
|
||||
extern int add_cn_ip(char cn_ip[MAXIPSET_][MAXIPLEN], char *ip);
|
||||
extern int is_ip_in_set(char cn_ip[MAXIPSET_][MAXIPLEN], const char *ip);
|
||||
extern int cn_ip_len(char cn_ip[MAXIPSET_][MAXIPLEN]);
|
||||
|
||||
163
cap.c
163
cap.c
@@ -10,131 +10,27 @@ pcap_t *handle; // 会话句柄
|
||||
struct bpf_program fp; // 编译后的过滤器
|
||||
|
||||
pid_t pid = -1; // 子进程全局PID
|
||||
|
||||
#define SHM_SIZE 1024 // 共享内存大小
|
||||
#define SHM_KEY 0124 // 共享内存键值
|
||||
int shmid = -1;
|
||||
int RULE_NAME_NUMBER = 0; // ipset 集合集合数
|
||||
char *RULE_NAME = NULL; // 共享内存
|
||||
|
||||
|
||||
char *ip2region_area = NULL; // ip2region 解析结果
|
||||
char *command_result = NULL; // 执行命令的结果
|
||||
|
||||
#define CACHE_TTL 180 // 设定缓存的存活时间为 600 秒 (10 分钟)
|
||||
#define MAX_CACHE_SIZE 100 // 缓存最多存储 100 个 IP 地址
|
||||
struct ip_cache_node *ip_cache_head = NULL; // 缓存链表的头节点
|
||||
int cache_size = 0; // 当前缓存中的 IP 数量
|
||||
|
||||
// 定义链表结构,用于缓存 IP 地址
|
||||
struct ip_cache_node {
|
||||
char ip[INET_ADDRSTRLEN]; // 存储 IP 地址
|
||||
time_t timestamp; // 记录缓存时间
|
||||
struct ip_cache_node *next; // 指向下一个节点
|
||||
};
|
||||
|
||||
|
||||
// 将新 IP 添加到缓存,若缓存过大则移除最早的 IP
|
||||
void add_ip_to_cache(const char *ip)
|
||||
void Processing_IP_addresses(char *src_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;
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
// 回调函数,在捕获到每个数据包时调用
|
||||
void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
|
||||
{
|
||||
int ethernet_header_len = 14;
|
||||
struct ip *ip_header = (struct ip *)(packet + ethernet_header_len);
|
||||
char src_ip[INET_ADDRSTRLEN] = { 0 };
|
||||
|
||||
// 地域白名单
|
||||
char _region_list[WHITELIST_IP_NUM][WHITELIST_IP_NUM] = { { 0 }, { 0 } };
|
||||
char _REGION_LIST[BUFFER] = { 0 };
|
||||
const char *REGION_ENV = NULL;
|
||||
|
||||
char ipset_query_command[256] = { 0 };
|
||||
|
||||
// 定义 Response 结构体
|
||||
Response response;
|
||||
|
||||
inet_ntop(AF_INET, &(ip_header->ip_src), src_ip, INET_ADDRSTRLEN);
|
||||
|
||||
// 如果 IP 地址已在缓存中且未过期,则跳过查询
|
||||
if (is_ip_in_cache(src_ip)) {
|
||||
_printf(RED "IP:%s 已在缓存中,跳过查询\n" REDEND, src_ip);
|
||||
@@ -156,14 +52,12 @@ void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char
|
||||
printf("%s ", cn_ip[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (cn_ip_len(cn_ip) >= 100) { // 清理集合
|
||||
if (cn_ip_len(cn_ip) >= 1024) { // 清理集合
|
||||
clear_ip_set(cn_ip);
|
||||
}
|
||||
|
||||
printf("cn_ip_len(cn_ip): %d\n", cn_ip_len(cn_ip));
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -196,34 +90,47 @@ void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char
|
||||
|
||||
add_ip_to_cache(src_ip); // 添加到缓存
|
||||
|
||||
char *p = curl_get_area(src_ip);
|
||||
char *p = CurlGetIpArea(src_ip);
|
||||
if (parse_json_to_struct(p, &response) == 0) { // 解析 JSON 到结构体
|
||||
|
||||
if (NULL == strstr(response.continent_country, "中国")) { // 这时是国外IP
|
||||
_printf(RED "%s %s\n" REDEND, src_ip, response.continent_country);
|
||||
_printf(RED "CurlGetIpArea(): %s %s\n" REDEND, src_ip, response.continent_country);
|
||||
add_ip_to_ipset(RULE_NAME, src_ip);
|
||||
} else { // 这时是国内IP
|
||||
add_cn_ip(cn_ip, src_ip); // 添加国内IP到缓存
|
||||
} else { // 这时是国内IP
|
||||
add_cn_ip(cn_ip, src_ip); // 添加国内IP到缓存
|
||||
_printf("IP: %s 离线库为国外, API 判断为国内, 标记为已处理!!!\n", src_ip);
|
||||
|
||||
if (append_string_to_file("cn.txt", src_ip) != 0) {
|
||||
_printf("append_string_to_file() Error!!!\n");
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
fprintf(stderr, "Failed to parse JSON.\n");
|
||||
}
|
||||
|
||||
if (p != NULL)
|
||||
free(p);
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (ip2region_area != NULL) {
|
||||
free(ip2region_area);
|
||||
ip2region_area = NULL;
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
||||
|
||||
// 回调函数,在捕获到每个数据包时调用
|
||||
void packet_handler(u_char *args, const struct pcap_pkthdr *header, const u_char *packet)
|
||||
{
|
||||
int ethernet_header_len = 14;
|
||||
struct ip *ip_header = (struct ip *)(packet + ethernet_header_len);
|
||||
char src_ip[INET_ADDRSTRLEN] = { 0 };
|
||||
|
||||
inet_ntop(AF_INET, &(ip_header->ip_src), src_ip, INET_ADDRSTRLEN);
|
||||
Processing_IP_addresses(src_ip);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -236,6 +143,7 @@ void usage()
|
||||
puts(" Usage: denyip [-d] [-i <interface>] [-s <start|stop>] [-h|-?]");
|
||||
puts(" -d --daemon Daemon mode");
|
||||
puts(" -i --interface interface (default eth0)");
|
||||
puts(" -f --protocol 过滤器 [\"tcp\" | \"udp\" | \"tcp or udp\"] (default \"tcp\")");
|
||||
puts(" -l print iptables rule");
|
||||
puts(" -s --signal regular signal (default start|stop) ");
|
||||
puts(" start Enable Iptables rule");
|
||||
@@ -292,7 +200,7 @@ int main(int argc, char **argv)
|
||||
|
||||
int opt;
|
||||
char errbuf[PCAP_ERRBUF_SIZE] = { 0 }; // 错误缓冲区
|
||||
char protocol[] = "tcp";
|
||||
char protocol[256] = "tcp";
|
||||
char interface[256] = "{ 0 }";
|
||||
char Ipset_Command[BUFFER] = { 0 };
|
||||
|
||||
@@ -302,9 +210,10 @@ int main(int argc, char **argv)
|
||||
memset(errbuf, 0, PCAP_ERRBUF_SIZE);
|
||||
|
||||
int longindex = 0;
|
||||
char optstring[] = "di:s:lh?";
|
||||
char optstring[] = "di:f:s:lh?";
|
||||
static struct option longopts[] = {
|
||||
{ "interface", required_argument, 0, 'i' },
|
||||
{ "protocol", required_argument, 0, 'f' },
|
||||
{ "signal", required_argument, 0, 's' },
|
||||
{ "daemon", no_argument, 0, 'd' },
|
||||
{ "l", no_argument, 0, 'l' },
|
||||
@@ -323,6 +232,9 @@ int main(int argc, char **argv)
|
||||
case 'i':
|
||||
strcpy(interface, optarg);
|
||||
break;
|
||||
case 'f':
|
||||
strcpy(protocol, optarg);
|
||||
break;
|
||||
case 'l':
|
||||
system("iptables -L -v -n --line-numbers");
|
||||
exit(0);
|
||||
@@ -381,16 +293,25 @@ int main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
char *local_addr = GetLocalAddr("https://inet-ip.aixiao.me/");
|
||||
if (local_addr == NULL) {
|
||||
perror("GetLocalAddr()");
|
||||
return 1;
|
||||
}
|
||||
remove_char(local_addr, '\n');
|
||||
printf("Local Address: %s\n", local_addr);
|
||||
|
||||
printf("Read %d lines from file:\n", line_count);
|
||||
for (int i = 0; i < line_count; i++) {
|
||||
printf("Line %d: %s\n", i + 1, cn_ip[i]);
|
||||
}
|
||||
|
||||
free(local_addr);
|
||||
}
|
||||
|
||||
pid = fork(); // 创建子进程
|
||||
if (pid == 0) // 子进程
|
||||
{
|
||||
|
||||
int count = 0;
|
||||
snprintf(RULE_NAME, BUFFER, "root%d", RULE_NAME_NUMBER);
|
||||
|
||||
@@ -400,7 +321,6 @@ int main(int argc, char **argv)
|
||||
|
||||
while (1) {
|
||||
//_printf("子进程当前 Ipset Rule 名 %s\n", RULE_NAME);
|
||||
|
||||
count = get_ip_count_in_ipset(RULE_NAME);
|
||||
if (count >= 0) {
|
||||
_printf("子进程当前 Ipset Rule 名 %s, 数量: %d \n", RULE_NAME, count);
|
||||
@@ -417,7 +337,6 @@ int main(int argc, char **argv)
|
||||
sprintf(iptables_command, "iptables -I INPUT -m set --match-set %s src -j DROP", RULE_NAME);
|
||||
system(iptables_command);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (RULE_NAME_NUMBER == MAXIPSET_RULT_NAME_NUM) {
|
||||
@@ -426,7 +345,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
}
|
||||
|
||||
sleep(9); // 每 3 秒检查一次
|
||||
sleep(3); // 每 3 秒检查一次
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
12
common.c
12
common.c
@@ -270,3 +270,15 @@ char *_execute_command(const char *command) {
|
||||
return output;
|
||||
}
|
||||
|
||||
void remove_char(char *str, char c)
|
||||
{
|
||||
int i = 0, j = 0;
|
||||
while (str[i]) {
|
||||
if (str[i] != c) {
|
||||
str[j++] = str[i];
|
||||
}
|
||||
i++;
|
||||
}
|
||||
str[j] = '\0';
|
||||
}
|
||||
|
||||
|
||||
2
common.h
2
common.h
@@ -43,4 +43,6 @@ extern int is_valid_ip(const char *ip);
|
||||
extern int _command_exists(const char *command);
|
||||
extern char *_execute_command(const char *command);
|
||||
|
||||
extern void remove_char(char *str, char c);
|
||||
|
||||
#endif
|
||||
|
||||
84
libcurl.c
84
libcurl.c
@@ -27,8 +27,76 @@ static size_t WriteMemoryCallback(void *contents, size_t size, size_t nmemb, voi
|
||||
return realsize;
|
||||
}
|
||||
|
||||
char *GetLocalAddr(char *url)
|
||||
{
|
||||
CURL *curl_handle;
|
||||
CURLcode res;
|
||||
|
||||
struct curl_slist *headers = NULL;
|
||||
struct MemoryStruct chunk;
|
||||
|
||||
chunk.memory = malloc(1); /* 将根据上述再分配的需要增长 */
|
||||
chunk.size = 0; /* 此时没有数据 */
|
||||
|
||||
curl_global_init(CURL_GLOBAL_ALL);
|
||||
|
||||
/* 初始化curl会话 */
|
||||
curl_handle = curl_easy_init();
|
||||
|
||||
char *p = NULL;
|
||||
char *buff;
|
||||
|
||||
p = strstr(url, "-H");
|
||||
if (p) {
|
||||
|
||||
buff = (char *)alloca(p - url + 1);
|
||||
if (buff == NULL)
|
||||
perror("out of memory.");
|
||||
|
||||
memset(buff, 0, p - url + 1);
|
||||
memcpy(buff, url, (int)(p - url - 1));
|
||||
|
||||
// 赋值header值
|
||||
headers = curl_slist_append(headers, p + 3);
|
||||
|
||||
// 设置header
|
||||
curl_easy_setopt(curl_handle, CURLOPT_HTTPHEADER, headers);
|
||||
curl_easy_setopt(curl_handle, CURLOPT_URL, buff);
|
||||
|
||||
} else {
|
||||
/* 指定要获取的URL */
|
||||
curl_easy_setopt(curl_handle, CURLOPT_URL, url);
|
||||
|
||||
}
|
||||
|
||||
/* 将所有数据发送到此函数 */
|
||||
//对于同一次阻塞的curl_easy_perform而言,在写完获取的数据之前,会多次调用 WriteMemoryCallback
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEFUNCTION, WriteMemoryCallback);
|
||||
|
||||
/* 将"chunk"结构传递给回调函数 */
|
||||
curl_easy_setopt(curl_handle, CURLOPT_WRITEDATA, (void *)&chunk);
|
||||
|
||||
curl_easy_setopt(curl_handle, CURLOPT_USERAGENT, "libcurl-agent/1.0");
|
||||
|
||||
//对于同一次阻塞的curl_easy_perform而言,在写完获取的数据之前,会多次调用 WriteMemoryCallback
|
||||
res = curl_easy_perform(curl_handle);
|
||||
|
||||
if (res != CURLE_OK) {
|
||||
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
|
||||
} else {
|
||||
//printf("%lu bytes retrieved\n", (unsigned long)chunk.size);
|
||||
//printf("%s", chunk.memory);
|
||||
;
|
||||
}
|
||||
|
||||
curl_easy_cleanup(curl_handle);
|
||||
curl_global_cleanup();
|
||||
|
||||
return chunk.memory;
|
||||
}
|
||||
|
||||
// 获取公网IP
|
||||
char *curl_get_area(char *ip)
|
||||
char *CurlGetIpArea(char *ip)
|
||||
{
|
||||
char url[256] = { 0 };
|
||||
snprintf(url, sizeof(url), "https://qifu.baidu.com/ip/geo/v1/district?ip=%s", ip);
|
||||
@@ -114,7 +182,10 @@ void parse_string_field(cJSON *parent, const char *field_name, char *output, siz
|
||||
// 函数用于从 JSON 字符串解析为结构体
|
||||
int parse_json_to_struct(const char *json_string, Response *response)
|
||||
{
|
||||
if (!response) return -1;
|
||||
if (!json_string || !response) {
|
||||
fprintf(stderr, "Invalid input parameters!\n");
|
||||
return -1;
|
||||
}
|
||||
|
||||
// 初始化结构体
|
||||
memset(response, 0, sizeof(Response));
|
||||
@@ -152,7 +223,12 @@ int parse_json_to_struct(const char *json_string, Response *response)
|
||||
parse_string_field(data_item, "region", response->data.region, sizeof(response->data.region));
|
||||
}
|
||||
|
||||
snprintf(response->continent_country, 256, "%s%s", response->data.continent, response->data.country);
|
||||
// ----------- 拼接 continent_country ---------------
|
||||
if (snprintf(response->continent_country, sizeof(response->continent_country), "%s%s", response->data.continent, response->data.country) >= sizeof(response->continent_country)) {
|
||||
fprintf(stderr, "continent_country truncated!\n");
|
||||
}
|
||||
|
||||
//snprintf(response->continent_country, 256, "%s%s", response->data.continent, response->data.country);
|
||||
|
||||
// 清理 JSON 对象
|
||||
cJSON_Delete(root);
|
||||
@@ -186,4 +262,4 @@ int main(int argc, char *argv[])
|
||||
|
||||
free(p);
|
||||
}
|
||||
*/
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user