📄 siprtp.c
字号:
/* 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 + -