[asterisk-commits] tzafrir: branch tzafrir/monitor-rtp-14 r222533 - /team/tzafrir/monitor-rtp-14...

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Wed Oct 7 09:13:58 CDT 2009


Author: tzafrir
Date: Wed Oct  7 09:13:54 2009
New Revision: 222533

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=222533
Log:
Get rid of RTP_PORT_OFFSET: the basics

Backport fixes from the trunk branch. First part: the basic changes:

Use a local bind() on a UDP port to allocate a port number.

Modified:
    team/tzafrir/monitor-rtp-14/res/res_monitor.c

Modified: team/tzafrir/monitor-rtp-14/res/res_monitor.c
URL: http://svnview.digium.com/svn/asterisk/team/tzafrir/monitor-rtp-14/res/res_monitor.c?view=diff&rev=222533&r1=222532&r2=222533
==============================================================================
--- team/tzafrir/monitor-rtp-14/res/res_monitor.c (original)
+++ team/tzafrir/monitor-rtp-14/res/res_monitor.c Wed Oct  7 09:13:54 2009
@@ -48,6 +48,7 @@
 #include "asterisk/utils.h"
 #include "asterisk/config.h"
 #include "asterisk/options.h"
+#include "asterisk/acl.h"
 
 AST_MUTEX_DEFINE_STATIC(monitorlock);
 
@@ -75,7 +76,20 @@
 
 static in_port_t rtp_portbase_rx = 9000;
 static in_port_t rtp_portbase_tx = 11000;
+
+/*! First port for RTP monitoring sessions (set in monitor.conf) */
+static int rtp_mon_start = 9000;
+/*! Last port for RTP monitoring sessions (set in monitor.conf) */
+static int rtp_mon_end = 9999;
 #define	PCM_FORMAT	"rtpmonitor"
+
+/* Simplify backporting */
+#ifndef ast_debug
+#define ast_debug(level, ...) do {       \
+	if (option_debug >= (level) ) \
+		ast_log(LOG_DEBUG, __VA_ARGS__); \
+} while (0)
+#endif
 
 static char *monitor_synopsis = "Monitor a channel";
 
@@ -142,6 +156,57 @@
 	return 0;
 }
 
+/* Allocate a local UDP port number. In order to gurantee the remote port
+ * is unique, we bind() using the same port number on the local interface
+ * first. THe whole point of this bind it to find a free port.
+ *
+ * Returns port number, or -1 in case of an error.
+ */
+static int get_local_udp_port(int sock)
+{
+	int x, startplace;
+	struct sockaddr_in saddr;
+
+	if (ast_get_ip(&saddr, reporting_host)) {
+		ast_log(LOG_NOTICE, "Failed to get address for our host: %s. No RTP monitoring.\n",
+			reporting_host);
+		return -1;
+	}
+
+	/* Now actually find a free RTP port to use */
+	x = (ast_random() % (rtp_mon_end - rtp_mon_start)) + rtp_mon_start;
+	x = x & ~1;
+	startplace = x;
+
+	for (;;) {
+		saddr.sin_port = htons(x);
+		/* Try to bind, this will tell us whether the port is available or not */
+		if (!bind(sock, &saddr, sizeof(saddr))) {
+			ast_debug(1, "Allocated port %d for RTP monitoring.\n", x);
+			return x;
+		}
+		if (errno != EADDRINUSE) {
+			ast_log(LOG_WARNING, "bind to port %d failed: %d (%s)\n", 
+				x, errno, strerror(errno));
+			return -1;
+		}
+
+		x += 2;
+		if (x > rtp_mon_end) {
+			x = (rtp_mon_start + 1) & ~1;
+		}
+
+		if (x == startplace) {
+			ast_log(LOG_ERROR, "RTP Monitoring: All ports in range %d-%d are in use.\n",
+				rtp_mon_start, rtp_mon_end);
+			return -1;
+		}
+	}
+
+	/* Unreachable */
+	
+}
+
 static int get_ipaddr(const char *str, struct in_addr *addr)
 {
 	struct ast_hostent he;
@@ -154,19 +219,37 @@
 	return 1;
 }
 
+
+/* Create a UDP stream.
+ *
+ * if port is 0, it is allocated using get_local_udp_port()
+ *
+ * Returns the socket or an error number if socket was not created.
+ */
 static int udp_stream(const char *server, in_port_t port, struct sockaddr_in *saddr)
 {
 	int sock;
 
-	if(!get_ipaddr(server, &(saddr->sin_addr)))
+	if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
+		ast_log(LOG_NOTICE, "Failed to create UDP socket: %s\n", 
+			strerror(errno));
+		return -errno;
+	}
+	if (port == 0) {
+		port = get_local_udp_port(sock);
+		if (port < 0) {
+			return -1;
+		}
+	}
+
+	if (ast_get_ip(saddr, server)) {
+		ast_log(LOG_NOTICE, "Failed to get address for: %s. No RTP monitoring.\n",
+			server);
 		return -EINVAL;
+	}
 	ast_log(LOG_NOTICE, "%s: %s:%d\n", __FUNCTION__, server, port);
 	saddr->sin_family = AF_INET;
 	saddr->sin_port = htons(port);
-	if((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
-		ast_log(LOG_NOTICE, "Failed to create UDP socket: %s\n", strerror(errno));
-		return -errno;
-	}
 	return sock;
 }
 
@@ -181,15 +264,15 @@
 	return sock;
 }
 
-static struct ast_filestream *rtp_stream(struct ast_channel *chan, const char *server, in_port_t port, uint32_t ssrc)
+static struct ast_filestream *rtp_stream(struct ast_channel *chan, const char *server, uint32_t ssrc)
 {
 	int sock;
 	struct ast_filestream *fs = NULL;
 	struct sockaddr_in saddr;
 	struct monitor_rtp_state *rtp_state;
 
-	if((sock = udp_stream(server, port, &saddr)) < 0) {
-		ast_log(LOG_WARNING, "Failed to create RTP stream to '%s:%d'\n", server, port);
+	if((sock = udp_stream(server, 0, &saddr)) < 0) {
+		ast_log(LOG_WARNING, "Failed to create RTP stream to '%s'\n", server);
 		return NULL;
 	}
 	rtp_state = ast_calloc(1, sizeof(*rtp_state));
@@ -201,7 +284,6 @@
 	rtp_state->ssrc = ssrc;
 	rtp_state->seqno = 0;
 	rtp_state->ts_start = ast_tvnow();
-	ast_log(LOG_NOTICE, "%s: '%s:%d' (ssrc=%ld)\n", __FUNCTION__, server, port, (unsigned long)rtp_state->ssrc);
 	rtp_state->dest = saddr;
 	ast_log(LOG_NOTICE, "%s: sockfd=%d\n", __FUNCTION__, sock);
 	fs = ast_writefile((const char *)rtp_state, PCM_FORMAT, "UDP", 0, sock, 0);
@@ -401,35 +483,25 @@
 	struct ast_channel_monitor *monitor;
 	struct monitor_rtp_state *rtp_state_rx;
 	struct monitor_rtp_state *rtp_state_tx;
-	const char	*port_offset;
 	uint32_t	rx_ssrc;
 	uint32_t	tx_ssrc;
-	int		portnum;
 	int		ret = -1;
 
 	ast_log(LOG_NOTICE, "START monitor2rtp\n");
 	LOCK_IF_NEEDED(chan, need_lock);
-	port_offset = pbx_builtin_getvar_helper(chan, "RTP_PORT_OFFSET");
-	portnum = atoi(port_offset);
-	if(portnum <= 0) {
-		ast_log(LOG_WARNING, "Bad RTP_PORT_OFFSET='%s'\n", port_offset);
-		goto out;
-	}
 	if (!(monitor = ast_calloc(1, sizeof(*monitor)))) {
 		goto out;
 	}
 	calc_ssrc(chan, &rx_ssrc, &tx_ssrc);
 	ast_log(LOG_NOTICE, "%s: rx_ssrc=%u tx_ssrc=%u\n", __FUNCTION__, rx_ssrc, tx_ssrc);
-	/* RTP uses even port numbers */
-	portnum = (portnum - 1) * 2;
 	/* RX port */
-	monitor->read_stream = rtp_stream(chan, rtp_server_name, rtp_portbase_rx + portnum, rx_ssrc);
+	monitor->read_stream = rtp_stream(chan, rtp_server_name, rx_ssrc);
 	if (!monitor->read_stream) {
 		ast_log(LOG_WARNING, "Could not create UDP stream for read\n");
 		goto out;
 	}
 	/* TX port */
-	monitor->write_stream = rtp_stream(chan, rtp_server_name, rtp_portbase_tx + portnum, tx_ssrc);
+	monitor->write_stream = rtp_stream(chan, rtp_server_name, tx_ssrc);
 	if (!monitor->write_stream) {
 		ast_log(LOG_WARNING, "Could not create UDP stream for write\n");
 		ast_closestream(monitor->read_stream);




More information about the asterisk-commits mailing list