Skip to content
Snippets Groups Projects
rtp.c 105 KiB
Newer Older
  • Learn to ignore specific revisions
  • 
    	/* Check if bridge is still possible (In SIP canreinvite=no stops this, like NAT) */
    	if (audio_p0_res == AST_RTP_GET_FAILED || audio_p1_res == AST_RTP_GET_FAILED) {
    		/* Somebody doesn't want to play... */
    		ast_channel_unlock(c0);
    		ast_channel_unlock(c1);
    		return AST_BRIDGE_FAILED_NOWARN;
    	}
    
    	/* If we need to feed DTMF frames into the core then only do a partial native bridge */
    	if (ast_test_flag(p0, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_0)) {
    		ast_set_flag(p0, FLAG_P2P_NEED_DTMF);
    		audio_p0_res = AST_RTP_TRY_PARTIAL;
    	}
    
    	if (ast_test_flag(p1, FLAG_HAS_DTMF) && (flags & AST_BRIDGE_DTMF_CHANNEL_1)) {
    		ast_set_flag(p1, FLAG_P2P_NEED_DTMF);
    		audio_p1_res = AST_RTP_TRY_PARTIAL;
    	}
    
    	/* Get codecs from both sides */
    	codec0 = pr0->get_codec ? pr0->get_codec(c0) : 0;
    	codec1 = pr1->get_codec ? pr1->get_codec(c1) : 0;
    	if (pr0->get_codec && pr1->get_codec) {
    		/* Hey, we can't do native bridging if both parties speak different codecs */
    		if (!(codec0 & codec1)) {
    			if (option_debug)
    				ast_log(LOG_DEBUG, "Channel codec0 = %d is not codec1 = %d, cannot native bridge in RTP.\n", codec0, codec1);
    			ast_channel_unlock(c0);
    			ast_channel_unlock(c1);
    			return AST_BRIDGE_FAILED_NOWARN;
    		}
    	}
    
    	/* If either side can only do a partial bridge, then don't try for a true native bridge */
    	if (audio_p0_res == AST_RTP_TRY_PARTIAL || audio_p1_res == AST_RTP_TRY_PARTIAL) {
    		if (option_verbose > 2)
    			ast_verbose(VERBOSE_PREFIX_3 "Packet2Packet bridging %s and %s\n", c0->name, c1->name);
    		res = bridge_p2p_loop(c0, c1, p0, p1, vp0, vp1, timeoutms, flags, fo, rc, pvt0, pvt1);
    	} else {
    		if (option_verbose > 2) 
    			ast_verbose(VERBOSE_PREFIX_3 "Native bridging %s and %s\n", c0->name, c1->name);
    		res = bridge_native_loop(c0, c1, p0, p1, vp0, vp1, pr0, pr1, codec0, codec1, timeoutms, flags, fo, rc, pvt0, pvt1);
    	}
    
    	return res;
    }
    
    
    static int rtp_do_debug_ip(int fd, int argc, char *argv[])
    {
    	struct hostent *hp;
    	struct ast_hostent ahp;
    	int port = 0;
    	char *p, *arg;
    
    	if (argc != 4)
    		return RESULT_SHOWUSAGE;
    	arg = argv[3];
    	p = strstr(arg, ":");
    
    		*p = '\0';
    		p++;
    		port = atoi(p);
    	}
    	hp = ast_gethostbyname(arg, &ahp);
    	if (hp == NULL)
    		return RESULT_SHOWUSAGE;
    	rtpdebugaddr.sin_family = AF_INET;
    	memcpy(&rtpdebugaddr.sin_addr, hp->h_addr, sizeof(rtpdebugaddr.sin_addr));
    	rtpdebugaddr.sin_port = htons(port);
    	if (port == 0)
    
    		ast_cli(fd, "RTP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtpdebugaddr.sin_addr));
    
    		ast_cli(fd, "RTP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtpdebugaddr.sin_addr), port);
    
    	rtpdebug = 1;
    	return RESULT_SUCCESS;
    }
    
    
    static int rtcp_do_debug_ip(int fd, int argc, char *argv[])
    {
    	struct hostent *hp;
    	struct ast_hostent ahp;
    	int port = 0;
    	char *p, *arg;
    	if (argc != 5)
    		return RESULT_SHOWUSAGE;
    
    	arg = argv[4];
    	p = strstr(arg, ":");
    	if (p) {
    		*p = '\0';
    		p++;
    		port = atoi(p);
    	}
    	hp = ast_gethostbyname(arg, &ahp);
    	if (hp == NULL)
    		return RESULT_SHOWUSAGE;
    	rtcpdebugaddr.sin_family = AF_INET;
    	memcpy(&rtcpdebugaddr.sin_addr, hp->h_addr, sizeof(rtcpdebugaddr.sin_addr));
    	rtcpdebugaddr.sin_port = htons(port);
    	if (port == 0)
    
    		ast_cli(fd, "RTCP Debugging Enabled for IP: %s\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr));
    
    		ast_cli(fd, "RTCP Debugging Enabled for IP: %s:%d\n", ast_inet_ntoa(rtcpdebugaddr.sin_addr), port);
    
    static int rtp_do_debug(int fd, int argc, char *argv[])
    {
    
    	if (argc != 2) {
    		if (argc != 4)
    
    			return RESULT_SHOWUSAGE;
    		return rtp_do_debug_ip(fd, argc, argv);
    	}
    	rtpdebug = 1;
    	memset(&rtpdebugaddr,0,sizeof(rtpdebugaddr));
    	ast_cli(fd, "RTP Debugging Enabled\n");
    	return RESULT_SUCCESS;
    }
       
    
    static int rtcp_do_debug(int fd, int argc, char *argv[]) {
    	if (argc != 3) {
    		if (argc != 5)
    
    			return RESULT_SHOWUSAGE;
    		return rtcp_do_debug_ip(fd, argc, argv);
    	}
    	rtcpdebug = 1;
    	memset(&rtcpdebugaddr,0,sizeof(rtcpdebugaddr));
    	ast_cli(fd, "RTCP Debugging Enabled\n");
    	return RESULT_SUCCESS;
    }
    
    
    static int rtcp_do_stats(int fd, int argc, char *argv[]) {
    	if (argc != 3) {
    
    		return RESULT_SHOWUSAGE;
    	}
    	rtcpstats = 1;
    	ast_cli(fd, "RTCP Stats Enabled\n");
    	return RESULT_SUCCESS;
    }
    
    
    static int rtp_no_debug(int fd, int argc, char *argv[])
    {
    
    	if (argc != 3)
    
    		return RESULT_SHOWUSAGE;
    	rtpdebug = 0;
    	ast_cli(fd,"RTP Debugging Disabled\n");
    	return RESULT_SUCCESS;
    }
    
    
    static int rtcp_no_debug(int fd, int argc, char *argv[])
    {
    
    	if (argc != 4)
    
    		return RESULT_SHOWUSAGE;
    	rtcpdebug = 0;
    	ast_cli(fd,"RTCP Debugging Disabled\n");
    	return RESULT_SUCCESS;
    }
    
    static int rtcp_no_stats(int fd, int argc, char *argv[])
    {
    
    	if (argc != 4)
    
    		return RESULT_SHOWUSAGE;
    	rtcpstats = 0;
    	ast_cli(fd,"RTCP Stats Disabled\n");
    	return RESULT_SUCCESS;
    }
    
    
    
    static int stun_do_debug(int fd, int argc, char *argv[])
    {
    
    	if (argc != 2) {
    
    		return RESULT_SHOWUSAGE;
    	}
    	stundebug = 1;
    	ast_cli(fd, "STUN Debugging Enabled\n");
    	return RESULT_SUCCESS;
    }
       
    static int stun_no_debug(int fd, int argc, char *argv[])
    {
    
    	if (argc != 3)
    
    		return RESULT_SHOWUSAGE;
    	stundebug = 0;
    	ast_cli(fd,"STUN Debugging Disabled\n");
    	return RESULT_SUCCESS;
    }
    
    
    
    static char debug_usage[] =
      "Usage: rtp debug [ip host[:port]]\n"
      "       Enable dumping of all RTP packets to and from host.\n";
    
    static char no_debug_usage[] =
      "Usage: rtp no debug\n"
      "       Disable all RTP debugging\n";
    
    
    static char stun_debug_usage[] =
      "Usage: stun debug\n"
      "       Enable STUN (Simple Traversal of UDP through NATs) debugging\n";
    
    static char stun_no_debug_usage[] =
      "Usage: stun no debug\n"
      "       Disable STUN debugging\n";
    
    
    
    static struct ast_cli_entry  cli_debug_ip =
    {{ "rtp", "debug", "ip", NULL } , rtp_do_debug, "Enable RTP debugging on IP", debug_usage };
    
    static struct ast_cli_entry  cli_debug =
    {{ "rtp", "debug", NULL } , rtp_do_debug, "Enable RTP debugging", debug_usage };
    
    static struct ast_cli_entry  cli_no_debug =
    {{ "rtp", "no", "debug", NULL } , rtp_no_debug, "Disable RTP debugging", no_debug_usage };
    
    
    static char rtcp_debug_usage[] =
      "Usage: rtp rtcp debug [ip host[:port]]\n"
      "       Enable dumping of all RTCP packets to and from host.\n";
      
    static char rtcp_no_debug_usage[] =
      "Usage: rtp rtcp no debug\n"
      "       Disable all RTCP debugging\n";
    
    static char rtcp_stats_usage[] =
      "Usage: rtp rtcp stats\n"
      "       Enable dumping of RTCP stats.\n";
      
    static char rtcp_no_stats_usage[] =
      "Usage: rtp rtcp no stats\n"
      "       Disable all RTCP stats\n";
    
    static struct ast_cli_entry  cli_debug_ip_rtcp =
    {{ "rtp", "rtcp", "debug", "ip", NULL } , rtcp_do_debug, "Enable RTCP debugging on IP", rtcp_debug_usage };
    
    static struct ast_cli_entry  cli_debug_rtcp =
    {{ "rtp", "rtcp", "debug", NULL } , rtcp_do_debug, "Enable RTCP debugging", rtcp_debug_usage };
    
    static struct ast_cli_entry  cli_no_debug_rtcp =
    {{ "rtp", "rtcp", "no", "debug", NULL } , rtcp_no_debug, "Disable RTCP debugging", rtcp_no_debug_usage };
    
    static struct ast_cli_entry  cli_stats_rtcp =
    {{ "rtp", "rtcp", "stats", NULL } , rtcp_do_stats, "Enable RTCP stats", rtcp_stats_usage };
    
    static struct ast_cli_entry  cli_no_stats_rtcp =
    {{ "rtp", "rtcp", "no", "stats", NULL } , rtcp_no_stats, "Disable RTCP stats", rtcp_no_stats_usage };
    
    
    static struct ast_cli_entry  cli_stun_debug =
    {{ "stun", "debug", NULL } , stun_do_debug, "Enable STUN debugging", stun_debug_usage };
    
    static struct ast_cli_entry  cli_stun_no_debug =
    {{ "stun", "no", "debug", NULL } , stun_no_debug, "Disable STUN debugging", stun_no_debug_usage };
    
    
    int ast_rtp_reload(void)
    
    {
    	struct ast_config *cfg;
    	char *s;
    
    	rtpstart = 5000;
    	rtpend = 31000;
    
    	dtmftimeout = DEFAULT_DTMF_TIMEOUT;
    
    	cfg = ast_config_load("rtp.conf");
    
    	if (cfg) {
    		if ((s = ast_variable_retrieve(cfg, "general", "rtpstart"))) {
    			rtpstart = atoi(s);
    			if (rtpstart < 1024)
    				rtpstart = 1024;
    			if (rtpstart > 65535)
    				rtpstart = 65535;
    		}
    		if ((s = ast_variable_retrieve(cfg, "general", "rtpend"))) {
    			rtpend = atoi(s);
    			if (rtpend < 1024)
    				rtpend = 1024;
    			if (rtpend > 65535)
    				rtpend = 65535;
    		}
    
    		if ((s = ast_variable_retrieve(cfg, "general", "rtcpinterval"))) {
    			rtcpinterval = atoi(s);
    			if (rtcpinterval == 0)
    				rtcpinterval = 0; /* Just so we're clear... it's zero */
    			if (rtcpinterval < RTCP_MIN_INTERVALMS)
    				rtcpinterval = RTCP_MIN_INTERVALMS; /* This catches negative numbers too */
    			if (rtcpinterval > RTCP_MAX_INTERVALMS)
    				rtcpinterval = RTCP_MAX_INTERVALMS;
    		}
    
    		if ((s = ast_variable_retrieve(cfg, "general", "rtpchecksums"))) {
    
    			if (ast_false(s))
    				nochecksums = 1;
    
    				ast_log(LOG_WARNING, "Disabling RTP checksums is not supported on this operating system!\n");
    #endif
    
    		if ((s = ast_variable_retrieve(cfg, "general", "dtmftimeout"))) {
    			dtmftimeout = atoi(s);
    			if ((dtmftimeout < 0) || (dtmftimeout > 20000)) {
    				ast_log(LOG_WARNING, "DTMF timeout of '%d' outside range, using default of '%d' instead\n",
    					dtmftimeout, DEFAULT_DTMF_TIMEOUT);
    				dtmftimeout = DEFAULT_DTMF_TIMEOUT;
    			};
    		}
    
    		ast_config_destroy(cfg);
    
    	}
    	if (rtpstart >= rtpend) {
    
    		ast_log(LOG_WARNING, "Unreasonable values for RTP start/end port in rtp.conf\n");
    
    		rtpstart = 5000;
    		rtpend = 31000;
    	}
    	if (option_verbose > 1)
    		ast_verbose(VERBOSE_PREFIX_2 "RTP Allocating from port range %d -> %d\n", rtpstart, rtpend);
    
    /*! \brief Initialize the RTP system in Asterisk */
    
    void ast_rtp_init(void)
    {
    
    	ast_cli_register(&cli_debug);
    	ast_cli_register(&cli_debug_ip);
    	ast_cli_register(&cli_no_debug);
    
    
    	ast_cli_register(&cli_debug_rtcp);
    	ast_cli_register(&cli_debug_ip_rtcp);
    	ast_cli_register(&cli_no_debug_rtcp);
    
    	ast_cli_register(&cli_stats_rtcp);
    	ast_cli_register(&cli_no_stats_rtcp);
    	
    
    	ast_cli_register(&cli_stun_debug);
    	ast_cli_register(&cli_stun_no_debug);
    
    	ast_rtp_reload();
    }