Ejemplo n.º 1
0
int main(int argc, char* argv[])
{

#if 1
    // For debug with segment fault
    struct sigaction sa;
    sa.sa_handler = backtrace_info;
    sigaction(SIGSEGV, &sa, NULL);

    // ignore SIGPIPE
    signal(SIGPIPE, SIG_IGN);
    signal(SIGCHLD, SIG_IGN);
    signal(SIGABRT, SIG_IGN);

#endif

    int opt_g = 0;
    memset(&cltopt, 0, sizeof(CLT_OPT));

    cltopt.C_TYPE = C_USR;
    while( (opt_g = getopt(argc, argv, "Dh")) != -1 )
    {
        switch(opt_g)
        {
            case 'D':
                cltopt.C_TYPE = C_DAEMON;
                break;
            case 'h':
            default:
                usage();
                exit(EXIT_SUCCESS);
        }
    }

    if(load_settings_client(&cltopt) == RET_NO)
    {
        st_d_error("加载配置文件settings.json出错!");
        exit(EXIT_FAILURE);
    }

    OpenSSL_add_ssl_algorithms();
    SSL_load_error_strings();
    SSL_library_init();     //SSL_library_init() always returns "1"

    //int sd_id128_from_string(const char *s, sd_id128_t *ret);
    sd_id128_get_machine(&cltopt.mach_uuid);
    gethostname(cltopt.hostname, sizeof(cltopt.hostname)); 
    st_d_print("CURRENT MACH_ID:%s, HOSTNAME:%s", SD_ID128_CONST_STR(cltopt.mach_uuid), 
               cltopt.hostname);

    if (cltopt.C_TYPE == C_DAEMON) 
    {
        cltopt.session_uuid = cltopt.mach_uuid;
        st_d_print("PLEASE REMEMEBER SET MACH_ID FOR USER TYPE!");
    }

    dump_clt_opts(&cltopt);

    /*带配置产生event_base对象*/
    struct event_config *cfg;
    cfg = event_config_new();
    event_config_avoid_method(cfg, "select");   //避免使用select
    event_config_require_features(cfg, EV_FEATURE_ET);  //使用边沿触发类型
    base = event_base_new_with_config(cfg);
    event_config_free(cfg);
    st_d_print("当前复用Event模式: %s", event_base_get_method(base)); // epoll

    /*连接服务器*/
    int srv_fd = socket(AF_INET, SOCK_STREAM, 0);
    unsigned int optval = 1;
    setsockopt(srv_fd, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));//禁用NAGLE算法

    if(sc_connect_srv(srv_fd) != RET_YES) 
    {
        SYS_ABORT("连接服务器失败!");
    }

    if(cltopt.C_TYPE == C_DAEMON) 
    {
        if (sc_daemon_init_srv(srv_fd) != RET_YES) 
            SYS_ABORT("(Daemon) 服务器返回错误!");
    }
    else
    {
        if (sc_usr_init_srv(srv_fd) != RET_YES) 
            SYS_ABORT("(Usr) 服务器返回错误!");
    }

    st_d_print("客户端连接服务器OK!");

    /**
     * USR 建立本地Listen侦听套接字
     */

    if (cltopt.C_TYPE == C_USR)
    {
        int i = 0;
        for (i=0; i<MAX_PORT_NUM; i++)
        {
            if (cltopt.maps[i].usrport) 
            {
                struct evconnlistener *listener;
                struct sockaddr_in sin;
                memset(&sin, 0, sizeof(sin));
                sin.sin_family = AF_INET;
                sin.sin_addr.s_addr = htonl(0);
                sin.sin_port = htons(cltopt.maps[i].usrport); /* Port Num */

                listener = evconnlistener_new_bind(base, accept_conn_cb, &cltopt.maps[i],
                        LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, -1/*backlog 连接无限制*/,
                        (struct sockaddr*)&sin, sizeof(sin));

                if (!listener) 
                {
                    st_d_error("[USR]创建侦听套接字失败 %d:%d", 
                               cltopt.maps[i].usrport, cltopt.maps[i].daemonport); 
                    continue;
                }
                evconnlistener_set_error_cb(listener, accept_error_cb);

                st_d_print("[USR]创建侦听套接字 %d:%d OK", 
                               cltopt.maps[i].usrport, cltopt.maps[i].daemonport); 
            }
            else
                break;
        }
    }
    
    encrypt_init(SD_ID128_CONST_STR(cltopt.mach_uuid), cltopt.enc_key);

    if (cltopt.C_TYPE == C_DAEMON && cltopt.ss5_port ) 
    {
        /**
         * 目前只考虑将sockets5代理使用线程池来处理,其它的端口暴露 
         * 基本都是长连接,不单独处理 
         */
        cltopt.thread_num = 5;

        cltopt.main_thread_id = pthread_self(); 
        cltopt.thread_objs = (P_THREAD_OBJ)calloc(sizeof(THREAD_OBJ), cltopt.thread_num);
        if (!cltopt.thread_objs) 
        {
            SYS_ABORT("申请THREAD_OBJ出错");
        }


        sc_create_ss5_worker_threads(cltopt.thread_num, cltopt.thread_objs); 

        st_d_print("[DAEMON]创建sockets5代理端口:%d", cltopt.ss5_port); 

        struct evconnlistener *listener;
        struct sockaddr_in sin;
        memset(&sin, 0, sizeof(sin));
        sin.sin_family = AF_INET;
        sin.sin_addr.s_addr = htonl(0);
        sin.sin_port = htons(cltopt.ss5_port); /* Port Num */

        listener = evconnlistener_new_bind(base, ss5_accept_conn_cb, NULL,
                LEV_OPT_LEAVE_SOCKETS_BLOCKING/* 阻塞 */|LEV_OPT_CLOSE_ON_FREE|LEV_OPT_REUSEABLE, 
                -1/*backlog 连接无限制*/,
                (struct sockaddr*)&sin, sizeof(sin));

        if (!listener) 
        {
            st_d_error("[DAEMON]sockets5代理创建侦听套接字失败 %d", cltopt.ss5_port); 
            exit(EXIT_FAILURE); 
        }
        evconnlistener_set_error_cb(listener, accept_error_cb);

        st_d_print("[DAEMON]sockets5代理创建侦听套接字OK %d", cltopt.ss5_port); 

    }



    if (cltopt.C_TYPE == C_DAEMON && cltopt.dns_port) 
    {
        st_d_print("[DAEMON]创建DNS代理端口:%d", cltopt.dns_port); 
        if (cltopt.dns_port != 53) 
        {
            st_d_print("[DAEMON]请注意标准DNS侦听#53端口!");
        }

        int dns_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
        if (dns_socket < 0 )
        {
            st_d_error("Create DNS socket error!");
            exit(EXIT_FAILURE);
        }

        unsigned int optval = 1;
        setsockopt(dns_socket, IPPROTO_TCP, TCP_NODELAY, &optval, sizeof(optval));//禁用NAGLE算法
        setsockopt(dns_socket, SOL_SOCKET, SO_REUSEPORT, &optval, sizeof(optval));
        evutil_make_socket_closeonexec(dns_socket);
        evutil_make_socket_nonblocking(dns_socket);

        struct sockaddr_in sin;
        memset(&sin, 0, sizeof(sin));
        sin.sin_family = AF_INET;
        sin.sin_addr.s_addr = htonl(0);
        sin.sin_port = htons(cltopt.dns_port); /* Port Num */

        if (bind(dns_socket, (struct sockaddr *)&sin, sizeof(sin)))
        {
            st_d_error("Bind DNS socket error!");
            exit(EXIT_FAILURE);
        }

        cltopt.dns_transid_port_map = (unsigned short*)malloc(sizeof(unsigned short) * 0xFFFF);
        if (!cltopt.dns_transid_port_map) 
        {
            st_d_error("Malloc for requestid-port failed!");
            exit(EXIT_FAILURE);
        }

        P_PORTTRANS p_trans = sc_create_trans(cltopt.dns_port); 
        if (!p_trans)
        {
            st_d_error("本地无空闲TRANS!");
            exit(EXIT_FAILURE);
        }
        p_trans->is_enc = 1;
        p_trans->l_port = cltopt.dns_port;
        encrypt_ctx_init(&p_trans->ctx_enc, p_trans->l_port, cltopt.enc_key, 1); 
        encrypt_ctx_init(&p_trans->ctx_dec, p_trans->l_port, cltopt.enc_key, 0);
        // 建立DNS UDP事件侦听
        p_trans->extra_ev = event_new(base, dns_socket, EV_READ | EV_PERSIST, 
                                      dns_client_to_proxy_cb, p_trans);


        int dns_srv_fd = socket(AF_INET, SOCK_STREAM, 0);
        if(sc_connect_srv(dns_srv_fd) != RET_YES) 
        {
            SYS_ABORT("连接服务器失败!");
        }

        sc_daemon_dns_init_srv(dns_srv_fd, p_trans->l_port, 12333);
        evutil_make_socket_nonblocking(dns_srv_fd);

        // later enabled
        //event_add(p_trans->extra_ev, NULL) != 0);

        p_trans->srv_bev = bufferevent_socket_new(base, dns_srv_fd, BEV_OPT_CLOSE_ON_FREE);
        bufferevent_setcb(p_trans->srv_bev, dns_bufferread_cb_enc, NULL, dns_bufferevent_cb, p_trans);

        st_d_print("[DAEMON]DNS代理创建侦听套接字OK %d", cltopt.dns_port); 
    }

    sc_set_eventcb_srv(srv_fd, base); 

    /**
     * Main Loop Here
     */

    event_base_loop(base, 0);
    event_base_free(base);
    st_d_print("程序退出!!!!");
    return 0;
}
Ejemplo n.º 2
0
void srv_bufferevent_cb(struct bufferevent *bev, short events, void *ptr)
{
    struct event_base *base = bufferevent_get_base(bev);
    int loop_terminate_flag = 0;

    //只有使用bufferevent_socket_connect进行的连接才会得到CONNECTED的事件
    if (events & BEV_EVENT_CONNECTED) 
    {
        st_d_print("GOT BEV_EVENT_CONNECTED event! ");
    } 
    else if (events & BEV_EVENT_ERROR) 
    {
        st_d_error("GOT BEV_EVENT_ERROR event! ");
        loop_terminate_flag = 1;
    } 
    else if (events & BEV_EVENT_EOF) 
    {
        st_d_print("GOT BEV_EVENT_EOF event! ");

        // main_be连接断开,这时候:如果是DAEMON端主动断开,那么USR端也要断开
        // 否则,就让DAEMON进行重置(重新连接服务器)
        // 任何情况下,所有的服务都必须断开

        // BEV_OPT_CLOSE_ON_FREE already closed the socket
        if (cltopt.C_TYPE == C_USR) 
        {
            st_d_print("DAEMON已经退出,本端挂起!");
            exit(EXIT_SUCCESS);
        }
        else
        {
            sc_free_all_trans();
            st_d_print("DAEMON端重连服务器!");

            int srv_fd;
            srv_fd = socket(AF_INET, SOCK_STREAM, 0);

            if (sc_connect_srv(srv_fd) != RET_YES)
            {
                st_d_error("连接服务器失败!");
                event_base_loopexit(base, NULL);
            }

            if (sc_daemon_init_srv(srv_fd) != RET_YES) 
            {
                st_d_error("(DAEMON)服务端返回错误!");
                event_base_loopexit(base, NULL);
            }
       
            sc_set_eventcb_srv(srv_fd, base);
            st_d_print("(DAEMON)重连OK!");

        }

    }
    else if (events & BEV_EVENT_TIMEOUT) 
    {
        st_d_print("GOT BEV_EVENT_TIMEOUT event! ");
    } 
    
    if (loop_terminate_flag)
    {
        bufferevent_free(bev);
        event_base_loopexit(base, NULL);
    }

    return;
}