📄 server.c
字号:
}/*end of while(1)*/
do_exit();
}/*end of main procedure*/
void do_exit()
{
int id = pthread_self();
if (id == timerid)
return;
pthread_cancel(timerid);
free_flowlist();
exit(0);
}
int init_config()
{
FILE *fp = NULL;
char linebuf[BUF_LEN];
struct flow_info *flow = NULL;
int wordnum;
char **wordlist = NULL;
int ret = -1;
if ((fp = fopen(CONFIG_FILE, "r")) == NULL) {
DEBUG("open file %s error", CONFIG_FILE);
goto done;
}
memset(linebuf, 0, sizeof(linebuf));
while (fgets(linebuf, sizeof(linebuf), fp) != NULL) {
if (linebuf[0] == '#')
continue;
STRIP(linebuf, '\n');
DEBUG("get line[%s]", linebuf);
wordnum = parse_line(linebuf, ",", &wordlist, 1);
if (wordnum <= 0) {
DEBUG("null line or error line");
continue;
}
if (wordnum != 6) {
DEBUG("format error[%d]", wordnum);
goto done;
}
flow = (struct flow_info *)malloc(sizeof(struct flow_info));
if (flow == NULL) {
DEBUG("malloc eror");
goto done;
}
memset(flow, 0, sizeof(*flow)); flow->ID = atoi(wordlist[0]);
flow->sip = ip2val(wordlist[1]);
flow->dip = ip2val(wordlist[2]);
flow->type = atoi(wordlist[3]);
flow->value = str2ll(wordlist[4], DEC);
flow->feeRatio=atoi(wordlist[5]);
flow->next = flow_list;
flow_list = flow;
if (wordlist && wordnum > 0) {
memset(wordlist, 0, wordnum * sizeof(char*));
free(wordlist);
wordlist = NULL;
}
}
ret = 0;
done:
FCLOSE(fp);
if (wordlist && wordnum > 0) {
memset(wordlist, 0, wordnum * sizeof(char*));
free(wordlist);
}
dump_flowlist();
return ret;
}
void free_flowlist()
{
struct flow_info *flow = NULL;
while (flow_list) {
flow = flow_list;
flow_list = flow->next;
free(flow);
}
}
void dump_flowlist()
{
struct flow_info *flow = flow_list;
char sip[16], dip[16];
DEBUG("flow list:");
while (flow) {
DEBUG("sip:%s dip:%s type:%d value:%llu",
val2ip(flow->sip, sip), val2ip(flow->dip, dip),
flow->type, flow->value);
flow = flow->next;
}
}
//流量检测函数。
//参数IP表示客户端的IP地址,SIZE表示此次产生的流量数。
//返回值: 0:表示可以使用。
// 1:表示超过流量,不能使用
// 2:表示没有规则,默认不使用。
// 3:表示达到最大同时连接数,禁止使用。
int check_flowlist(unsigned int ip, int size)
{
struct avl_node *node = NULL;
struct avl_data *data = NULL;
struct flow_info *info = NULL;
char ipbuf[16];
DEBUG("check flow list with ip[%s] size[%d]", val2ip(ip, ipbuf), size);
if ((node = avl_find(&avltree, (unsigned char *)&ip)) != NULL) { //在已有的连接中找此用户
//如果此用户已经有连接
data = NODE_RESOLVE(node);
DEBUG("node found in avltree");
DEBUG("ip:%s type:%d value:%llu used:%llu time:%s",
val2ip(data->ip, ipbuf), data->type, data->value, data->used, ctime(&(data->time)));
if (data->type == 0) //?类型为0,返回0。(可能为特殊权限用户(不限流量))
return 0;
if (data->used + size > data->value) //已用加上此次产生的流量大于限制流量,禁止使用。
return 1;
else
{
data->used += size; //记录此次的流量,
recordFee(data->ID,data->feeRatio,size);//记录费用
}
} else {
DEBUG("New Account\n");
if ((info = find_flowlist(ip)) == NULL) //未找到此用用户,禁止使用。
return 2;
if (info->type == 0) //特殊用户,不限制。
return 0;
if (info->value < size) //此次使用量大于限制量,禁止使用。
return 1;
if (flow_list == NULL) //超过最大连接数。
return 3;
pthread_mutex_lock(&lockavl);
node = free_node;
free_node = node->next;
if (free_node)
free_node->prev = NULL;
if (used_node)
used_node->prev = node;
node->next = used_node;
node->prev = NULL;
used_node = node;
//记录当前用户信息。
data = NODE_RESOLVE(node);
data->ip = ip;
data->type = info->type;
data->value = info->value;
data->used = size; data->ID=info->ID;
data->feeRatio=info->feeRatio;
time(&data->time);
DEBUG("create new node");
DEBUG("ip:%s type:%d value:%llu used:%llu time:%s",
val2ip(data->ip, ipbuf), data->type, data->value, data->used, ctime(&(data->time)));
recordFee(data->ID,data->feeRatio,size);//记录费用
avl_insert(&avltree, node);
pthread_mutex_unlock(&lockavl); }
return 0;
}
struct flow_info *find_flowlist(unsigned int ip)
{
struct flow_info *info = flow_list;
while (info) {
if (ip >= info->sip && ip <= info->dip) //IP在一个范围之内,
break;
info = info->next;
}
return info;
}
void dump_usedlist()
{
struct avl_node *node = used_node;
struct avl_data *data = NULL;
char ip[16];
int num = 0;
DEBUG("used list:");
while (node) {
data = NODE_RESOLVE(node);
num++;
DEBUG("%d ip:%s type:%d value:%llu used:%llu time:%s",
num, val2ip(data->ip, ip), data->type, data->value, data->used, ctime(&data->time));
node = node->next;
}
}
void *server_timer(void *arg)
{
struct avl_node *node = NULL;
struct avl_data *data = NULL;
time_t curr;
struct tm *m1 = NULL, *m2 = NULL;
int t;
pthread_detach(pthread_self());
DEBUG("server_timer pid : %u", getpid());
DEBUG("server_timer thread id : %d", (int)pthread_self());
while (1) {
//DEBUG("come in server_timer ...");
pthread_mutex_lock(&lockavl);
curr = time(NULL);
node = used_node;
while (node) {
data = NODE_RESOLVE(node);
m1 = localtime(&data->time);
m2 = localtime(&curr);
switch (data->type) {
case 1: /* every hour */
t = m2->tm_hour - m1->tm_hour;
break;
case 2: /* every day */
t = m2->tm_mday - m1->tm_mday;
break;
case 3: /* every month */
t = m2->tm_mon - m1->tm_mon;
break;
default:
t = 1;
break;
}
if (t > 0) {
if (node->prev)
node->prev->next = node->next;
else
used_node = node->next;
if (node->next)
node->next->prev = node->prev;
node->next = NULL;
node->prev = NULL;
if (free_node)
free_node->prev = node;
node->next = free_node;
node->prev = NULL;
free_node = node;
}
}
pthread_mutex_unlock(&lockavl);
sleep(SERVER_TIMER_INTER);
}
}
void daemon_init()
{
int i, maxfd;
if (fork() != 0)
exit(1);
if (setsid() < 0)
exit(1);
if (fork() != 0)
exit(1);
// chdir("/");
umask(0);
maxfd = sysconf(_SC_OPEN_MAX);
for (i = 0; i < maxfd; i++)
close(i);
open("/dev/null", O_RDWR);
dup(0);
dup(1);
dup(2);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -