socks5基于epoll实现
单线程事件循环,火狐浏览器可以设置socks代理,部署于阿里云服务器,
源代码 socks5.tar-Linux文档类资源-CSDN下载
server.c
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/epoll.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <pthread.h>
#include "list.h"
#include "socks5.h"
#include "log.h"
#include "server.h"
#define LISTENQ 20
#define EPOLLEVENTS 512
#define FDSIZE 1024
#define POXY_CONNECT_MAX (FDSIZE)
static void msg_log(const char *e,int fd,u_char *dat, int len);
list_t *list_socks_mg = NULL;
static int socks_mg_compare_func(void *first, void *second)
{
socks_mg_t *a = first, *b = second;
if (a->c_fd == b->c_fd)
{
return 0;
}
else if (a->c_fd > b->c_fd)
{
return 1;
}
else
{
return -1;
}
}
static void socks_mg_free_func(void *data)
{
socks_mg_t *a = data;
free(a);
a = NULL;
}
static int socket_bind(const char *ip, int port);
static int do_epoll(int listenfd);
static int handle_events(int epollfd, struct epoll_event *events, int num, int listenfd);
static int do_accpet(int epollfd, int listenfd);
static int do_read(int epollfd, struct epoll_event *ev);
static int do_write(int epollfd, struct epoll_event *ev);
static int do_err(int epollfd, struct epoll_event *ev);
//./socks5 -p 1200 m 0
int main(int argc, char *argv[])
{
int listenfd,fd;
char ip[INET6_ADDRSTRLEN]="0.0.0.0";
int port = 1200;
int ret,opt;
char *optstr = "p:m:u:s:";
char m=0,u[SOCKS5_UNAME_PASSWD_LEN],s[SOCKS5_UNAME_PASSWD_LEN];
strcpy(u,SOCKS5_UNAME);
strcpy(s,SOCKS5_PASSWD);
while((opt = getopt(argc,argv,optstr))!=-1)
{
switch(opt)
{
case 'p':
port = atoi(optarg);
break;
case 'm':
m = atoi(optarg);
break;
case 'u':
strcpy(u,optarg);
break;
case 's':
strcpy(s,optarg);
break;
case '?':
break;
}
}
select_method(m,u,s);
list_socks_mg = listNew(socks_mg_free_func, socks_mg_compare_func);
if(list_socks_mg==NULL)
{
perror("malloc:");
return -1;
}
set_log_level(LOG_LEVELS_DEBUG);
listenfd = socket_bind(ip, port);
ret = listen(listenfd, LISTENQ);
if(ret != 0)
{
perror("listen error: ");
exit(1);
}
printf("listen on %d\n",port);
do_epoll(listenfd);
listDelete(list_socks_mg);
return 0;
}
static int socket_bind(const char *ip, int port)
{
int listenfd;
struct sockaddr_in servaddr;
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if (listenfd == -1)
{
perror("socket error:");
exit(1);
}
bzero(&servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
inet_pton(AF_INET, ip, &servaddr.sin_addr);
servaddr.sin_port = htons(port);
if (bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1)
{
perror("bind error: ");
exit(1);
}
return listenfd;
}
static int do_epoll(int listenfd)
{
int epollfd;
struct epoll_event events[EPOLLEVENTS];
int ret;
struct epoll_event ev;
epollfd = epoll_create(FDSIZE);
if(epollfd<0)
{
exit(1);
}
ev.events = EPOLLIN;
ev.data.fd = listenfd;
epoll_ctl(epollfd, EPOLL_CTL_ADD, listenfd, &ev);
for (;;)
{
ret = epoll_wait(epollfd, events, EPOLLEVENTS, -1);
if(ret < 0)
{
perror("epoll_wait error");
exit(1);
}
else if (ret>0)
{
LOG_DBG("\n{b%d ",ret);
ret = handle_events(epollfd, events, ret, listenfd);
LOG_DBG("B}");
if(ret)
{
list_sock_free_mg(list_socks_mg);
}
}
else
{
//list_sock_free_mg(list_socks_mg);
LOG_DBG("Z\n");
}
}
close(epollfd);
}
static int handle_events(int epollfd, struct epoll_event *events, int num, int listenfd)
{
int i;
int fd;
int ret=0;
for (i = 0; i < num; i++)
{
fd = events[i].data.fd;
if ((fd == listenfd) && (events[i].events & EPOLLIN))
{
LOG_DBG("[a");
ret |= do_accpet(epollfd, listenfd);
LOG_DBG("A]");
}
else if (events[i].events & EPOLLIN )
{
LOG_DBG("[r");
ret |= do_read(epollfd, &events[i]);
LOG_DBG("R]");
}
else if (events[i].events & EPOLLOUT )
{
LOG_DBG("[w");
ret |= do_write(epollfd, &events[i]);
LOG_DBG("W]");
}
else if (events[i].events & EPOLLERR)
{
LOG_DBG("[e");
ret |= do_err(epollfd, &events[i]);
LOG_DBG("E]");
}
else
{
LOG_DBG("[]");
}
}
return ret;
}
static int do_accpet(int epollfd, int listenfd)
{
int clifd,ret;
struct sockaddr_in cliaddr;
struct epoll_event ev;
socklen_t cliaddrlen=sizeof(struct sockaddr_in);
socks5_poxy_t *t_client;
socks_mg_t *mg;
struct timeval tv={0};
gettimeofday(&tv,NULL);
clifd = accept(listenfd, (struct sockaddr *)&cliaddr, &cliaddrlen);
if (clifd == -1)
perror("accpet error");
else
{
t_client = new_socks5_handle();
ev.events = EPOLLIN|EPOLLERR;
ev.data.ptr = t_client;
ret = epoll_ctl(epollfd, EPOLL_CTL_ADD, clifd, &ev);
if(ret == 0 && t_client!=NULL)
{
mg = malloc(sizeof(socks_mg_t));
if(t_client && mg)
{
t_client->mg = mg;
t_client->ipaddr = cliaddr;
t_client->fd = clifd;
t_client->fd_tp = CLIENT_FD;
mg->c_fd = clifd;
mg->epollfd = epollfd;
mg->process = 0;
mg->cmd = 0;
mg->err = 0;
mg->last_act_time = tv.tv_sec;
mg->client = t_client;
mg->client = t_client;
mg->server = NULL;
mg->listen = NULL;
listAdd(list_socks_mg,mg);
LOG_DBG("\nNew fd=%d num_elements=%d\n", clifd,list_socks_mg->num_elements);
}
else
{
free(t_client);
close(clifd);
}
}
else
{
close(clifd);
}
}
return 0;
}
static int do_read(int epollfd, struct epoll_event *ev)
{
int nread,ret;
socks5_poxy_t *s;
int addrlen;
struct sockaddr_in client_addr;
s = ev->data.ptr;
nread = read(s->fd, s->rev_buf, s->rev_max_size);
if (nread == -1)
{
perror("read error");
socks_mg_mark_err(s);
return 1;
}
else if (nread == 0)
{
LOG_DBG("m");
socks_mg_mark_err(s);
LOG_DBG("M");
//k考虑做下面两行类似操作 否则当有 CPU100%情况出现
//epoll_ctl(epollfd, EPOLL_CTL_DEL, events[i].data.fd, NULL);
//close(events[i].data.fd);
return 1;
}
else
{
//msg_log("recv",s->fd,s->rev_buf,nread);
s->rev_len = nread;
LOG_DBG("<");
ret = read_socks5_pro(s);
LOG_DBG(">");
return ret;
}
}
static int do_err(int epollfd, struct epoll_event *ev)
{
socks5_poxy_t *s;
u_char w_buf[10];
socks_mg_t *mg;
socks5_poxy_t *t_client,*t_server,*t_listen;
s = ev->data.ptr;
mg = s->mg;
t_client = mg->client;
t_server = mg->server;
t_listen = mg->listen;
if(s==t_server && mg->process == 5)
{
w_buf[0] = SOCKS_VERSION;
w_buf[1] = 4;
w_buf[2] = 0;
w_buf[3] = 1;
*(in_addr_t *)(w_buf +4) = t_server->ipaddr.sin_addr.s_addr;
*(in_port_t *)(w_buf +8) = t_server->ipaddr.sin_port;
write(t_client->fd,w_buf,10);
}
socks_mg_mark_err(s);
return 1;
}
static int do_write(int epollfd, struct epoll_event *ev)
{
socks5_poxy_t *s;
u_char w_buf[10];
socks_mg_t *mg;
struct epoll_event t_ev;
socks5_poxy_t *t_client,*t_server,*t_listen;
s = ev->data.ptr;
mg = s->mg;
t_client = mg->client;
t_server = mg->server;
t_listen = mg->listen;
if(s==t_server && mg->process == 5)
{
mg->process = 4;
t_ev.events = EPOLLERR|EPOLLIN;
t_ev.data.ptr = t_server;
epoll_ctl(mg->epollfd, EPOLL_CTL_MOD, t_server->fd, &t_ev);
w_buf[0] = SOCKS_VERSION;
w_buf[1] = 0;
w_buf[2] = 0;
w_buf[3] = 1;
*(in_addr_t *)(w_buf +4) = t_server->ipaddr.sin_addr.s_addr;
*(in_port_t *)(w_buf +8) = t_server->ipaddr.sin_port;
write(t_client->fd,w_buf,10);
}
return 0;
}
void msg_log(const char *e,int fd,u_char *dat, int len)
{
// struct sockaddr clientaddr;
// struct sockaddr_in *addr_v4;
// int nLocalPort,i;
// char ipstr[INET6_ADDRSTRLEN];
// int addr_len = sizeof(clientaddr);
// memset(&clientaddr, 0, sizeof(clientaddr));
// ipstr[0]=0;
// nLocalPort=0;
// if (0 == getpeername(fd, &clientaddr, &addr_len))
// {
// if (clientaddr.sa_family == AF_INET)
// {
// addr_v4 = (struct sockaddr_in *)&clientaddr;
// memset(ipstr, 0, INET6_ADDRSTRLEN);
// inet_ntop(addr_v4->sin_family, &addr_v4->sin_addr, ipstr, INET6_ADDRSTRLEN);
// nLocalPort = ntohs(addr_v4->sin_port);
// }
// }
// LOG_DBG("%s:%d %s: ",ipstr,nLocalPort,e);
// for(i=0;i<len;i++)
// {
// LOG_DBG("%02x ",dat[i]);
// }
// LOG_DBG("\n");
int i;
LOG_DBG("recv: ");
for(i=0;i<len;i++)
{
LOG_DBG("%02x ",dat[i]);
}
LOG_DBG("\n");
}
socks5.c
#include "socks5.h"
#include "log.h"
static char socks5_uname[SOCKS5_UNAME_PASSWD_LEN];
static char socks5_passwd[SOCKS5_UNAME_PASSWD_LEN];
static char s_method=2;
void select_method(char m,char *uname,char *passwd)
{
s_method = m;
strcpy(socks5_uname,uname);
strcpy(socks5_passwd,passwd);
}
void msg_log(char *s,u_char *dat, int len)
{
int i;
// LOG_DBG("%s recv: ",s);
// for(i=0;i<len;i++)
// {
// LOG_DBG("%02x ",dat[i]);
// }
// LOG_DBG("\n");
}
int read_socks5_pro(socks5_poxy_t *s)
{
int ret = 0;
socks_mg_t *mg = s->mg;
struct timeval tv={0};
gettimeofday(&tv,NULL);
mg->last_act_time = tv.tv_sec;
switch(mg->process)
{
case 0:
LOG_DBG("0");
ret = method_setp0(s);
LOG_DBG("0");
break;
case 1:
LOG_DBG("1");
ret = signIn_setp1(s);
LOG_DBG("1");
break;
case 2:
LOG_DBG("2");
ret = dest_setp2(s);
LOG_DBG("2");
break;
case 3:/*bind step2*/
LOG_DBG("3");
ret = bind_setp3(s);
LOG_DBG("3");
break;
case 4:
LOG_DBG("4");
ret = data_step4(s);
LOG_DBG("4");
break;
}
if(ret != 0)
{
LOG_DBG("5");
socks_mg_mark_err(s);
LOG_DBG("5");
}
return ret;
}
int method_setp0(socks5_poxy_t *s)
{
u_char i;
u_char nmethods=0;
u_char methods[255];
u_char method=0xff;
u_char w_buf[256];
socks5_poxy_t *t_client;
socks_mg_t *mg = s->mg;
t_client = mg->client;
msg_log("method_setp0 ",s->rev_buf,s->rev_len);
if(s->rev_buf[0]==SOCKS_VERSION)
{
nmethods = s->rev_buf[1];
if(nmethods+2>s->rev_len)
{
return -1;
}
memcpy(methods,s->rev_buf + 2,nmethods);
for(i=0;i<nmethods;i++)
{
if(s_method == METHODS_VALUE1)
{
if(methods[i]==METHODS_VALUE1)
{
method = METHODS_VALUE1;
mg->process = 2;
break;
}
}
else if(s_method == METHODS_VALUE2)
{
if(methods[i]==METHODS_VALUE2)
{
method = METHODS_VALUE2;
mg->process = 1;
break;
}
}
else
{
/* code */
}
}
w_buf[0] = SOCKS_VERSION;
w_buf[1] = method;
write(s->fd,w_buf,2);
}
if(mg->process==0)
{
return -1;
}
return 0;
}
int signIn_setp1(socks5_poxy_t *s)
{
char name[255];
char passwd[255];
u_char w_buf[2];
u_char l_name;
u_char l_passwd;
u_char n_p_ok=0xff;
socks5_poxy_t *t_client;
socks_mg_t *mg = s->mg;
t_client = mg->client;
msg_log("signIn_setp1 ",s->rev_buf,s->rev_len);
if(s->rev_buf[0]==SOCKS_VERSION)
{
l_name = s->rev_buf[1];
l_passwd = s->rev_buf[l_name+2];
if(l_name + l_passwd +3 == s->rev_len)
{
if(l_name == strlen(SOCKS5_UNAME))
{
if(0==memcmp(s->rev_buf + 2,SOCKS5_UNAME,strlen(SOCKS5_UNAME)))
{
l_passwd = s->rev_buf[l_name+2];
if(l_passwd == strlen(SOCKS5_PASSWD))
{
if(0==memcmp(s->rev_buf + l_name + 3,SOCKS5_PASSWD,strlen(SOCKS5_PASSWD)))
{
n_p_ok = 0;
}
}
}
}
}
w_buf[0] = SOCKS_VERSION;
w_buf[1] = n_p_ok;
write(s->fd,w_buf,2);
if(n_p_ok!=0)
{
mg->process = 0;
mg->process = 0;
mg->process = 0;
return -1;
}
else
{
mg->process = 2;
mg->process = 2;
mg->process = 2;
return 0;
}
}
return -1;
}
static ssize_t dest_setp2_ack(int fd,u_char rep,struct sockaddr_in *addr)
{
u_char w_buf[10];
w_buf[0] = SOCKS_VERSION;
w_buf[1] = rep;
w_buf[2] = 0;
w_buf[3] = 1;
*(in_addr_t *)(w_buf +4) = addr->sin_addr.s_addr;
*(in_port_t *)(w_buf +8) = addr->sin_port;
return write(fd,w_buf,10);
}
static int socket_resolver(const char *domain, char* ipaddr)
{
if (!domain || !ipaddr) return -1;
struct hostent* host=gethostbyname(domain);
if (!host)
{
return -1;
}
// 获取第一个IP地址
strncpy(ipaddr, inet_ntoa(*(struct in_addr*)host->h_addr), 16);
// #if 1
// // 获取所有的地址
// for (int i = 0; host->h_addr_list[i]; i++)
// {
// printf("%d ip: %s\n", i, inet_ntoa(*(struct in_addr*)host->h_addr_list[i]));
// }
// #endif
return 0;
}
int dest_setp2(socks5_poxy_t *s)
{
u_char rep=0;
u_char addr_len;
u_char ipaddr[46];
u_char cmd,atyp;
int val,ret;
struct sockaddr_in *ret_to_client_serverAddr;//return to client msg
struct epoll_event ev;
struct hostent *h=NULL;
socks5_poxy_t *t_client,*t_server,*t_listen;
socks_mg_t *mg = s->mg;
t_client = mg->client;
msg_log("dest_setp2 ",s->rev_buf,s->rev_len);
if(s->rev_buf[0]==SOCKS_VERSION)
{
t_server = new_socks5_handle();
if(t_server==NULL)
{
rep = 1;
goto end;
}
t_server->mg = mg;
t_server->fd_tp = SERVER_FD;
mg->server = t_server;
mg->cmd = s->rev_buf[1];
atyp = s->rev_buf[3];
ret_to_client_serverAddr = &t_server->ipaddr;
switch(atyp)
{
case IPV4:
addr_len = 4;
t_server->ipaddr.sin_family = AF_INET;
t_server->ipaddr.sin_addr.s_addr = *(in_addr_t *)(s->rev_buf +4);
t_server->ipaddr.sin_port = *(in_port_t*)(s->rev_buf + addr_len + 4);
break;
case DOMAINNAME:
addr_len = s->rev_buf[4];
t_server->ipaddr.sin_family = AF_INET;
t_server->ipaddr.sin_port = *(in_port_t*)(s->rev_buf + addr_len + 5);
if(0==socket_resolver(s->rev_buf + 5,ipaddr))
{
t_server->ipaddr.sin_addr.s_addr = inet_addr(ipaddr);
}
else
{
rep = 4;
goto end;
}
break;
//IPV6
default:
rep = 8;
goto end;
break;
}
switch (mg->cmd)
{
case CONNECT:
//LOG_WAR("connect\n");
//LOG_DBG(" connect %s:%d\n",inet_ntoa(t_server->ipaddr.sin_addr),ntohs(t_server->ipaddr.sin_port));
t_server->fd = socket(AF_INET, SOCK_STREAM, 0);
if(t_server->fd<0)
{
rep = 1;
goto end;
}
val = fcntl(t_server->fd,F_GETFL,0);
if (fcntl(t_server->fd,F_SETFL,val|SOCK_NONBLOCK)==-1)
{
rep = 1;
goto end;
}
ret = connect(t_server->fd,(struct sockaddr *)&t_server->ipaddr,sizeof(struct sockaddr));
if(ret == 0)
{
ev.events = EPOLLIN;
ev.data.ptr = t_server;
epoll_ctl(mg->epollfd, EPOLL_CTL_ADD, t_server->fd, &ev);
}
else if (ret == -1)
{
if(errno == EINTR)
{
rep = 1;
goto end;
}
else if(errno != EINPROGRESS)
{
perror("connect ");
rep =4;
goto end;
}
else
{
ev.events = EPOLLERR|EPOLLOUT;
ev.data.ptr = t_server;
epoll_ctl(mg->epollfd, EPOLL_CTL_ADD, t_server->fd, &ev);
mg->process = 5;
}
}
break;
case BIND:
LOG_WAR("bind\n");
t_listen = new_socks5_handle();
if(t_listen==NULL)
{
rep = 1;
goto end;
}
t_listen->mg = mg;
t_listen->fd_tp = SERVER_FD;
mg->listen = t_listen;
t_listen->fd = socket(AF_INET, SOCK_STREAM, 0);
ret_to_client_serverAddr = &t_listen->ipaddr;
t_listen->ipaddr.sin_family = AF_INET;
t_listen->ipaddr.sin_port = htons(0);
t_listen->ipaddr.sin_addr.s_addr = inet_addr("0.0.0.0");
if (bind(t_listen->fd, (struct sockaddr *)&t_listen->ipaddr, sizeof(struct sockaddr)) == -1)
{
rep =1;
goto end;
}
if(0!=listen(t_listen->fd, 5))
{
rep =1;
goto end;
}
mg->process = 3;
ev.events = EPOLLIN;
ev.data.ptr = t_listen;
epoll_ctl(mg->epollfd, EPOLL_CTL_ADD, t_listen->fd, &ev);
break;
case UDP:
LOG_WAR("udp\n");
t_server->fd = socket(AF_INET, SOCK_DGRAM, 0);
if(t_server->fd<0)
{
rep = 1;
goto end;
}
if(connect(t_server->fd,(struct sockaddr*)&t_server->ipaddr,sizeof(struct sockaddr))==-1)
{
rep = 1;
t_server->fd = 0;
goto end;
}
ev.events = EPOLLIN;
ev.data.ptr = t_server;
epoll_ctl(mg->epollfd, EPOLL_CTL_ADD, t_server->fd, &ev);
//new a thread for recv data from udp_server
break;
default:
rep = 7;
break;
}
}
end:
if(rep == 0)
{
if( mg->process != 5)
{
dest_setp2_ack(t_client->fd,rep,ret_to_client_serverAddr);
}
if(mg->process ==2)
{
mg->process = 4;
}
}
return rep;
}
int bind_setp3(socks5_poxy_t *s)
{
u_char rep=0;
socklen_t cliaddrlen;
socks5_poxy_t *t_client,*t_server,*t_listen;
socks_mg_t *mg = s->mg;
t_client = mg->client;
t_server = mg->server;
t_listen = mg->listen;
t_server->fd = accept(t_server->fd, (struct sockaddr *)&t_server->ipaddr,&cliaddrlen);
if(t_server->fd < 0)
{
mg->process = 0;
rep = 1;
}
dest_setp2_ack(t_client->fd,rep,&t_server->ipaddr);
mg->process = 4;
return rep;
}
int data_step4(socks5_poxy_t *s)
{
struct sockaddr_in a;
int ret = -1;
uint16_t addr_len=0;
u_char ipaddr[46];
u_char buf[TCP_MAX_SIZE];
socks5_poxy_t *t_client,*t_server,*t_listen;
socks_mg_t *mg = s->mg;
if(mg->err)
return;
t_client = mg->client;
t_server = mg->server;
t_listen = mg->listen;
// LOG_DBG("data_step4;");
bzero(&a,sizeof(struct sockaddr_in));
if(mg->cmd == UDP)//UDP
{
LOG_DBG("U");
//data from server,sendto client
if(s->fd_tp == SERVER_FD)
{
buf[0]=0;buf[1]=0;
buf[2]=0;buf[3]=IPV4;
*(in_addr_t *)(buf+4) = t_server->ipaddr.sin_addr.s_addr;
*(in_port_t *)(buf+8) = t_server->ipaddr.sin_port;
memcpy(buf+10,s->rev_buf,s->rev_len);
ret = write(t_client->fd,buf,s->rev_len+10);
}
//data from client,sendto server
else if(s->fd_tp == CLIENT_FD)
{
//write(s->server_fd,s->rev_buf,s->rev_len);
struct sockaddr_in addr;
if(s->rev_buf[3]== IPV4)
{
addr_len = 4;
a.sin_addr.s_addr = *(in_addr_t *)(s->rev_buf +4);
a.sin_port = *(in_port_t*)(s->rev_buf + addr_len + 4);
}
else if(s->rev_buf[3]== DOMAINNAME)
{
addr_len = s->rev_buf[4] +1;
a.sin_family = AF_INET;
a.sin_port = *(in_port_t*)(s->rev_buf + addr_len + 4);
if(0==socket_resolver(s->rev_buf + 4,ipaddr))
{
a.sin_addr.s_addr = inet_addr(ipaddr);
}
else
{
return -1;
}
}
else
{
return -1;
}
//sendto(s->server_fd,s->rev_buf,s->rev_len,0,(struct sockaddr*)&a,sizeof(struct sockaddr));
ret = write(t_server->fd,s->rev_buf+addr_len+6,s->rev_len-(addr_len+6));
}
else
{
return -1;
}
}
else//connect bind
{
//data from server,sendto client
if(s->fd_tp == SERVER_FD)
{
ret = write(t_client->fd,s->rev_buf,s->rev_len);
if(ret == -1)
{
if(errno == EAGAIN)
{
}
}
}
//data from client,sendto server
else if(s->fd_tp == CLIENT_FD)
{
ret = write(t_server->fd,s->rev_buf,s->rev_len);
if(ret == -1)
{
if(errno == EAGAIN)
{
}
}
}
}
return ret>=0 ? 0:1;
}
socks5_poxy_t *new_socks5_handle()
{
socks5_poxy_t *s=NULL;
s = malloc(sizeof(socks5_poxy_t));
s->rev_max_size = TCP_MAX_SIZE;
s->rev_buf = malloc(TCP_MAX_SIZE);
bzero(&s->ipaddr,sizeof(s->ipaddr));
return s;
}
void socks_mg_mark_err(socks5_poxy_t *s)
{
socks_mg_t *mg = s->mg;
mg->err = 1;
}
void close_fd(socks_mg_t *mg)
{
struct epoll_event ev;
socks5_poxy_t *t_client,*t_server,*t_listen;
t_client = mg->client;
t_server = mg->server;
t_listen = mg->listen;
if(t_client !=NULL)
{
if(t_client->fd>0)
{
ev.events = EPOLLIN;
epoll_ctl(mg->epollfd, EPOLL_CTL_DEL, t_client->fd, &ev);
close(t_client->fd);
t_client->fd = 0;
}
}
if(t_server !=NULL)
{
if(t_server->fd>0)
{
ev.events = EPOLLIN;
epoll_ctl(mg->epollfd, EPOLL_CTL_DEL, t_server->fd, &ev);
close(t_server->fd);
t_server->fd = 0;
}
}
if(t_listen !=NULL)
{
if(t_listen->fd>0)
{
ev.events = EPOLLIN;
epoll_ctl(mg->epollfd, EPOLL_CTL_DEL, t_listen->fd, &ev);
close(t_listen->fd);
t_listen->fd = 0;
}
}
}
void del_socks5_handle(list_t *l,node_t *nd)
{
socks_mg_t *mg = nd->data;
int fd;
if(mg->client!=NULL)
{
free(mg->client->rev_buf);
free(mg->client);
}
if(mg->server!=NULL)
{
free(mg->server->rev_buf);
free(mg->server);
}
if(mg->listen!=NULL)
{
free(mg->listen->rev_buf);
free(mg->listen);
}
fd = mg->c_fd;
listRemoveNode(l,nd);
LOG_DBG("\nDel fd=%d mg->cnt=%d\n", fd,l->num_elements);
}
void list_sock_free_mg(list_t *l)
{
node_t *node;
socks_mg_t *mg;
node_t *ndt;
int cnt = 0;
struct timeval tv={0};
if(l == NULL )
{
return;
}
gettimeofday(&tv,NULL);
for(node = l->head; node !=NULL; )
{
mg = node->data;
ndt = node;
node = node->next;
if(mg->err)
{
close_fd(mg);
del_socks5_handle(l,ndt);
}
else if(tv.tv_sec - mg->last_act_time > 60)
{
socks_mg_mark_err(mg->client);
}
if(cnt<10240)cnt++;
else
{
LOG_DBG("\nerr\n");
break;
}
}
}