Home --> Documentations --> PJSIP Reference
This source is an example to demonstrate using SIP and RTP/RTCP framework to measure the network quality/impairment from the SIP call. This program can be used to make calls or to receive calls from other SIP endpoint (or other siprtp program), and to display the media quality statistics at the end of the call.
Note that the remote peer must support RTCP.
The layout of the program has been designed so that custom reporting can be generated instead of plain human readable text.
The source code of the file is pjsip-apps/src/samples/siprtp.c
Screenshots on WinXP:
25static const char *USAGE =
27" This program establishes SIP INVITE session and media, and calculate \n"
28" the media quality (packet lost, jitter, rtt, etc.). Unlike normal \n"
29" pjmedia applications, this program bypasses all pjmedia stream \n"
30" framework and transmit encoded RTP packets manually using own thread. \n"
33" siprtp [options] => to start in server mode\n"
34" siprtp [options] URL => to start in client mode\n"
37" --count=N, -c Set number of calls to create (default:1) \n"
38" --gap=N -g Set call gapping to N msec (default:0)\n"
39" --duration=SEC, -d Set maximum call duration (default:unlimited) \n"
40" --auto-quit, -q Quit when calls have been completed (default:no)\n"
41" --call-report -R Display report on call termination (default:yes)\n"
43" Address and ports options:\n"
44" --local-port=PORT,-p Set local SIP port (default: 5060)\n"
45" --rtp-port=PORT, -r Set start of RTP port (default: 4000)\n"
46" --ip-addr=IP, -i Set local IP address to use (otherwise it will\n"
47" try to determine local IP address from hostname)\n"
50" --log-level=N, -l Set log verbosity level (default=5)\n"
51" --app-log-level=N Set app screen log verbosity (default=3)\n"
52" --log-file=FILE Write log to file FILE\n"
53" --report-file=FILE Write report to file FILE\n"
74#include <pjlib-util.h>
90#if PJ_HAS_HIGH_RES_TIMER==0
91# error "High resolution timer is needed for this sample"
94#define THIS_FILE "siprtp.c"
96#define RTP_START_PORT 4000
116 unsigned media_index;
127 unsigned samples_per_frame;
128 unsigned bytes_per_frame;
150 unsigned media_count;
169 unsigned thread_count;
179 char *report_filename;
181 struct codec audio_codec;
217static int sip_worker_thread( void *arg);
225static void hangup_call( unsigned index);
228static void destroy_call_media( unsigned call_index);
231static void destroy_media();
234static void on_rx_rtp( void *user_data, void *pkt, pj_ssize_t size);
237static void on_rx_rtcp( void *user_data, void *pkt, pj_ssize_t size);
240static void app_perror( const char *sender, const char *title,
244static void print_call( int call_index);
255 { "mod-siprtpapp", 13 },
271struct codec audio_codecs[] =
273 { 0, "PCMU", 8000, 64000, 20, "G.711 ULaw" },
274 { 3, "GSM", 8000, 13200, 20, "GSM" },
275 { 4, "G723", 8000, 6400, 30, "G.723.1" },
276 { 8, "PCMA", 8000, 64000, 20, "G.711 ALaw" },
277 { 18, "G729", 8000, 8000, 20, "G.729" },
297 app.pool = pj_pool_create(&app.cp.factory, "app", 1000, 1000, NULL);
316 if (app.local_addr.slen) {
318 addrname. host = app.local_addr;
319 addrname. port = app.sip_port;
324 app_perror(THIS_FILE, "Unable to resolve IP interface", status);
330 (app.local_addr.slen ? &addrname:NULL),
333 app_perror(THIS_FILE, "Unable to start UDP transport", status);
337 PJ_LOG(3,(THIS_FILE, "SIP UDP listening on %.*s:%d",
377 for (i=0; i<app.max_calls; ++i)
378 app.call[i].index = i;
388static void destroy_sip()
393 for (i=0; i<app.thread_count; ++i) {
394 if (app.sip_thread[i]) {
397 app.sip_thread[i] = NULL;
403 app.sip_endpt = NULL;
433#if defined(PJMEDIA_HAS_G711_CODEC) && PJMEDIA_HAS_G711_CODEC!=0
438 rtp_port = ( pj_uint16_t)(app.rtp_start_port & 0xFFFE);
441 for (i=0, count=0; i<app.max_calls; ++i, ++count) {
452 app.call[i].media[j].call_index = i;
453 app.call[i].media[j].media_index = j;
456 for (retry=0; retry<100; ++retry,rtp_port+=2) {
487static void destroy_media()
491 for (i=0; i<app.max_calls; ++i) {
505 app.med_endpt = NULL;
524 for (i=0; i<app.max_calls; ++i) {
525 if (app.call[i].inv == NULL)
529 if (i == app.max_calls)
598 for (i=0; i<app.max_calls; ++i) {
599 if (app.call[i].inv == NULL)
603 if (i == app.max_calls) {
616 app.sip_endpt, &tdata);
641 &app.local_contact, &dlg);
678 PJSIP_SC_NOT_ACCEPTABLE,
724 process_incoming_call(rdata);
740 hangup_call( call->index);
764 PJ_LOG(3,(THIS_FILE, "Call #%d disconnected. Reason=%d (%.*s)",
770 if (app.call_report) {
771 PJ_LOG(3,(THIS_FILE, "Call #%d statistics:", call->index));
772 print_call( call->index);
779 destroy_call_media( call->index);
781 call->start_time = null_time;
782 call->response_time = null_time;
783 call->connect_time = null_time;
792 if ( call->response_time.sec == 0)
793 call->response_time = call->connect_time;
795 t = call->connect_time;
798 PJ_LOG(3,(THIS_FILE, "Call #%d connected in %d ms", call->index,
801 if (app.duration != 0) {
806 t. sec = app.duration;
815 if ( call->response_time.sec == 0)
823static void app_perror( const char *sender, const char *title,
829 PJ_LOG(3,(sender, "%s: %s [status=%d]", title, errmsg, status));
834static int sip_worker_thread( void *arg)
838 while (!app.thread_quit) {
848static pj_status_t init_options( int argc, char *argv[])
851 static char local_uri[64];
854 OPT_APP_LOG_LEVEL, OPT_LOG_FILE,
855 OPT_A_PT, OPT_A_NAME, OPT_A_CLOCK, OPT_A_BITRATE, OPT_A_PTIME,
859 { "count", 1, 0, 'c' },
860 { "gap", 1, 0, 'g' },
861 { "call-report", 0, 0, 'R' },
862 { "duration", 1, 0, 'd' },
863 { "auto-quit", 0, 0, 'q' },
864 { "local-port", 1, 0, 'p' },
865 { "rtp-port", 1, 0, 'r' },
866 { "ip-addr", 1, 0, 'i' },
868 { "log-level", 1, 0, 'l' },
869 { "app-log-level", 1, 0, OPT_APP_LOG_LEVEL },
870 { "log-file", 1, 0, OPT_LOG_FILE },
872 { "report-file", 1, 0, OPT_REPORT_FILE },
900 app.thread_count = 1;
902 app.rtp_start_port = RTP_START_PORT;
903 app.local_addr = pj_str(ip_addr);
905 app.app_log_level = 3;
906 app.log_filename = NULL;
909 app.audio_codec = audio_codecs[0];
913 while((c=pj_getopt_long(argc,argv, "c:d:p:r:i:l:g:qR",
914 long_options, &option_index))!=-1)
918 app.max_calls = atoi(pj_optarg);
919 if (app.max_calls > MAX_CALLS) {
920 PJ_LOG(3,(THIS_FILE, "Invalid max calls value %s "
921 "(must be <= %d)", pj_optarg, MAX_CALLS));
926 app.call_gap = atoi(pj_optarg);
932 app.duration = atoi(pj_optarg);
939 app.sip_port = atoi(pj_optarg);
942 app.rtp_start_port = atoi(pj_optarg);
945 app.local_addr = pj_str(pj_optarg);
949 app.log_level = atoi(pj_optarg);
951 case OPT_APP_LOG_LEVEL:
952 app.app_log_level = atoi(pj_optarg);
955 app.log_filename = pj_optarg;
959 app.audio_codec.pt = atoi(pj_optarg);
962 app.audio_codec.name = pj_optarg;
965 app.audio_codec.clock_rate = atoi(pj_optarg);
968 app.audio_codec.bit_rate = atoi(pj_optarg);
971 app.audio_codec.ptime = atoi(pj_optarg);
973 case OPT_REPORT_FILE:
974 app.report_filename = pj_optarg;
984 if (pj_optind < argc)
985 app.uri_to_call = pj_str(argv[pj_optind]);
988 pj_ansi_sprintf( local_uri, "sip:%s:%d", app.local_addr.ptr, app.sip_port);
989 app.local_uri = pj_str(local_uri);
990 app.local_contact = app.local_uri;
1066 sprintf(ptstr, "%d", app.audio_codec.pt);
1069 rtpmap. clock_rate = app.audio_codec.clock_rate;
1106#if (defined(PJ_WIN32) && PJ_WIN32 != 0) || (defined(PJ_WIN64) && PJ_WIN64 != 0)
1108static void boost_priority( void)
1110 SetPriorityClass( GetCurrentProcess(), REALTIME_PRIORITY_CLASS);
1111 SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST);
1114#elif defined(PJ_LINUX) && PJ_LINUX != 0
1116static void boost_priority( void)
1118#define POLICY SCHED_FIFO
1119 struct sched_param tp;
1124 if (sched_get_priority_min(POLICY) < sched_get_priority_max(POLICY))
1125 max_prio = sched_get_priority_max(POLICY)-1;
1127 max_prio = sched_get_priority_max(POLICY)+1;
1132 rc = sched_getparam(0, &tp);
1134 app_perror( THIS_FILE, "sched_getparam error",
1138 tp.sched_priority = max_prio;
1140 rc = sched_setscheduler(0, POLICY, &tp);
1142 app_perror( THIS_FILE, "sched_setscheduler error",
1146 PJ_LOG(4, (THIS_FILE, "New process policy=%d, priority=%d",
1147 policy, tp.sched_priority));
1152 rc = pthread_getschedparam(pthread_self(), &policy, &tp);
1154 app_perror( THIS_FILE, "pthread_getschedparam error",
1159 PJ_LOG(4, (THIS_FILE, "Old thread policy=%d, priority=%d",
1160 policy, tp.sched_priority));
1163 tp.sched_priority = max_prio;
1165 rc = pthread_setschedparam(pthread_self(), policy, &tp);
1167 app_perror( THIS_FILE, "pthread_setschedparam error",
1172 PJ_LOG(4, (THIS_FILE, "New thread policy=%d, priority=%d",
1173 policy, tp.sched_priority));
1177# define boost_priority()
1184static void on_rx_rtp( void *user_data, void *pkt, pj_ssize_t size)
1189 const void *payload;
1190 unsigned payload_len;
1200 app_perror(THIS_FILE, "RTP recv() error", ( pj_status_t)-size);
1207 &hdr, &payload, &payload_len);
1209 app_perror(THIS_FILE, "RTP decode error", status);
1227static void on_rx_rtcp( void *user_data, void *pkt, pj_ssize_t size)
1239 app_perror(THIS_FILE, "Error receiving RTCP packet",( pj_status_t)-size);
1253static int media_thread( void *arg)
1255 enum { RTCP_INTERVAL = 5000, RTCP_RAND = 2000 };
1258 unsigned msec_interval;
1268 msec_interval = strm->samples_per_frame * 1000 / strm->clock_rate;
1272 next_rtp.u64 += (freq.u64 * msec_interval / 1000);
1274 next_rtcp = next_rtp;
1275 next_rtcp.u64 += (freq.u64 * (RTCP_INTERVAL+( pj_rand()%RTCP_RAND)) / 1000);
1278 while (!strm->thread_quit_flag) {
1286 if (next_rtp.u64 < next_rtcp.u64) {
1295 if (lesser.u64 <= now.u64) {
1296 timeout. sec = timeout. msec = 0;
1299 pj_uint64_t tick_delay;
1300 tick_delay = lesser.u64 - now.u64;
1311 if (strm->thread_quit_flag)
1317 if (send_rtp || next_rtp.u64 <= now.u64) {
1330 strm->bytes_per_frame,
1331 strm->samples_per_frame,
1343 pj_bzero(packet+hdrlen, strm->bytes_per_frame);
1346 size = hdrlen + strm->bytes_per_frame;
1350 app_perror(THIS_FILE, "Error sending RTP packet", status);
1360 next_rtp.u64 += (msec_interval * freq.u64 / 1000);
1364 if (send_rtcp || next_rtcp.u64 <= now.u64) {
1382 app_perror(THIS_FILE, "Error sending RTCP packet", status);
1386 next_rtcp.u64 += (freq.u64 * (RTCP_INTERVAL+( pj_rand()%RTCP_RAND)) /
1402 struct codec *codec_desc = NULL;
1406 audio = & call->media[0];
1409 if (audio->thread != NULL)
1410 destroy_call_media( call->index);
1415 app_perror(THIS_FILE, "SDP negotiation failed", status);
1425 local_sdp, remote_sdp, 0);
1427 app_perror(THIS_FILE, "Error creating stream info from SDP", status);
1432 if (audio->si.fmt.pt == app.audio_codec.pt)
1433 codec_desc = &app.audio_codec;
1437 if (audio_codecs[i].pt == audio->si.fmt.pt) {
1438 codec_desc = &audio_codecs[i];
1443 if (codec_desc == NULL) {
1444 PJ_LOG(3, (THIS_FILE, "Error: Invalid codec payload type"));
1449 audio->clock_rate = audio->si.fmt.clock_rate;
1450 audio->samples_per_frame = audio->clock_rate * codec_desc->ptime / 1000;
1451 audio->bytes_per_frame = codec_desc->bit_rate * codec_desc->ptime / 1000 / 8;
1458 audio->samples_per_frame, 0);
1463 &audio->si.rem_addr,
1464 &audio->si.rem_rtcp,
1469 app_perror(THIS_FILE, "Error on pjmedia_transport_attach()", status);
1477 audio->thread_quit_flag = 0;
1480 0, 0, &audio->thread);
1482 app_perror(THIS_FILE, "Error creating media thread", status);
1494static void destroy_call_media( unsigned call_index)
1496 struct media_stream *audio = &app.call[call_index].media[0];
1501 if (audio->thread) {
1502 audio->thread_quit_flag = 1;
1505 audio->thread = NULL;
1506 audio->thread_quit_flag = 0;
1518static void call_get_duration( int call_index, pj_time_val *dur)
1520 struct call * call = &app.call[call_index];
1540static const char *good_number( char *buf, pj_int32_t val)
1543 pj_ansi_sprintf(buf, "%d", val);
1544 } else if (val < 1000000) {
1545 pj_ansi_sprintf(buf, "%d.%02dK",
1547 (val % 1000) / 100);
1549 pj_ansi_sprintf(buf, "%d.%02dM",
1551 (val % 1000000) / 10000);
1559static void print_avg_stat( void)
1561#define MIN_(var,val) if ((int)val < (int)var) var = val
1562#define MAX_(var,val) if ((int)val > (int)var) var = val
1563#define AVG_(var,val) var = ( ((var * count) + val) / (count+1) )
1564#define BIGVAL 0x7FFFFFFFL
1570 struct stat_entry call_dur, call_pdd;
1573 char srx_min[16], srx_avg[16], srx_max[16];
1574 char brx_min[16], brx_avg[16], brx_max[16];
1575 char stx_min[16], stx_avg[16], stx_max[16];
1576 char btx_min[16], btx_avg[16], btx_max[16];
1581 pj_bzero(&call_dur, sizeof(call_dur));
1582 call_dur.min = BIGVAL;
1584 pj_bzero(&call_pdd, sizeof(call_pdd));
1585 call_pdd.min = BIGVAL;
1587 pj_bzero(&min_stat, sizeof(min_stat));
1588 min_stat.rx.pkt = min_stat.tx.pkt = BIGVAL;
1589 min_stat.rx.bytes = min_stat.tx.bytes = BIGVAL;
1590 min_stat.rx.loss = min_stat.tx.loss = BIGVAL;
1591 min_stat.rx.dup = min_stat.tx.dup = BIGVAL;
1592 min_stat.rx.reorder = min_stat.tx.reorder = BIGVAL;
1593 min_stat.rx.jitter.min = min_stat.tx.jitter.min = BIGVAL;
1594 min_stat.rtt.min = BIGVAL;
1596 pj_bzero(&avg_stat, sizeof(avg_stat));
1597 pj_bzero(&max_stat, sizeof(max_stat));
1600 for (i=0, count=0; i<app.max_calls; ++i) {
1607 if ( call->inv == NULL ||
1609 call->connect_time.sec == 0)
1615 call_get_duration(i, &dur);
1618 MIN_(call_dur.min, msec_dur);
1619 MAX_(call_dur.max, msec_dur);
1620 AVG_(call_dur.avg, msec_dur);
1623 if ( call->connect_time.sec) {
1631 MIN_(call_pdd.min, msec_dur);
1632 MAX_(call_pdd.max, msec_dur);
1633 AVG_(call_pdd.avg, msec_dur);
1638 MIN_(min_stat.rx.pkt, audio->rtcp.stat.rx.pkt);
1639 MAX_(max_stat.rx.pkt, audio->rtcp.stat.rx.pkt);
1640 AVG_(avg_stat.rx.pkt, audio->rtcp.stat.rx.pkt);
1643 MIN_(min_stat.rx.bytes, audio->rtcp.stat.rx.bytes);
1644 MAX_(max_stat.rx.bytes, audio->rtcp.stat.rx.bytes);
1645 AVG_(avg_stat.rx.bytes, audio->rtcp.stat.rx.bytes);
1649 MIN_(min_stat.rx.loss, audio->rtcp.stat.rx.loss);
1650 MAX_(max_stat.rx.loss, audio->rtcp.stat.rx.loss);
1651 AVG_(avg_stat.rx.loss, audio->rtcp.stat.rx.loss);
1654 MIN_(min_stat.rx.dup, audio->rtcp.stat.rx.dup);
1655 MAX_(max_stat.rx.dup, audio->rtcp.stat.rx.dup);
1656 AVG_(avg_stat.rx.dup, audio->rtcp.stat.rx.dup);
1659 MIN_(min_stat.rx.reorder, audio->rtcp.stat.rx.reorder);
1660 MAX_(max_stat.rx.reorder, audio->rtcp.stat.rx.reorder);
1661 AVG_(avg_stat.rx.reorder, audio->rtcp.stat.rx.reorder);
1664 MIN_(min_stat.rx.jitter.min, audio->rtcp.stat.rx.jitter.min);
1665 MAX_(max_stat.rx.jitter.max, audio->rtcp.stat.rx.jitter.max);
1666 AVG_(avg_stat.rx.jitter.mean, audio->rtcp.stat.rx.jitter.mean);
1672 MIN_(min_stat.tx.pkt, audio->rtcp.stat.tx.pkt);
1673 MAX_(max_stat.tx.pkt, audio->rtcp.stat.tx.pkt);
1674 AVG_(avg_stat.tx.pkt, audio->rtcp.stat.tx.pkt);
1677 MIN_(min_stat.tx.bytes, audio->rtcp.stat.tx.bytes);
1678 MAX_(max_stat.tx.bytes, audio->rtcp.stat.tx.bytes);
1679 AVG_(avg_stat.tx.bytes, audio->rtcp.stat.tx.bytes);
1682 MIN_(min_stat.tx.loss, audio->rtcp.stat.tx.loss);
1683 MAX_(max_stat.tx.loss, audio->rtcp.stat.tx.loss);
1684 AVG_(avg_stat.tx.loss, audio->rtcp.stat.tx.loss);
1687 MIN_(min_stat.tx.dup, audio->rtcp.stat.tx.dup);
1688 MAX_(max_stat.tx.dup, audio->rtcp.stat.tx.dup);
1689 AVG_(avg_stat.tx.dup, audio->rtcp.stat.tx.dup);
1692 MIN_(min_stat.tx.reorder, audio->rtcp.stat.tx.reorder);
1693 MAX_(max_stat.tx.reorder, audio->rtcp.stat.tx.reorder);
1694 AVG_(avg_stat.tx.reorder, audio->rtcp.stat.tx.reorder);
1697 MIN_(min_stat.tx.jitter.min, audio->rtcp.stat.tx.jitter.min);
1698 MAX_(max_stat.tx.jitter.max, audio->rtcp.stat.tx.jitter.max);
1699 AVG_(avg_stat.tx.jitter.mean, audio->rtcp.stat.tx.jitter.mean);
1703 MIN_(min_stat.rtt.min, audio->rtcp.stat.rtt.min);
1704 MAX_(max_stat.rtt.max, audio->rtcp.stat.rtt.max);
1705 AVG_(avg_stat.rtt.mean, audio->rtcp.stat.rtt.mean);
1711 puts( "No active calls");
1715 printf( "Total %d call(s) active.\n"
1716 " Average Statistics\n"
1718 " -----------------------\n"
1719 " call duration: %7d %7d %7d %s\n"
1720 " connect delay: %7d %7d %7d %s\n"
1722 " packets: %7s %7s %7s %s\n"
1723 " payload: %7s %7s %7s %s\n"
1724 " loss: %7d %7d %7d %s\n"
1725 " percent loss: %7.3f %7.3f %7.3f %s\n"
1726 " dup: %7d %7d %7d %s\n"
1727 " reorder: %7d %7d %7d %s\n"
1728 " jitter: %7.3f %7.3f %7.3f %s\n"
1730 " packets: %7s %7s %7s %s\n"
1731 " payload: %7s %7s %7s %s\n"
1732 " loss: %7d %7d %7d %s\n"
1733 " percent loss: %7.3f %7.3f %7.3f %s\n"
1734 " dup: %7d %7d %7d %s\n"
1735 " reorder: %7d %7d %7d %s\n"
1736 " jitter: %7.3f %7.3f %7.3f %s\n"
1737 " RTT : %7.3f %7.3f %7.3f %s\n"
1740 call_dur.min/1000, call_dur.avg/1000, call_dur.max/1000,
1743 call_pdd.min, call_pdd.avg, call_pdd.max,
1748 good_number(srx_min, min_stat.rx.pkt),
1749 good_number(srx_avg, avg_stat.rx.pkt),
1750 good_number(srx_max, max_stat.rx.pkt),
1753 good_number(brx_min, min_stat.rx.bytes),
1754 good_number(brx_avg, avg_stat.rx.bytes),
1755 good_number(brx_max, max_stat.rx.bytes),
1758 min_stat.rx.loss, avg_stat.rx.loss, max_stat.rx.loss,
1761 min_stat.rx.loss*100.0/(min_stat.rx.pkt+min_stat.rx.loss),
1762 avg_stat.rx.loss*100.0/(avg_stat.rx.pkt+avg_stat.rx.loss),
1763 max_stat.rx.loss*100.0/(max_stat.rx.pkt+max_stat.rx.loss),
1767 min_stat.rx.dup, avg_stat.rx.dup, max_stat.rx.dup,
1770 min_stat.rx.reorder, avg_stat.rx.reorder, max_stat.rx.reorder,
1773 min_stat.rx.jitter.min/1000.0,
1774 avg_stat.rx.jitter.mean/1000.0,
1775 max_stat.rx.jitter.max/1000.0,
1780 good_number(stx_min, min_stat.tx.pkt),
1781 good_number(stx_avg, avg_stat.tx.pkt),
1782 good_number(stx_max, max_stat.tx.pkt),
1785 good_number(btx_min, min_stat.tx.bytes),
1786 good_number(btx_avg, avg_stat.tx.bytes),
1787 good_number(btx_max, max_stat.tx.bytes),
1790 min_stat.tx.loss, avg_stat.tx.loss, max_stat.tx.loss,
1793 min_stat.tx.loss*100.0/(min_stat.tx.pkt+min_stat.tx.loss),
1794 avg_stat.tx.loss*100.0/(avg_stat.tx.pkt+avg_stat.tx.loss),
1795 max_stat.tx.loss*100.0/(max_stat.tx.pkt+max_stat.tx.loss),
1798 min_stat.tx.dup, avg_stat.tx.dup, max_stat.tx.dup,
1801 min_stat.tx.reorder, avg_stat.tx.reorder, max_stat.tx.reorder,
1804 min_stat.tx.jitter.min/1000.0,
1805 avg_stat.tx.jitter.mean/1000.0,
1806 max_stat.tx.jitter.max/1000.0,
1810 min_stat.rtt.min/1000.0,
1811 avg_stat.rtt.mean/1000.0,
1812 max_stat.rtt.max/1000.0,
1819#include "siprtp_report.c"
1822static void list_calls()
1825 puts( "List all calls:");
1826 for (i=0; i<app.max_calls; ++i) {
1827 if (!app.call[i].inv)
1833static void hangup_call( unsigned index)
1838 if (app.call[index].inv == NULL)
1846static void hangup_all_calls()
1849 for (i=0; i<app.max_calls; ++i) {
1850 if (!app.call[i].inv)
1857 for (i=0; i<app.max_calls; ++i) {
1858 while (app.call[i].inv)
1867 printf( "%s (empty to cancel): ", title); fflush(stdout);
1868 if (fgets(buf, ( int)len, stdin) == NULL)
1872 for (p=buf; ; ++p) {
1873 if (*p== '\r' || *p== '\n') *p= '\0';
1874 else if (!*p) break;
1884static const char *MENU =
1886"Enter menu character:\n"
1888" l List all calls\n"
1890" H Hangup all calls\n"
1896static void console_main()
1904 printf( ">>> "); fflush(stdout);
1905 if (fgets(input1, sizeof(input1), stdin) == NULL) {
1906 puts( "EOF while reading stdin, will quit now..");
1910 switch (input1[0]) {
1921 if (!simple_input( "Call number to hangup", input1, sizeof(input1)))
1936 puts( "Invalid command");
1957 PJ_LOG(4,(THIS_FILE, "RX %d bytes %s from %s:%d:\n"
1980 PJ_LOG(4,(THIS_FILE, "TX %d bytes %s to %s:%d:\n"
1997 { "mod-siprtp-log", 14 },
2019static FILE *log_file;
2022static void app_log_writer( int level, const char *buffer, int len)
2026 if (level <= app.app_log_level)
2030 pj_size_t count = fwrite(buffer, len, 1, log_file);
2045 if (app.log_filename) {
2046 log_file = fopen(app.log_filename, "wt");
2047 if (log_file == NULL) {
2048 PJ_LOG(1,(THIS_FILE, "Unable to open log file %s",
2058void app_logging_shutdown( void)
2072int main( int argc, char *argv[])
2083 status = init_options(argc, argv);
2090 if (app.auto_quit && app.uri_to_call.slen == 0) {
2091 printf( "Error: --auto-quit option only valid for outgoing "
2092 "mode (UAC) only\n");
2097 status = app_logging_init();
2102 status = init_sip();
2104 app_perror(THIS_FILE, "Initialization has failed", status);
2113 status = init_media();
2115 app_perror(THIS_FILE, "Media initialization failed", status);
2122 for (i=0; i<app.thread_count; ++i) {
2124 0, 0, &app.sip_thread[i]);
2129 if (app.uri_to_call.slen) {
2130 PJ_LOG(3,(THIS_FILE, "Making %d calls to %s..", app.max_calls,
2131 app.uri_to_call.ptr));
2133 for (i=0; i<app.max_calls; ++i) {
2134 status = make_call(&app.uri_to_call);
2136 app_perror(THIS_FILE, "Error making call", status);
2142 if (app.auto_quit) {
2144 while (app.uac_calls < app.max_calls)
2156 PJ_LOG(3,(THIS_FILE, "Ready for incoming calls (max=%d)",
2166 PJ_LOG(3,(THIS_FILE, "Press Ctrl-C to quit"));
2183 app_logging_shutdown();
pj_status_t pjlib_util_init(void)
pj_status_t pjmedia_endpt_create(pj_pool_factory *pf, pj_ioqueue_t *ioqueue, unsigned worker_cnt, pjmedia_endpt **p_endpt)
pj_status_t pjmedia_endpt_destroy(pjmedia_endpt *endpt)
pj_status_t pjmedia_codec_g711_init(pjmedia_endpt *endpt)
void pjmedia_rtcp_rx_rtcp(pjmedia_rtcp_session *session, const void *rtcp_pkt, pj_size_t size)
void pjmedia_rtcp_rx_rtp(pjmedia_rtcp_session *session, unsigned seq, unsigned ts, unsigned payload)
void pjmedia_rtcp_build_rtcp(pjmedia_rtcp_session *session, void **rtcp_pkt, int *len)
void pjmedia_rtcp_tx_rtp(pjmedia_rtcp_session *session, unsigned ptsize)
void pjmedia_rtcp_init(pjmedia_rtcp_session *session, char *name, unsigned clock_rate, unsigned samples_per_frame, pj_uint32_t ssrc)
pj_status_t pjmedia_rtp_encode_rtp(pjmedia_rtp_session *ses, int pt, int m, int payload_len, int ts_len, const void **rtphdr, int *hdrlen)
void pjmedia_rtp_session_update(pjmedia_rtp_session *ses, const pjmedia_rtp_hdr *hdr, pjmedia_rtp_status *seq_st)
pj_status_t pjmedia_rtp_decode_rtp(pjmedia_rtp_session *ses, const void *pkt, int pkt_len, const pjmedia_rtp_hdr **hdr, const void **payload, unsigned *payloadlen)
pj_status_t pjmedia_rtp_session_init(pjmedia_rtp_session *ses, int default_pt, pj_uint32_t sender_ssrc)
pj_status_t pjsip_100rel_init_module(pjsip_endpoint *endpt)
pj_status_t pjsip_dlg_send_response(pjsip_dialog *dlg, pjsip_transaction *tsx, pjsip_tx_data *tdata)
void pjsip_dlg_dec_lock(pjsip_dialog *dlg)
pj_status_t pjsip_dlg_create_response(pjsip_dialog *dlg, pjsip_rx_data *rdata, int st_code, const pj_str_t *st_text, pjsip_tx_data **tdata)
pj_status_t pjsip_dlg_create_uac(pjsip_user_agent *ua, const pj_str_t *local_uri, const pj_str_t *local_contact, const pj_str_t *remote_uri, const pj_str_t *target, pjsip_dialog **p_dlg)
pj_status_t pjsip_dlg_create_uas_and_inc_lock(pjsip_user_agent *ua, pjsip_rx_data *rdata, const pj_str_t *contact, pjsip_dialog **p_dlg)
pj_status_t pjsip_dlg_terminate(pjsip_dialog *dlg)
pj_status_t pjsip_endpt_respond_stateless(pjsip_endpoint *endpt, pjsip_rx_data *rdata, int st_code, const pj_str_t *st_text, const pjsip_hdr *hdr_list, const pjsip_msg_body *body)
pj_status_t pjsip_get_response_addr(pj_pool_t *pool, pjsip_rx_data *rdata, pjsip_response_addr *res_addr)
pj_status_t pjsip_endpt_send_response(pjsip_endpoint *endpt, pjsip_response_addr *res_addr, pjsip_tx_data *tdata, void *token, pjsip_send_callback cb)
void pjsip_endpt_destroy(pjsip_endpoint *endpt)
pj_status_t pjsip_endpt_register_module(pjsip_endpoint *endpt, pjsip_module *module)
pj_ioqueue_t * pjsip_endpt_get_ioqueue(pjsip_endpoint *endpt)
pj_status_t pjsip_endpt_handle_events(pjsip_endpoint *endpt, const pj_time_val *max_timeout)
pj_status_t pjsip_endpt_schedule_timer(pjsip_endpoint *endpt, pj_timer_entry *entry, const pj_time_val *delay)
void pjsip_endpt_cancel_timer(pjsip_endpoint *endpt, pj_timer_entry *entry)
pj_status_t pjsip_endpt_create(pj_pool_factory *pf, const char *name, pjsip_endpoint **endpt)
pj_status_t pjsip_inv_send_msg(pjsip_inv_session *inv, pjsip_tx_data *tdata)
pj_status_t pjsip_inv_end_session(pjsip_inv_session *inv, int st_code, const pj_str_t *st_text, pjsip_tx_data **p_tdata)
pj_status_t pjsip_inv_create_uas(pjsip_dialog *dlg, pjsip_rx_data *rdata, const pjmedia_sdp_session *local_sdp, unsigned options, pjsip_inv_session **p_inv)
pj_status_t pjsip_inv_create_uac(pjsip_dialog *dlg, const pjmedia_sdp_session *local_sdp, unsigned options, pjsip_inv_session **p_inv)
pj_status_t pjsip_inv_invite(pjsip_inv_session *inv, pjsip_tx_data **p_tdata)
pj_status_t pjsip_inv_initial_answer(pjsip_inv_session *inv, pjsip_rx_data *rdata, int st_code, const pj_str_t *st_text, const pjmedia_sdp_session *sdp, pjsip_tx_data **p_tdata)
pj_status_t pjsip_inv_verify_request(pjsip_rx_data *rdata, unsigned *options, const pjmedia_sdp_session *sdp, pjsip_dialog *dlg, pjsip_endpoint *endpt, pjsip_tx_data **tdata)
pj_status_t pjsip_inv_terminate(pjsip_inv_session *inv, int st_code, pj_bool_t notify)
pj_status_t pjsip_inv_usage_init(pjsip_endpoint *endpt, const pjsip_inv_callback *cb)
@ PJSIP_INV_STATE_EARLY Definition: sip_inv.h:92
@ PJSIP_INV_STATE_DISCONNECTED Definition: sip_inv.h:95
@ PJSIP_INV_STATE_CONNECTING Definition: sip_inv.h:93
@ PJSIP_INV_STATE_CONFIRMED Definition: sip_inv.h:94
@ PJSIP_MOD_PRIORITY_APPLICATION Definition: sip_module.h:210
@ PJSIP_MOD_PRIORITY_TRANSPORT_LAYER Definition: sip_module.h:190
@ PJSIP_ACK_METHOD Definition: sip_msg.h:58
@ PJSIP_INVITE_METHOD Definition: sip_msg.h:56
pj_status_t pjsip_tsx_layer_init_module(pjsip_endpoint *endpt)
pjsip_transaction * pjsip_rdata_get_tsx(pjsip_rx_data *rdata)
pj_status_t pjsip_udp_transport_start(pjsip_endpoint *endpt, const pj_sockaddr_in *local, const pjsip_host_port *a_name, unsigned async_cnt, pjsip_transport **p_transport)
char * pjsip_rx_data_get_info(pjsip_rx_data *rdata)
char * pjsip_tx_data_get_info(pjsip_tx_data *tdata)
pj_status_t pjsip_tx_data_dec_ref(pjsip_tx_data *tdata)
struct pjsip_endpoint pjsip_endpoint Definition: sip_types.h:111
pj_status_t pjsip_ua_init_module(pjsip_endpoint *endpt, const pjsip_ua_init_param *prm)
pjsip_user_agent * pjsip_ua_instance(void)
pj_status_t pj_init(void)
unsigned short pj_uint16_t
struct pj_thread_t pj_thread_t
struct pj_timer_heap_t pj_timer_heap_t
void pj_caching_pool_destroy(pj_caching_pool *ch_pool)
void pj_caching_pool_init(pj_caching_pool *ch_pool, const pj_pool_factory_policy *policy, pj_size_t max_capacity)
void pj_log_write(int level, const char *buffer, int len)
#define PJ_LOG(level, arg)
void pj_log_set_log_func(pj_log_func *func)
pj_pool_factory_policy pj_pool_factory_default_policy
#define PJ_POOL_ZALLOC_T(pool, type)
pj_pool_t * pj_pool_create(pj_pool_factory *factory, const char *name, pj_size_t initial_size, pj_size_t increment_size, pj_pool_callback *callback)
void pj_pool_release(pj_pool_t *pool)
void * pj_memcpy(void *dst, const void *src, pj_size_t size)
pj_str_t pj_str(char *str)
pj_str_t * pj_strdup2(pj_pool_t *pool, pj_str_t *dst, const char *src)
void pj_bzero(void *dst, pj_size_t size)
pj_uint16_t pj_htons(pj_uint16_t hostshort)
#define PJ_INET_ADDRSTRLEN
pj_status_t pj_inet_ntop(int af, const void *src, char *dst, int size)
const pj_str_t * pj_gethostname(void)
pj_uint32_t pj_ntohl(pj_uint32_t netlong)
pj_uint16_t pj_ntohs(pj_uint16_t netshort)
pj_status_t pj_sockaddr_in_init(pj_sockaddr_in *addr, const pj_str_t *cp, pj_uint16_t port)
pj_status_t pj_thread_destroy(pj_thread_t *thread)
pj_status_t pj_thread_join(pj_thread_t *thread)
pj_status_t pj_thread_create(pj_pool_t *pool, const char *thread_name, pj_thread_proc *proc, void *arg, pj_size_t stack_size, unsigned flags, pj_thread_t **thread)
pj_status_t pj_thread_sleep(unsigned msec)
pj_status_t pj_get_timestamp_freq(pj_timestamp *freq)
pj_status_t pj_get_timestamp(pj_timestamp *ts)
pj_status_t pj_gettimeofday(pj_time_val *tv)
void pj_time_val_normalize(pj_time_val *t)
#define PJ_TIME_VAL_MSEC(t)
#define PJ_TIME_VAL_SUB(t1, t2)
#define PJ_ASSERT_ON_FAIL(expr, exec_on_fail)
#define PJ_ASSERT_RETURN(expr, retval)
#define PJ_UNUSED_ARG(arg)
pj_str_t pj_strerror(pj_status_t statcode, char *buf, pj_size_t bufsize)
#define PJ_RETURN_OS_ERROR(os_code)
pj_timer_heap_callback * cb
char * start Definition: sip_types.h:207
char * cur Definition: sip_types.h:212
Definition: sip_dialog.h:136
pj_pool_t * pool Definition: sip_dialog.h:142
Definition: sip_event.h:81
Definition: sip_types.h:224
int port Definition: sip_types.h:226
pj_str_t host Definition: sip_types.h:225
Definition: sip_inv.h:115
void(* on_new_session)(pjsip_inv_session *inv, pjsip_event *e) Definition: sip_inv.h:141
void(* on_state_changed)(pjsip_inv_session *inv, pjsip_event *e) Definition: sip_inv.h:127
void(* on_media_update)(pjsip_inv_session *inv_ses, pj_status_t status) Definition: sip_inv.h:243
Definition: sip_inv.h:431
pjsip_status_code cause Definition: sip_inv.h:440
pj_str_t cause_text Definition: sip_inv.h:441
pjmedia_sdp_neg * neg Definition: sip_inv.h:449
pjsip_inv_state state Definition: sip_inv.h:436
void * mod_data[PJSIP_MAX_MODULE] Definition: sip_inv.h:456
pj_pool_t * pool Definition: sip_inv.h:433
pjsip_method_e id Definition: sip_msg.h:78
Definition: sip_module.h:54
int id Definition: sip_module.h:70
struct pjsip_request_line req Definition: sip_msg.h:868
union pjsip_msg::@19 line
pjsip_method method Definition: sip_msg.h:434
Definition: sip_util.h:617
Definition: sip_transport.h:295
int src_port Definition: sip_transport.h:346
struct pjsip_rx_data::@26 msg_info
char src_name[PJ_INET6_ADDRSTRLEN] Definition: sip_transport.h:343
struct pjsip_rx_data::@25 pkt_info
pj_ssize_t len Definition: sip_transport.h:334
pjsip_msg * msg Definition: sip_transport.h:364
char * msg_buf Definition: sip_transport.h:358
Definition: sip_transport.h:806
pjsip_host_port local_name Definition: sip_transport.h:827
Definition: sip_transport.h:522
pj_pool_t * pool Definition: sip_transport.h:527
char dst_name[PJ_INET6_ADDRSTRLEN] Definition: sip_transport.h:614
int dst_port Definition: sip_transport.h:615
struct pjsip_tx_data::@29 tp_info
pjsip_buffer buf Definition: sip_transport.h:568
PJSIP Open Source, high performance, small footprint, and very very portable SIP stack
Copyright (C) 2006-2008 Teluu Inc.
|