⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 pjsip-perf.c

📁 基于sip协议的网络电话源码
💻 C
📖 第 1 页 / 共 4 页
字号:
#if defined(PJMEDIA_HAS_GSM_CODEC) && PJMEDIA_HAS_GSM_CODEC!=0    pjmedia_codec_gsm_init(app.med_endpt);#endif#if defined(PJMEDIA_HAS_SPEEX_CODEC) && PJMEDIA_HAS_SPEEX_CODEC!=0    pjmedia_codec_speex_init(app.med_endpt, PJMEDIA_SPEEX_NO_UWB, 3, 3);#endif    /* Init dummy socket addresses */    app.skinfo_cnt = 0;    for (i=0, rtp_port=4000; i<PJ_ARRAY_SIZE(app.skinfo); ++i, rtp_port+=2) {	pjmedia_sock_info *skinfo;	skinfo = &app.skinfo[i];		pj_sockaddr_in_init(&skinfo->rtp_addr_name, &app.local_addr,			    (pj_uint16_t)rtp_port);	pj_sockaddr_in_init(&skinfo->rtp_addr_name, &app.local_addr,			    (pj_uint16_t)(rtp_port+1));	app.skinfo_cnt++;    }    /* Generate dummy SDP */    dummy_sdp_str.slen = pj_ansi_strlen(dummy_sdp_str.ptr);    status = pjmedia_sdp_parse(app.pool, dummy_sdp_str.ptr, dummy_sdp_str.slen, 			       &app.dummy_sdp);    if (status != PJ_SUCCESS) {	app_perror(THIS_FILE, "Error parsing dummy SDP", status);	return status;    }    /* Done */    return PJ_SUCCESS;}/* This is notification from the call about media negotiation * status. This is called for client calls only. */static void call_on_media_update( pjsip_inv_session *inv,				  pj_status_t status){    if (status != PJ_SUCCESS) {	pjsip_tx_data *tdata;	pj_status_t status;	status = pjsip_inv_end_session(inv, PJSIP_SC_UNSUPPORTED_MEDIA_TYPE, 				       NULL, &tdata);	if (status == PJ_SUCCESS && tdata)	    status = pjsip_inv_send_msg(inv, tdata);    }}/* This is notification from the call when the call state has changed. * This is called for client calls only. */static void call_on_state_changed( pjsip_inv_session *inv, 				   pjsip_event *e){    PJ_UNUSED_ARG(e);    /* Bail out if the session has been counted before */    if (inv->mod_data[mod_test.id] != NULL)	return;    /* Bail out if this is not an outgoing call */    if (inv->role != PJSIP_UAC_ROLE)	return;    if (inv->state == PJSIP_INV_STATE_CONFIRMED) {	pjsip_tx_data *tdata;	pj_status_t status;	//report_completion(200);	//inv->mod_data[mod_test.id] = (void*)1;	status = pjsip_inv_end_session(inv, PJSIP_SC_OK, NULL, &tdata);	if (status == PJ_SUCCESS && tdata)	    status = pjsip_inv_send_msg(inv, tdata);    } else if (inv->state == PJSIP_INV_STATE_DISCONNECTED) {	report_completion(inv->cause);	inv->mod_data[mod_test.id] = (void*)1;    }}/* Not implemented for now */static void call_on_forked(pjsip_inv_session *inv, pjsip_event *e){    /* Do nothing */    PJ_UNUSED_ARG(inv);    PJ_UNUSED_ARG(e);}/* * Make outgoing call. */static pj_status_t make_call(const pj_str_t *dst_uri){    struct call *call;    pjsip_dialog *dlg;    pjmedia_sdp_session *sdp;    pjsip_tx_data *tdata;    pj_status_t status;    /* Create UAC dialog */    status = pjsip_dlg_create_uac( pjsip_ua_instance(), 				   &app.local_uri,	/* local URI	    */				   &app.local_contact,	/* local Contact    */				   dst_uri,		/* remote URI	    */				   dst_uri,		/* remote target    */				   &dlg);		/* dialog	    */    if (status != PJ_SUCCESS) {	return status;    }    /* Create call */    call = pj_pool_zalloc(dlg->pool, sizeof(struct call));    /* Create SDP */    if (app.real_sdp) {	status = pjmedia_endpt_create_sdp(app.med_endpt, dlg->pool, 1, 					  app.skinfo, &sdp);	if (status != PJ_SUCCESS) {	    pjsip_dlg_terminate(dlg);	    return status;	}    } else	sdp = app.dummy_sdp;    /* Create the INVITE session. */    status = pjsip_inv_create_uac( dlg, sdp, 0, &call->inv);    if (status != PJ_SUCCESS) {	pjsip_dlg_terminate(dlg);	return status;    }    /* Create initial INVITE request.     * This INVITE request will contain a perfectly good request and      * an SDP body as well.     */    status = pjsip_inv_invite(call->inv, &tdata);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    /* Send initial INVITE request.      * From now on, the invite session's state will be reported to us     * via the invite session callbacks.     */    status = pjsip_inv_send_msg(call->inv, tdata);    PJ_ASSERT_RETURN(status == PJ_SUCCESS, status);    return PJ_SUCCESS;}/* * Verify that valid SIP url is given. */static pj_status_t verify_sip_url(const char *c_url){    pjsip_uri *p;    pj_pool_t *pool;    char *url;    int len = (c_url ? pj_ansi_strlen(c_url) : 0);    if (!len) return -1;    pool = pj_pool_create(&app.cp.factory, "check%p", 1024, 0, NULL);    if (!pool) return PJ_ENOMEM;    url = pj_pool_alloc(pool, len+1);    pj_ansi_strcpy(url, c_url);    url[len] = '\0';    p = pjsip_parse_uri(pool, url, len, 0);    if (!p || pj_stricmp2(pjsip_uri_get_scheme(p), "sip") != 0)	p = NULL;    pj_pool_release(pool);    return p ? 0 : -1;}static void usage(void){    printf(	"Usage:\n"	"   pjsip-perf [OPTIONS]        -- to start as server\n"	"   pjsip-perf [OPTIONS] URL    -- to call server (possibly itself)\n"	"\n"	"where:\n"	"   URL                     The SIP URL to be contacted.\n"	"\n"	"Client options:\n"	"   --method=METHOD, -m     Set test method (set to INVITE for call benchmark)\n"        "                           [default: OPTIONS]\n"	"   --count=N, -n           Set total number of requests to initiate\n"	"                           [default=%d]\n"	"   --stateless, -s         Set to operate in stateless mode\n"	"                           [default: stateful]\n"	"   --timeout=SEC, -t       Set client timeout [default=60 sec]\n"	"   --window=COUNT, -w      Set maximum outstanding job [default: %d]\n"	"\n"	"SDP options (client and server):\n"	"   --real-sdp              Generate real SDP from pjmedia, and also perform\n"	"                           proper SDP negotiation [default: dummy]\n"	"\n"	"Client and Server options:\n"	"   --local-port=PORT, -p   Set local port [default: 5060]\n"	"   --use-tcp, -T           Use TCP instead of UDP. Note that when started as\n"	"                           client, you must add ;transport=tcp parameter to URL\n"	"                           [default: no]\n"	"   --thread-count=N        Set number of worker threads [default=1]\n"	"   --trying                Send 100/Trying response (server, default no)\n"	"   --ringing               Send 180/Ringing response (server, default no)\n"	"   --delay=MS, -d          Delay answering call by MS (server, default no)\n"	"\n"	"Misc options:\n"	"   --help, -h              Display this screen\n"	"   --verbose, -v           Verbose logging (put more than once for even more)\n"	"\n"	"When started as server, pjsip-perf can be contacted on the following URIs:\n"	"   - sip:0@server-addr     To handle requests statelessly.\n"	"   - sip:1@server-addr     To handle requests statefully.\n"	"   - sip:2@server-addr     To handle INVITE call.\n",	DEFAULT_COUNT, JOB_WINDOW);}static int my_atoi(const char *s){    pj_str_t ss = pj_str((char*)s);    return pj_strtoul(&ss);}static pj_status_t init_options(int argc, char *argv[]){    enum { OPT_THREAD_COUNT = 1, OPT_REAL_SDP, OPT_TRYING, OPT_RINGING };    struct pj_getopt_option long_options[] = {	{ "local-port",	    1, 0, 'p' },	{ "count",	    1, 0, 'c' },	{ "thread-count",   1, 0, OPT_THREAD_COUNT },	{ "method",	    1, 0, 'm' },	{ "help",	    0, 0, 'h' },	{ "stateless",	    0, 0, 's' },	{ "timeout",	    1, 0, 't' },	{ "real-sdp",	    0, 0, OPT_REAL_SDP },	{ "verbose",        0, 0, 'v' },	{ "use-tcp",	    0, 0, 'T' },	{ "window",	    1, 0, 'w' },	{ "delay",	    1, 0, 'd' },	{ "trying",	    0, 0, OPT_TRYING},	{ "ringing",	    0, 0, OPT_RINGING},	{ NULL, 0, 0, 0 },    };    int c;    int option_index;    /* Init default application configs */    app.local_port = 5060;    app.thread_count = 1;    app.client.job_count = DEFAULT_COUNT;    app.client.method = pjsip_options_method;    app.client.job_window = c = JOB_WINDOW;    app.client.timeout = 60;    app.log_level = 3;    /* Parse options */    pj_optind = 0;    while((c=pj_getopt_long(argc,argv, "p:c:m:t:w:d:hsv", 			    long_options, &option_index))!=-1)     {	switch (c) {	case 'p':	    app.local_port = my_atoi(pj_optarg);	    if (app.local_port < 0 || app.local_port > 65535) {		PJ_LOG(3,(THIS_FILE, "Invalid --local-port %s", pj_optarg));		return -1;	    }	    break;	case 'c':	    app.client.job_count = my_atoi(pj_optarg);	    if (app.client.job_count < 0) {		PJ_LOG(3,(THIS_FILE, "Invalid --local-port %s", pj_optarg));		return -1;	    }	    if (app.client.job_count > PJSIP_MAX_TSX_COUNT)		PJ_LOG(3,(THIS_FILE, 			  "Warning: --count value (%d) exceeds maximum "			  "transaction count (%d)", app.client.job_count,			  PJSIP_MAX_TSX_COUNT));	    break;	case OPT_THREAD_COUNT:	    app.thread_count = my_atoi(pj_optarg);	    if (app.thread_count < 1 || app.thread_count > 16) {		PJ_LOG(3,(THIS_FILE, "Invalid --thread-count %s", pj_optarg));		return -1;	    }	    break;	case 'm':	    {		pj_str_t temp = pj_str((char*)pj_optarg);		pjsip_method_init_np(&app.client.method, &temp);	    }	    break;	case 'h':	    usage();	    return -1;	case 's':	    app.client.stateless = PJ_TRUE;	    break;	case OPT_REAL_SDP:	    app.real_sdp = 1;	    break;	case 'v':	    app.log_level++;	    break;	case 't':	    app.client.timeout = my_atoi(pj_optarg);	    if (app.client.timeout < 0 || app.client.timeout > 600) {		PJ_LOG(3,(THIS_FILE, "Invalid --timeout %s", pj_optarg));		return -1;	    }	    break;	case 'w':	    app.client.job_window = my_atoi(pj_optarg);	    if (app.client.job_window <= 0) {		PJ_LOG(3,(THIS_FILE, "Invalid --window %s", pj_optarg));		return -1;	    }	    break;	case 'T':	    app.use_tcp = PJ_TRUE;	    break;	case 'd':	    app.server.delay = my_atoi(pj_optarg);	    if (app.server.delay > 3600) {		PJ_LOG(3,(THIS_FILE, "I think --delay %s is too long", 			  pj_optarg));		return -1;	    }	    break;	case OPT_TRYING:	    app.server.send_trying = 1;	    break;	case OPT_RINGING:	    app.server.send_ringing = 1;	    break;	default:	    PJ_LOG(1,(THIS_FILE, 		      "Invalid argument. Use --help to see help"));	    return -1;	}    }    if (pj_optind != argc) {	if (verify_sip_url(argv[pj_optind]) != PJ_SUCCESS) {	    PJ_LOG(1,(THIS_FILE, "Invalid SIP URI %s", argv[pj_optind]));	    return -1;	}	app.client.dst_uri = pj_str(argv[pj_optind]);		pj_optind++;    }    if (pj_optind != argc) {	PJ_LOG(1,(THIS_FILE, "Error: unknown options %s", argv[pj_optind]));	return -1;    }    return 0;}/* Send one stateless request */static pj_status_t submit_stateless_job(void){    pjsip_tx_data *tdata;    pj_status_t status;    status = pjsip_endpt_create_request(app.sip_endpt, &app.client.method, 					&app.client.dst_uri, &app.local_uri,					&app.client.dst_uri, &app.local_contact,					NULL, -1, NULL, &tdata);    if (status != PJ_SUCCESS) {	app_perror(THIS_FILE, "Error creating request", status);	report_completion(701);	return status;    }    status = pjsip_endpt_send_request_stateless(app.sip_endpt, tdata, NULL,						NULL);    if (status != PJ_SUCCESS) {	pjsip_tx_data_dec_ref(tdata);	app_perror(THIS_FILE, "Error sending stateless request", status);	report_completion(701);	return status;    }    return PJ_SUCCESS;}/* This callback is called when client transaction state has changed */static void tsx_completion_cb(void *token, pjsip_event *event){    pjsip_transaction *tsx;    PJ_UNUSED_ARG(token);    if (event->type != PJSIP_EVENT_TSX_STATE)	return;    tsx = event->body.tsx_state.tsx;    if (tsx->mod_data[mod_test.id] != NULL) {	/* This transaction has been calculated before */	return;    }    if (tsx->state==PJSIP_TSX_STATE_TERMINATED) {	report_completion(tsx->status_code);	tsx->mod_data[mod_test.id] = (void*)1;    }    else if (tsx->method.id == PJSIP_INVITE_METHOD &&	     tsx->state == PJSIP_TSX_STATE_CONFIRMED) {	report_completion(tsx->status_code);	tsx->mod_data[mod_test.id] = (void*)1;	    } else if (tsx->state == PJSIP_TSX_STATE_COMPLETED) {	report_completion(tsx->status_code);	tsx->mod_data[mod_test.id] = (void*)1;	TERMINATE_TSX(tsx, tsx->status_code);    }}

⌨️ 快捷键说明

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