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

📄 siprtp.c

📁 一个开源SIP协议栈
💻 C
📖 第 1 页 / 共 4 页
字号:
	/* Bytes */
	MIN_(min_stat.rx.bytes, audio->rtcp.stat.rx.bytes);
	MAX_(max_stat.rx.bytes, audio->rtcp.stat.rx.bytes);
	AVG_(avg_stat.rx.bytes, audio->rtcp.stat.rx.bytes);


	/* Packet loss */
	MIN_(min_stat.rx.loss, audio->rtcp.stat.rx.loss);
	MAX_(max_stat.rx.loss, audio->rtcp.stat.rx.loss);
	AVG_(avg_stat.rx.loss, audio->rtcp.stat.rx.loss);

	/* Packet dup */
	MIN_(min_stat.rx.dup, audio->rtcp.stat.rx.dup);
	MAX_(max_stat.rx.dup, audio->rtcp.stat.rx.dup);
	AVG_(avg_stat.rx.dup, audio->rtcp.stat.rx.dup);

	/* Packet reorder */
	MIN_(min_stat.rx.reorder, audio->rtcp.stat.rx.reorder);
	MAX_(max_stat.rx.reorder, audio->rtcp.stat.rx.reorder);
	AVG_(avg_stat.rx.reorder, audio->rtcp.stat.rx.reorder);

	/* Jitter  */
	MIN_(min_stat.rx.jitter.min, audio->rtcp.stat.rx.jitter.min);
	MAX_(max_stat.rx.jitter.max, audio->rtcp.stat.rx.jitter.max);
	AVG_(avg_stat.rx.jitter.avg, audio->rtcp.stat.rx.jitter.avg);


	/* TX Statistisc: */

	/* Packets */
	MIN_(min_stat.tx.pkt, audio->rtcp.stat.tx.pkt);
	MAX_(max_stat.tx.pkt, audio->rtcp.stat.tx.pkt);
	AVG_(avg_stat.tx.pkt, audio->rtcp.stat.tx.pkt);

	/* Bytes */
	MIN_(min_stat.tx.bytes, audio->rtcp.stat.tx.bytes);
	MAX_(max_stat.tx.bytes, audio->rtcp.stat.tx.bytes);
	AVG_(avg_stat.tx.bytes, audio->rtcp.stat.tx.bytes);

	/* Packet loss */
	MIN_(min_stat.tx.loss, audio->rtcp.stat.tx.loss);
	MAX_(max_stat.tx.loss, audio->rtcp.stat.tx.loss);
	AVG_(avg_stat.tx.loss, audio->rtcp.stat.tx.loss);

	/* Packet dup */
	MIN_(min_stat.tx.dup, audio->rtcp.stat.tx.dup);
	MAX_(max_stat.tx.dup, audio->rtcp.stat.tx.dup);
	AVG_(avg_stat.tx.dup, audio->rtcp.stat.tx.dup);

	/* Packet reorder */
	MIN_(min_stat.tx.reorder, audio->rtcp.stat.tx.reorder);
	MAX_(max_stat.tx.reorder, audio->rtcp.stat.tx.reorder);
	AVG_(avg_stat.tx.reorder, audio->rtcp.stat.tx.reorder);

	/* Jitter  */
	MIN_(min_stat.tx.jitter.min, audio->rtcp.stat.tx.jitter.min);
	MAX_(max_stat.tx.jitter.max, audio->rtcp.stat.tx.jitter.max);
	AVG_(avg_stat.tx.jitter.avg, audio->rtcp.stat.tx.jitter.avg);


	/* RTT */
	MIN_(min_stat.rtt.min, audio->rtcp.stat.rtt.min);
	MAX_(max_stat.rtt.max, audio->rtcp.stat.rtt.max);
	AVG_(avg_stat.rtt.avg, audio->rtcp.stat.rtt.avg);

	++count;
    }

    if (count == 0) {
	puts("No active calls");
	return;
    }

    printf("Total %d call(s) active.\n"
	   "                    Average Statistics\n"
	   "                    min     avg     max \n"
	   "                -----------------------\n"
	   " call duration: %7d %7d %7d %s\n"
	   " connect delay: %7d %7d %7d %s\n"
	   " RX stat:\n"
	   "       packets: %7s %7s %7s %s\n"
	   "       payload: %7s %7s %7s %s\n"
	   "          loss: %7d %7d %7d %s\n"
	   "  percent loss: %7.3f %7.3f %7.3f %s\n"
	   "           dup: %7d %7d %7d %s\n"
	   "       reorder: %7d %7d %7d %s\n"
	   "        jitter: %7.3f %7.3f %7.3f %s\n"
	   " TX stat:\n"
	   "       packets: %7s %7s %7s %s\n"
	   "       payload: %7s %7s %7s %s\n"
	   "          loss: %7d %7d %7d %s\n"
	   "  percent loss: %7.3f %7.3f %7.3f %s\n"
	   "           dup: %7d %7d %7d %s\n"
	   "       reorder: %7d %7d %7d %s\n"
	   "        jitter: %7.3f %7.3f %7.3f %s\n"
	   " RTT          : %7.3f %7.3f %7.3f %s\n"
	   ,
	   count,
	   call_dur.min/1000, call_dur.avg/1000, call_dur.max/1000, 
	   "seconds",

	   call_pdd.min, call_pdd.avg, call_pdd.max, 
	   "ms",

	   /* rx */

	   good_number(srx_min, min_stat.rx.pkt),
	   good_number(srx_avg, avg_stat.rx.pkt),
	   good_number(srx_max, max_stat.rx.pkt),
	   "packets",

	   good_number(brx_min, min_stat.rx.bytes),
	   good_number(brx_avg, avg_stat.rx.bytes),
	   good_number(brx_max, max_stat.rx.bytes),
	   "bytes",

	   min_stat.rx.loss, avg_stat.rx.loss, max_stat.rx.loss,
	   "packets",
	   
	   min_stat.rx.loss*100.0/(min_stat.rx.pkt+min_stat.rx.loss),
	   avg_stat.rx.loss*100.0/(avg_stat.rx.pkt+avg_stat.rx.loss),
	   max_stat.rx.loss*100.0/(max_stat.rx.pkt+max_stat.rx.loss),
	   "%",


	   min_stat.rx.dup, avg_stat.rx.dup, max_stat.rx.dup,
	   "packets",

	   min_stat.rx.reorder, avg_stat.rx.reorder, max_stat.rx.reorder,
	   "packets",

	   min_stat.rx.jitter.min/1000.0, 
	   avg_stat.rx.jitter.avg/1000.0, 
	   max_stat.rx.jitter.max/1000.0,
	   "ms",
	
	   /* tx */

	   good_number(stx_min, min_stat.tx.pkt),
	   good_number(stx_avg, avg_stat.tx.pkt),
	   good_number(stx_max, max_stat.tx.pkt),
	   "packets",

	   good_number(btx_min, min_stat.tx.bytes),
	   good_number(btx_avg, avg_stat.tx.bytes),
	   good_number(btx_max, max_stat.tx.bytes),
	   "bytes",

	   min_stat.tx.loss, avg_stat.tx.loss, max_stat.tx.loss,
	   "packets",
	   
	   min_stat.tx.loss*100.0/(min_stat.tx.pkt+min_stat.tx.loss),
	   avg_stat.tx.loss*100.0/(avg_stat.tx.pkt+avg_stat.tx.loss),
	   max_stat.tx.loss*100.0/(max_stat.tx.pkt+max_stat.tx.loss),
	   "%",

	   min_stat.tx.dup, avg_stat.tx.dup, max_stat.tx.dup,
	   "packets",

	   min_stat.tx.reorder, avg_stat.tx.reorder, max_stat.tx.reorder,
	   "packets",

	   min_stat.tx.jitter.min/1000.0, 
	   avg_stat.tx.jitter.avg/1000.0, 
	   max_stat.tx.jitter.max/1000.0,
	   "ms",

	   /* rtt */
	   min_stat.rtt.min/1000.0, 
	   avg_stat.rtt.avg/1000.0, 
	   max_stat.rtt.max/1000.0,
	   "ms"
	   );

}


#include "siprtp_report.c"


static void list_calls()
{
    unsigned i;
    puts("List all calls:");
    for (i=0; i<app.max_calls; ++i) {
	if (!app.call[i].inv)
	    continue;
	print_call(i);
    }
}

static void hangup_call(unsigned index)
{
    pjsip_tx_data *tdata;
    pj_status_t status;

    if (app.call[index].inv == NULL)
	return;

    status = pjsip_inv_end_session(app.call[index].inv, 603, NULL, &tdata);
    if (status==PJ_SUCCESS && tdata!=NULL)
	pjsip_inv_send_msg(app.call[index].inv, tdata);
}

static void hangup_all_calls()
{
    unsigned i;
    for (i=0; i<app.max_calls; ++i) {
	if (!app.call[i].inv)
	    continue;
	hangup_call(i);
    }
    
    /* Wait until all calls are terminated */
    for (i=0; i<app.max_calls; ++i) {
	while (app.call[i].inv)
	    pj_thread_sleep(10);
    }
}

static pj_bool_t simple_input(const char *title, char *buf, pj_size_t len)
{
    char *p;

    printf("%s (empty to cancel): ", title); fflush(stdout);
    fgets(buf, len, stdin);

    /* Remove trailing newlines. */
    for (p=buf; ; ++p) {
	if (*p=='\r' || *p=='\n') *p='\0';
	else if (!*p) break;
    }

    if (!*buf)
	return PJ_FALSE;
    
    return PJ_TRUE;
}


static const char *MENU =
"\n"
"Enter menu character:\n"
"  s    Summary\n"
"  l    List all calls\n"
"  h    Hangup a call\n"
"  H    Hangup all calls\n"
"  q    Quit\n"
"\n";


/* Main screen menu */
static void console_main()
{
    char input1[10];
    unsigned i;

    printf("%s", MENU);

    for (;;) {
	printf(">>> "); fflush(stdout);
	fgets(input1, sizeof(input1), stdin);

	switch (input1[0]) {

	case 's':
	    print_avg_stat();
	    break;

	case 'l':
	    list_calls();
	    break;

	case 'h':
	    if (!simple_input("Call number to hangup", input1, sizeof(input1)))
		break;

	    i = atoi(input1);
	    hangup_call(i);
	    break;

	case 'H':
	    hangup_all_calls();
	    break;

	case 'q':
	    goto on_exit;

	default:
	    puts("Invalid command");
	    printf("%s", MENU);
	    break;
	}

	fflush(stdout);
    }

on_exit:
    hangup_all_calls();
}


/*****************************************************************************
 * Below is a simple module to log all incoming and outgoing SIP messages
 */


/* Notification on incoming messages */
static pj_bool_t logger_on_rx_msg(pjsip_rx_data *rdata)
{
    PJ_LOG(4,(THIS_FILE, "RX %d bytes %s from %s:%d:\n"
			 "%s\n"
			 "--end msg--",
			 rdata->msg_info.len,
			 pjsip_rx_data_get_info(rdata),
			 rdata->pkt_info.src_name,
			 rdata->pkt_info.src_port,
			 rdata->msg_info.msg_buf));
    
    /* Always return false, otherwise messages will not get processed! */
    return PJ_FALSE;
}

/* Notification on outgoing messages */
static pj_status_t logger_on_tx_msg(pjsip_tx_data *tdata)
{
    
    /* Important note:
     *	tp_info field is only valid after outgoing messages has passed
     *	transport layer. So don't try to access tp_info when the module
     *	has lower priority than transport layer.
     */

    PJ_LOG(4,(THIS_FILE, "TX %d bytes %s to %s:%d:\n"
			 "%s\n"
			 "--end msg--",
			 (tdata->buf.cur - tdata->buf.start),
			 pjsip_tx_data_get_info(tdata),
			 tdata->tp_info.dst_name,
			 tdata->tp_info.dst_port,
			 tdata->buf.start));

    /* Always return success, otherwise message will not get sent! */
    return PJ_SUCCESS;
}

/* The module instance. */
static pjsip_module msg_logger = 
{
    NULL, NULL,				/* prev, next.		*/
    { "mod-siprtp-log", 14 },		/* Name.		*/
    -1,					/* Id			*/
    PJSIP_MOD_PRIORITY_TRANSPORT_LAYER-1,/* Priority	        */
    NULL,				/* load()		*/
    NULL,				/* start()		*/
    NULL,				/* stop()		*/
    NULL,				/* unload()		*/
    &logger_on_rx_msg,			/* on_rx_request()	*/
    &logger_on_rx_msg,			/* on_rx_response()	*/
    &logger_on_tx_msg,			/* on_tx_request.	*/
    &logger_on_tx_msg,			/* on_tx_response()	*/
    NULL,				/* on_tsx_state()	*/

};



/*****************************************************************************
 * Console application custom logging:
 */


static FILE *log_file;


static void app_log_writer(int level, const char *buffer, int len)
{
    /* Write to both stdout and file. */

    if (level <= app.app_log_level)
	pj_log_write(level, buffer, len);

    if (log_file) {
	fwrite(buffer, len, 1, log_file);
	fflush(log_file);
    }
}


pj_status_t app_logging_init(void)
{
    /* Redirect log function to ours */

    pj_log_set_log_func( &app_log_writer );

    /* If output log file is desired, create the file: */

    if (app.log_filename) {
	log_file = fopen(app.log_filename, "wt");
	if (log_file == NULL) {
	    PJ_LOG(1,(THIS_FILE, "Unable to open log file %s", 
		      app.log_filename));   
	    return -1;
	}
    }

    return PJ_SUCCESS;
}


void app_logging_shutdown(void)
{
    /* Close logging file, if any: */

    if (log_file) {
	fclose(log_file);
	log_file = NULL;
    }
}


/*
 * main()
 */
int main(int argc, char *argv[])
{
    unsigned i;
    pj_status_t status;

    /* Must init PJLIB first */
    status = pj_init();
    if (status != PJ_SUCCESS)
	return 1;

    /* Get command line options */
    status = init_options(argc, argv);
    if (status != PJ_SUCCESS)
	return 1;

    /* Verify options: */

    /* Auto-quit can not be specified for UAS */
    if (app.auto_quit && app.uri_to_call.slen == 0) {
	printf("Error: --auto-quit option only valid for outgoing "
	       "mode (UAC) only\n");
	return 1;
    }

    /* Init logging */
    status = app_logging_init();
    if (status != PJ_SUCCESS)
	return 1;

    /* Init SIP etc */
    status = init_sip();
    if (status != PJ_SUCCESS) {
	app_perror(THIS_FILE, "Initialization has failed", status);
	destroy_sip();
	return 1;
    }

    /* Register module to log incoming/outgoing messages */
    pjsip_endpt_register_module(app.sip_endpt, &msg_logger);

    /* Init media */
    status = init_media();
    if (status != PJ_SUCCESS) {
	app_perror(THIS_FILE, "Media initialization failed", status);
	destroy_sip();
	return 1;
    }

    /* Start worker threads */
    for (i=0; i<app.thread_count; ++i) {
	pj_thread_create( app.pool, "app", &sip_worker_thread, NULL,
			  0, 0, &app.sip_thread[i]);
    }

    /* If URL is specified, then make call immediately */
    if (app.uri_to_call.slen) {
	unsigned i;

	PJ_LOG(3,(THIS_FILE, "Making %d calls to %s..", app.max_calls,
		  app.uri_to_call.ptr));

	for (i=0; i<app.max_calls; ++i) {
	    status = make_call(&app.uri_to_call);
	    if (status != PJ_SUCCESS) {
		app_perror(THIS_FILE, "Error making call", status);
		break;
	    }
	}

	if (app.auto_quit) {
	    /* Wait for calls to complete */
	    while (app.uac_calls < app.max_calls)
		pj_thread_sleep(100);
	    pj_thread_sleep(200);
	} else {
	    /* Start user interface loop */
	    console_main();
	}

    } else {

	PJ_LOG(3,(THIS_FILE, "Ready for incoming calls (max=%d)", 
		  app.max_calls));

	/* Start user interface loop */
	console_main();

    }

    
    /* Shutting down... */
    destroy_sip();
    destroy_media();

    if (app.pool) {
	pj_pool_release(app.pool);
	app.pool = NULL;
	pj_caching_pool_destroy(&app.cp);
    }

    app_logging_shutdown();

    /* Shutdown PJLIB */
    pj_shutdown();

    return 0;
}

⌨️ 快捷键说明

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