socks5代理基于epoll实现

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;
        }
        
    }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值