client_main.c

来自「一个开源的sip源代码」· C语言 代码 · 共 753 行 · 第 1/2 页

C
753
字号
	my_perror("Error sending STUN request", rc);
}

static void send_allocate_request(pj_bool_t allocate)
{
    pj_stun_tx_data *tdata;
    pj_status_t rc;

    rc = pj_stun_session_create_req(g.sess, PJ_STUN_ALLOCATE_REQUEST, 
				    NULL, &tdata);
    pj_assert(rc == PJ_SUCCESS);


    if (BANDWIDTH != -1) {
	pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, 
				  PJ_STUN_ATTR_BANDWIDTH, BANDWIDTH);
    }

    if (!allocate) {
	pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, 
				  PJ_STUN_ATTR_LIFETIME, 0);

    } else {
	if (LIFETIME != -1) {
	    pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, 
				      PJ_STUN_ATTR_LIFETIME, LIFETIME);
	}

	if (REQ_TRANSPORT != -1) {
	    pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, 
				      PJ_STUN_ATTR_REQ_TRANSPORT, REQ_TRANSPORT);
	}

	if (REQ_PORT_PROPS != -1) {
	    pj_stun_msg_add_uint_attr(tdata->pool, tdata->msg, 
				      PJ_STUN_ATTR_REQ_PORT_PROPS, REQ_PORT_PROPS);
	}

	if (REQ_IP) {
	    pj_sockaddr_in addr;
	    pj_str_t tmp;

	    pj_sockaddr_in_init(&addr, pj_cstr(&tmp, REQ_IP), 0);
	    pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg,
					 PJ_STUN_ATTR_REQ_IP, PJ_FALSE,
					 &addr, sizeof(addr));
	}
    }

    rc = pj_stun_session_send_msg(g.sess, PJ_FALSE, 
				  &g.srv_addr, sizeof(g.srv_addr),
				  tdata);
    pj_assert(rc == PJ_SUCCESS);
}

static void send_sad_request(pj_bool_t set)
{
    pj_stun_tx_data *tdata;
    pj_status_t rc;

    if (g.peer_addr.sin_addr.s_addr == 0 ||
	g.peer_addr.sin_port == 0)
    {
	puts("Error: peer address is not set");
	return;
    }

    rc = pj_stun_session_create_req(g.sess, 
				    PJ_STUN_SET_ACTIVE_DESTINATION_REQUEST, 
				    NULL, &tdata);
    pj_assert(rc == PJ_SUCCESS);

    if (set) {
	pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg,
				     PJ_STUN_ATTR_REMOTE_ADDR, PJ_FALSE,
				     &g.peer_addr, sizeof(g.peer_addr));
    }

    rc = pj_stun_session_send_msg(g.sess, PJ_FALSE, 
				  &g.srv_addr, sizeof(g.srv_addr),
				  tdata);
    pj_assert(rc == PJ_SUCCESS);
}

static void send_send_ind(void)
{
    pj_stun_tx_data *tdata;
    int len;
    pj_status_t rc;

    if (g.peer_addr.sin_addr.s_addr == 0 ||
	g.peer_addr.sin_port == 0)
    {
	puts("Error: peer address is not set");
	return;
    }

    len = strlen(g.data);
    if (len==0) {
	puts("Error: data is not set");
	return;
    }

    rc = pj_stun_session_create_ind(g.sess, PJ_STUN_SEND_INDICATION, &tdata);
    pj_assert(rc == PJ_SUCCESS);

    pj_stun_msg_add_sockaddr_attr(tdata->pool, tdata->msg,
				  PJ_STUN_ATTR_REMOTE_ADDR, PJ_FALSE,
				  &g.peer_addr, sizeof(g.peer_addr));
    pj_stun_msg_add_binary_attr(tdata->pool, tdata->msg,
				PJ_STUN_ATTR_DATA, (pj_uint8_t*)g.data, len);

    rc = pj_stun_session_send_msg(g.sess, PJ_FALSE, 
				  &g.srv_addr, sizeof(g.srv_addr),
				  tdata);
    pj_assert(rc == PJ_SUCCESS);

}

static void send_raw_data_to_srv(void)
{
    pj_ssize_t len;

    if (g.srv_addr.sin_addr.s_addr == 0 ||
	g.srv_addr.sin_port == 0)
    {
	puts("Error: server address is not set");
	return;
    }

    len = strlen(g.data);
    if (len==0) {
	puts("Error: data is not set");
	return;
    }

    len = strlen(g.data);
    pj_sock_sendto(g.sock, g.data, &len, 0, &g.srv_addr, sizeof(g.srv_addr));
}

static void send_raw_data_to_relay(void)
{
    pj_ssize_t len;

    if (g.relay_addr.sin_addr.s_addr == 0 ||
	g.relay_addr.sin_port == 0)
    {
	puts("Error: relay address is not set");
	return;
    }

    len = strlen(g.data);
    if (len==0) {
	puts("Error: data is not set");
	return;
    }

    len = strlen(g.data);
    pj_sock_sendto(g.peer_sock, g.data, &len, 0, &g.relay_addr, sizeof(g.relay_addr));
}

static pj_status_t parse_addr(const char *input,
			      pj_sockaddr_in *addr)
{
    const char *pos;
    pj_str_t ip;
    pj_uint16_t port;
    pj_sockaddr_in tmp_addr;

    pos = pj_ansi_strchr(input, ':');
    if (pos==NULL) {
	puts("Invalid format");
	return -1;
    }

    ip.ptr = (char*)input;
    ip.slen = pos - input;
    port = (pj_uint16_t)atoi(pos+1);

    if (port==0) {
	puts("Invalid port");
	return -1;
    }

    if (pj_sockaddr_in_init(&tmp_addr, &ip, port)!=PJ_SUCCESS) {
	puts("Invalid address");
	return -1;
    }

    pj_memcpy(addr, &tmp_addr, sizeof(tmp_addr));

    return PJ_SUCCESS;
}

static void set_peer_addr(void)
{
    char addr[64];

    printf("Current peer address: %s:%d\n", 
	   pj_inet_ntoa(g.peer_addr.sin_addr), 
	   pj_ntohs(g.peer_addr.sin_port));

    printf("Input peer address in IP:PORT format: ");
    fflush(stdout);
    fgets(addr, sizeof(addr), stdin);

    if (parse_addr(addr, &g.peer_addr) != PJ_SUCCESS) {
	return;
    }

}

static void menu(void)
{
    puts("Menu:");
    printf("  pr      Set peer address (currently %s:%d)\n",
	   pj_inet_ntoa(g.peer_addr.sin_addr), pj_ntohs(g.peer_addr.sin_port));
    printf("  dt      Set data (currently \"%s\")\n", g.data);
    puts("  br      Send Bind request");
    puts("  ar      Send Allocate request");
    puts("  dr      Send de-Allocate request");
    puts("  sr      Send Set Active Destination request");
    puts("  cr      Send clear Active Destination request");
    puts("  si      Send data with Send Indication");
    puts("  rw      Send raw data to TURN server");
    puts("  rW      Send raw data to relay address");
    puts("  q       Quit");
    puts("");
    printf("Choice: ");
}


static void console_main(void)
{
    while (!g.quit) {
	char input[10];

	menu();

	fgets(input, sizeof(input), stdin);
	
	if (0) {

	} else if (input[0]=='d' && input[1]=='t') {
	    printf("Input data: ");
	    fgets(g.data, sizeof(g.data_buf), stdin);
	    
	} else if (input[0]=='p' && input[1]=='r') {
	    set_peer_addr();
	    
	} else if (input[0]=='b' && input[1]=='r') {
	    send_bind_request();
	    
	} else if (input[0]=='a' && input[1]=='r') {
	    send_allocate_request(PJ_TRUE);
	    
	} else if (input[0]=='d' && input[1]=='r') {
	    send_allocate_request(PJ_FALSE);
	    
	} else if (input[0]=='s' && input[1]=='r') {
	    send_sad_request(PJ_TRUE);
	    
	} else if (input[0]=='c' && input[1]=='r') {
	    send_sad_request(PJ_FALSE);
	    
	} else if (input[0]=='s' && input[1]=='i') {
	    send_send_ind();
	    
	} else if (input[0]=='r' && input[1]=='w') {
	    send_raw_data_to_srv();
	    
	} else if (input[0]=='r' && input[1]=='W') {
	    send_raw_data_to_relay();
	    
	} else if (input[0]=='q') {
	    g.quit = 1;
	}
    }
}


static void usage(void)
{
    puts("Usage: pjstun_client TARGET [OPTIONS]");
    puts("");
    puts("where TARGET is \"host[:port]\"");
    puts("");
    puts("and OPTIONS:");
    puts(" --realm, -r       Set realm of the credential");
    puts(" --username, -u    Set username of the credential");
    puts(" --password, -p    Set password of the credential");
    puts(" --nonce, -N       Set NONCE");   
    puts(" --fingerprint, -F Use fingerprint for outgoing requests");
    puts(" --peer, -P        Set peer address (address is in HOST:PORT format)");
    puts(" --data, -D        Set data");
    puts(" --help, -h");
}

int main(int argc, char *argv[])
{
    struct pj_getopt_option long_options[] = {
	{ "realm",	1, 0, 'r'},
	{ "username",	1, 0, 'u'},
	{ "password",	1, 0, 'p'},
	{ "nonce",	1, 0, 'N'},
	{ "fingerprint",0, 0, 'F'},
	{ "peer",	1, 0, 'P'},
	{ "data",	1, 0, 'D'},
	{ "help",	0, 0, 'h'}
    };
    int c, opt_id;
    char *pos;
    pj_status_t status;

    g.data = g.data_buf;
    pj_ansi_strcpy(g.data, "Hello world");

    while((c=pj_getopt_long(argc,argv, "r:u:p:N:hF", long_options, &opt_id))!=-1) {
	switch (c) {
	case 'r':
	    o.realm = pj_optarg;
	    break;
	case 'u':
	    o.user_name = pj_optarg;
	    break;
	case 'p':
	    o.password = pj_optarg;
	    break;
	case 'N':
	    o.nonce = pj_optarg;
	    break;
	case 'h':
	    usage();
	    return 0;
	case 'F':
	    o.use_fingerprint = PJ_TRUE;
	    break;
	case 'P':
	    o.peer_addr = pj_optarg;
	    break;
	case 'D':
	    g.data = pj_optarg;
	    break;

	default:
	    printf("Argument \"%s\" is not valid. Use -h to see help",
		   argv[pj_optind]);
	    return 1;
	}
    }

    if (pj_optind == argc) {
	puts("Error: TARGET is needed");
	return 1;
    }

    if ((pos=pj_ansi_strchr(argv[pj_optind], ':')) != NULL) {
	o.srv_addr = argv[pj_optind];
	*pos = '\0';
	o.srv_port = pos+1;
    } else {
	o.srv_addr = argv[pj_optind];
    }

    status = init();
    if (status != PJ_SUCCESS)
	goto on_return;
    
    console_main();

on_return:
    shutdown();
    return status ? 1 : 0;
}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?