예제 #1
0
int udpclient(int argc, char *argv[])
{
    char *lhost, *lport, *phost, *pport, *rhost, *rport;
    list_t *clients = NULL;
    list_t *conn_clients;
    client_t *client;
    client_t *client2;
    socket_t *tcp_serv = NULL;
    socket_t *tcp_sock = NULL;
    socket_t *udp_sock = NULL;
    char data[MSG_MAX_LEN];
    char addrstr[ADDRSTRLEN];
    
    struct timeval curr_time;
    struct timeval check_time;
    struct timeval check_interval;
    struct timeval timeout;
    fd_set client_fds;
    fd_set read_fds;
    uint16_t tmp_id;
    uint8_t tmp_type;
    uint16_t tmp_len;
    uint16_t tmp_req_id;
    int num_fds;
    
    int ret;
    int i;
    
    signal(SIGINT, &signal_handler);

    i = 0;    
    lhost = (argc - i == 5) ? NULL : argv[i++];
    lport = argv[i++];
    phost = argv[i++];
    pport = argv[i++];
    rhost = argv[i++];
    rport = argv[i++];

    /* Check validity of ports (can't check ip's b/c might be host names) */
    ERROR_GOTO(!isnum(lport), "Invalid local port.", done);
    ERROR_GOTO(!isnum(pport), "Invalid proxy port.", done);
    ERROR_GOTO(!isnum(rport), "Invalid remote port.", done);
    
    srand(time(NULL));
    next_req_id = rand() % 0xffff;
    
    /* Create an empty list for the clients */
    clients = list_create(sizeof(client_t), p_client_cmp, p_client_copy,
                          p_client_free, 1);
    ERROR_GOTO(clients == NULL, "Error creating clients list.", done);

    /* Create and empty list for the connecting clients */
    conn_clients = list_create(sizeof(client_t), p_client_cmp, p_client_copy,
                               p_client_free, 1);
    ERROR_GOTO(conn_clients == NULL, "Error creating clients list.", done);

    /* Create a TCP server socket to listen for incoming connections */
    tcp_serv = sock_create(lhost, lport, ipver, SOCK_TYPE_TCP, 1, 1);
    ERROR_GOTO(tcp_serv == NULL, "Error creating TCP socket.", done);
    if(debug_level >= DEBUG_LEVEL1)
    {
        printf("Listening on TCP %s\n",
               sock_get_str(tcp_serv, addrstr, sizeof(addrstr)));
    }
    
    FD_ZERO(&client_fds);

    /* Initialize all the timers */
    timerclear(&timeout);
    check_interval.tv_sec = 0;
    check_interval.tv_usec = 500000;
    gettimeofday(&check_time, NULL);
    
    while(running)
    {
        if(!timerisset(&timeout))
            timeout.tv_usec = 50000;

        read_fds = client_fds;
        FD_SET(SOCK_FD(tcp_serv), &read_fds);

        ret = select(FD_SETSIZE, &read_fds, NULL, NULL, &timeout);
        PERROR_GOTO(ret < 0, "select", done);
        num_fds = ret;

        gettimeofday(&curr_time, NULL);

        /* Go through all the clients and check if didn't get an ACK for sent
           data during the timeout period */
        if(timercmp(&curr_time, &check_time, >))
        {
            for(i = 0; i < LIST_LEN(clients); i++)
            {
                client = list_get_at(clients, i);

                ret = client_check_and_resend(client, curr_time);
                if(ret == -2)
                {
                    disconnect_and_remove_client(CLIENT_ID(client), clients,
                                                 &client_fds, 1);
                    i--;
                    continue;
                }

                ret = client_check_and_send_keepalive(client, curr_time);
                if(ret == -2)
                {
                    disconnect_and_remove_client(CLIENT_ID(client), clients,
                                                 &client_fds, 1);
                    i--;
                }
            }

            timeradd(&curr_time, &check_interval, &check_time);
        }
        
        if(num_fds == 0)
            continue;

        /* Check if pending TCP connection to accept and create a new client
           and UDP connection if one is ready */
        if(FD_ISSET(SOCK_FD(tcp_serv), &read_fds))
        {
            tcp_sock = sock_accept(tcp_serv);
            if(tcp_sock == NULL)
                continue;
            udp_sock = sock_create(phost, pport, ipver, SOCK_TYPE_UDP, 0, 1);
            if(udp_sock == NULL)
            {
                sock_close(tcp_sock);
                sock_free(tcp_sock);
                continue;
            }

            client = client_create(next_req_id++, tcp_sock, udp_sock, 1);
            if(!client || !tcp_sock || !udp_sock)
            {
                if(tcp_sock)
                    sock_close(tcp_sock);
                if(udp_sock)
                    sock_close(udp_sock);
            }
            else
            {
                client2 = list_add(conn_clients, client, 1);
                client_free(client);
                client = NULL;
                
                client_send_hello(client2, rhost, rport, CLIENT_ID(client2));
                client_add_tcp_fd_to_set(client2, &client_fds);
                client_add_udp_fd_to_set(client2, &client_fds);
            }
            
            sock_free(tcp_sock);
            sock_free(udp_sock);
            tcp_sock = NULL;
            udp_sock = NULL;

            num_fds--;
        }

        /* Check for pending handshakes from UDP connection */
        for(i = 0; i < LIST_LEN(conn_clients) && num_fds > 0; i++)
        {
            client = list_get_at(conn_clients, i);
            
            if(client_udp_fd_isset(client, &read_fds))
            {
                num_fds--;
                tmp_req_id = CLIENT_ID(client);

                ret = client_recv_udp_msg(client, data, sizeof(data),
                                          &tmp_id, &tmp_type, &tmp_len);
                if(ret == 0)
                    ret = handle_message(client, tmp_id, tmp_type,
                                         data, tmp_len);

                if(ret < 0)
                {
                    disconnect_and_remove_client(tmp_req_id, conn_clients,
                                                 &client_fds, 1);
                    i--;
                }
                else
                {
                    client = list_add(clients, client, 1);
                    list_delete_at(conn_clients, i);
                    client_remove_udp_fd_from_set(client, &read_fds);
                    i--;
                }
            }
        }

        /* Check if data is ready from any of the clients */
        for(i = 0; i < LIST_LEN(clients); i++)
        {
            client = list_get_at(clients, i);

            /* Check for UDP data */
            if(num_fds > 0 && client_udp_fd_isset(client, &read_fds))
            {
                num_fds--;

                ret = client_recv_udp_msg(client, data, sizeof(data),
                                          &tmp_id, &tmp_type, &tmp_len);
                if(ret == 0)
                    ret = handle_message(client, tmp_id, tmp_type,
                                         data, tmp_len);
                if(ret < 0)
                {
                    disconnect_and_remove_client(CLIENT_ID(client), clients,
                                                 &client_fds, 1);
                    i--;
                    continue; /* Don't go to check the TCP connection */
                }
            }

            /* Check for TCP data */
            if(num_fds > 0 && client_tcp_fd_isset(client, &read_fds))
            {
                ret = client_recv_tcp_data(client);
                if(ret == -1)
                {
                    disconnect_and_remove_client(CLIENT_ID(client), clients,
                                                 &client_fds, 1);
                    i--;
                    continue;
                }
                else if(ret == -2)
                {
                    client_mark_to_disconnect(client);
                    disconnect_and_remove_client(CLIENT_ID(client),
                                                 clients, &client_fds, 0);
                }

                num_fds--;
            }

            /* send any TCP data that was ready */
            ret = client_send_udp_data(client);
            if(ret < 0)
            {
                disconnect_and_remove_client(CLIENT_ID(client), clients,
                                             &client_fds, 1);
                i--;
            }
        }

        /* Finally, send any udp data that's still in the queue */
        for(i = 0; i < LIST_LEN(clients); i++)
        {
            client = list_get_at(clients, i);
            ret = client_send_udp_data(client);

            if(ret < 0 || client_ready_to_disconnect(client))
            {
                disconnect_and_remove_client(CLIENT_ID(client), clients,
                                             &client_fds, 1);
                i--;
            }
        }
    }
    
  done:
    if(debug_level >= DEBUG_LEVEL1)
        printf("Cleaning up...\n");
    if(tcp_serv)
    {
        sock_close(tcp_serv);
        sock_free(tcp_serv);
    }
    if(udp_sock)
    {
        sock_close(udp_sock);
        sock_free(udp_sock);
    }
    if(clients)
        list_free(clients);
    if(conn_clients)
        list_free(conn_clients);
    if(debug_level >= DEBUG_LEVEL1)
        printf("Goodbye.\n");
    return 0;
}
예제 #2
0
파일: udpclient.c 프로젝트: eXcomm/mobius
int udpclient(int argc, char *argv[])
{

	list_t *clients = NULL;
	list_t *conn_clients;
	client_t *client;
	client_t *tunnel;
	client_t *client2;

	char data[MSG_MAX_LEN];
	char addrstr[ADDRSTRLEN];
	char taddrstr[ADDRSTRLEN];

	socket_t *tcp_sock = NULL;
	socket_t *udp_sock = NULL;
	socket_t *next_sock = NULL;

	struct timeval curr_time;
	struct timeval check_time;
	struct timeval check_interval;
	struct timeval timeout;
	fd_set client_fds;
	fd_set read_fds;
	uint16_t tmp_id;
	uint8_t tmp_type;
	uint16_t tmp_len;
	// uint16_t tmp_req_id;
	int num_fds;
	uint32_t sourceid;



	int ret;
	int i;

	signal(SIGINT, &signal_handler);

	i = 0;    
	lhost = (argc - i == 5) ? NULL : argv[i++];
	lport = argv[i++];
	rport = argv[i++];
	phost = argv[i++];
	pport = argv[i++];
	relays = atoi(argv[i++]);
	if(debug_level >= DEBUG_LEVEL1)
		printf("relays need %d \n",relays);


	/* Check validity of ports (can't check ip's b/c might be host names) */

	ERROR_GOTO(!isnum(lport), "Invalid listen port.", done);

	ERROR_GOTO(!isnum(rport), "Invalid recv port.", done);

	ERROR_GOTO(!isnum(pport), "Invalid inter port.", done);
	//ERROR_GOTO(!isnum(rport), "Invalid remote port.", done);

	srand(inet_addr(lhost));
	localid=(rand());
	generate_rsakey(lhost);
	if(debug_level >= DEBUG_LEVEL1)
	{
		printf("local id %d \n",localid);
	}
	next_req_id = rand() % 0xffff;

	/* Create an empty list for the clients */
	clients = list_create(sizeof(client_t), p_client_cmp, p_client_copy,
	                      p_client_free, 1);
	ERROR_GOTO(clients == NULL, "Error creating clients list.", done);

	/* Create and empty list for the connecting clients */
	conn_clients = list_create(sizeof(client_t), p_client_cmp, p_client_copy,
	                           p_client_free, 1);
	ERROR_GOTO(conn_clients == NULL, "Error creating conn_clients list.", done);

	relay_clients = list_create(sizeof(client_t), p_client_cmp, p_client_copy,
	                            p_client_free, 1);
	ERROR_GOTO(relay_clients == NULL, "Error creating clients list.", done);

	/* Create a TCP server socket to listen for incoming connections */
	tcp_serv = sock_create(lhost, lport, ipver, SOCK_TYPE_TCP, 1, 1);

	ERROR_GOTO(tcp_serv == NULL, "Error creating TCP socket.", done);
	udp_serv = sock_create(lhost, rport,ipver, SOCK_TYPE_UDP, 1, 1);
	ERROR_GOTO(udp_serv == NULL, "Error creating TCP socket.", done);
	if(debug_level >= DEBUG_LEVEL1)
	{
		printf("Listening on TCP %s,UDP %s \n",
		       sock_get_str(tcp_serv, addrstr, sizeof(addrstr)),sock_get_str(udp_serv, taddrstr, sizeof(taddrstr)));
	}
	next_sock = sock_create(phost, pport, ipver, SOCK_TYPE_UDP, 0, 1);

	msg_send_req(next_sock,lhost,rport,0,localid);	   
	sock_free(next_sock);		
	next_sock = NULL;		

	FD_ZERO(&client_fds);

	/* Initialize all the timers */
	timerclear(&timeout);
	check_interval.tv_sec = 0;
	check_interval.tv_usec = 500000;
	gettimeofday(&check_time, NULL);


	while(running)
	{
		if(!timerisset(&timeout))
			timeout.tv_usec = 50000;

		read_fds = client_fds;
		FD_SET(SOCK_FD(tcp_serv), &read_fds);
		FD_SET(SOCK_FD(udp_serv), &read_fds);

		ret = select(FD_SETSIZE, &read_fds, NULL, NULL, &timeout);
		PERROR_GOTO(ret < 0, "select", done);
		num_fds = ret;

		gettimeofday(&curr_time, NULL);

		/* Go through all the clients and check if didn't get an ACK for sent
		 data during the timeout period */
		if(timercmp(&curr_time, &check_time, >))
		{
			for(i = 0; i < LIST_LEN(clients); i++)
			{
				client = list_get_at(clients, i);

				ret = client_check_and_resend(client, curr_time);
				if(ret == -2)
				{
					disconnect_and_remove_client(CLIENT_ID(client), clients,
					                             &client_fds, 1);
					i--;
					continue;
				}

				ret = client_check_and_send_keepalive(client, curr_time);
				if(ret == -2)
				{
					disconnect_and_remove_client(CLIENT_ID(client), clients,
					                             &client_fds, 1);
					i--;
				}
			}

			timeradd(&curr_time, &check_interval, &check_time);
		}

		if(num_fds == 0)
			continue;

		/* Check if pending TCP connection to accept and create a new client
		 and UDP connection if one is ready */
		if(FD_ISSET(SOCK_FD(tcp_serv), &read_fds))
		{
			tcp_sock = sock_accept(tcp_serv);
			if(tcp_sock == NULL)
				continue;
			if(SelectMethod(tcp_sock->fd)==-1)
			{ 
				if(debug_level >= DEBUG_LEVEL1)
					printf("socks version error\n");
				return-1;
			}
			rhost=ParseCommand(tcp_sock->fd);
			if (0<LIST_LEN(relay_clients))
			{

				tunnel = list_get_at(relay_clients, 0);

				udp_sock =sock_copy(CLIENT_TCP_SOCK(tunnel));

				SOCK_FD(udp_sock)=socket(AF_INET, SOCK_DGRAM, 0); 					
			}

			if(udp_sock == NULL)
			{
				sock_close(tcp_sock);
				sock_free(tcp_sock);
				continue;
			}

			client = client_create(next_req_id++, localid, tcp_sock, udp_sock, 1);
			memcpy(client->rsakey,tunnel->rsakey,strlen(tunnel->rsakey));

			printf("expid rsakey is %s",client->rsakey);
			if(debug_level >= DEBUG_LEVEL1)
				printf("create client id %d \n",CLIENT_ID(client));
			if(!client || !tcp_sock || !udp_sock)
			{
				if(tcp_sock)
					sock_close(tcp_sock);
				if(udp_sock)
					sock_close(udp_sock);
			}
			else
			{
				client2 = list_add(conn_clients, client, 1);
				client_free(client);
				client = NULL;
				if(debug_level >= DEBUG_LEVEL1)
				{
					sock_get_str(CLIENT_TCP_SOCK(client2), addrstr,
					             sizeof(addrstr));				
					printf("tunnel(%d): local %s ",client2->sourceid, addrstr);
					sock_get_str(CLIENT_UDP_SOCK(client2), addrstr,
					             sizeof(addrstr));
					printf("to %s \n",addrstr);
				}
				client_send_hello(client2,rhost,CLIENT_ID(client2));
				client_add_tcp_fd_to_set(client2, &client_fds);
				//client_add_udp_fd_to_set(client2, &client_fds);
			}

			sock_free(tcp_sock);
			sock_free(udp_sock);
			tcp_sock = NULL;
			udp_sock = NULL;

			num_fds--;
		}

		/* Check for UDP data */
		if(FD_ISSET(SOCK_FD(udp_serv), &read_fds))
		{


			//ret = client_recv_udp_msg(client, data, sizeof(data),
			//                          &tmp_id, &tmp_type, &tmp_len,&sourceid);
			ret = msg_recv_msg(udp_serv, data, sizeof(data),
			                   &tmp_id, &tmp_type, &tmp_len,&sourceid);

			if(debug_level >= DEBUG_LEVEL2)
				printf("recv msg from %d type %d %d bytes \n ",sourceid,tmp_type,tmp_len);
			if(ret == 0)
				ret = handle_message(tmp_id, tmp_type,
				                     data, tmp_len,sourceid,clients, conn_clients);
			/*if(ret < 0)
			{

				disconnect_and_remove_client(tmp_id, clients,
				                             &client_fds, 1);

		}	*/		
		}

		/* Check if data is ready from any of the clients */
		for(i = 0; i < LIST_LEN(clients); i++)
		{
			client = list_get_at(clients, i);



			/* Check for TCP data */
			if(num_fds > 0 && client_tcp_fd_isset(client, &read_fds))
			{
				ret = client_recv_tcp_data(client);
				if(ret == -1)
				{
					disconnect_and_remove_client(CLIENT_ID(client), clients,
					                             &client_fds, 1);
					i--;
					continue;
				}
				else if(ret == -2)
				{
					client_mark_to_disconnect(client);
					disconnect_and_remove_client(CLIENT_ID(client),
					                             clients, &client_fds, 0);
				}

				num_fds--;
			}

			/* send any TCP data that was ready */
			ret = client_send_udp_data(client);
			if(ret < 0)
			{
				disconnect_and_remove_client(CLIENT_ID(client), clients,
				                             &client_fds, 1);
				i--;
			}
		}

		/* Finally, send any udp data that's still in the queue */
		for(i = 0; i < LIST_LEN(clients); i++)
		{
			client = list_get_at(clients, i);
			ret = client_send_udp_data(client);

			if(ret < 0 || client_ready_to_disconnect(client))
			{
				disconnect_and_remove_client(CLIENT_ID(client), clients,
				                             &client_fds, 1);
				i--;
			}
		}
	}

	done:
		if(debug_level >= DEBUG_LEVEL1)
			printf("Cleaning up...\n");
		if(tcp_serv)
	{
		sock_close(tcp_serv);
		sock_free(tcp_serv);
	}
		if(udp_serv)
	{
		sock_close(udp_serv);
		sock_free(udp_serv);
	}
		if(clients)
			list_free(clients);
		if(conn_clients)
			list_free(conn_clients);
		if(debug_level >= DEBUG_LEVEL1)
			printf("Goodbye.\n");
		return 0;
}