[asterisk-commits] tzafrir: branch tzafrir/monitor-rtp r222104 - /team/tzafrir/monitor-rtp/res/

SVN commits to the Asterisk project asterisk-commits at lists.digium.com
Mon Oct 5 12:00:59 CDT 2009


Author: tzafrir
Date: Mon Oct  5 12:00:57 2009
New Revision: 222104

URL: http://svnview.digium.com/svn/asterisk?view=rev&rev=222104
Log:
Avoid the need to assign port numbers in chan var

We now "allocate" UDP port numbers on the remote port by binding
to a local UDP port with the same port number.

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

Modified: team/tzafrir/monitor-rtp/res/res_monitor.c
URL: http://svnview.digium.com/svn/asterisk/team/tzafrir/monitor-rtp/res/res_monitor.c?view=diff&rev=222104&r1=222103&r2=222104
==============================================================================
--- team/tzafrir/monitor-rtp/res/res_monitor.c (original)
+++ team/tzafrir/monitor-rtp/res/res_monitor.c Mon Oct  5 12:00:57 2009
@@ -266,6 +266,10 @@
 
 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;
 
 /* FIXME: Should be moved to some header file: */
 #define PCM_FORMAT "rtpmonitor"
@@ -289,9 +293,79 @@
 	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 */
+	
+}
+
+
+/* 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 ((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",
@@ -301,10 +375,6 @@
 	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;
 }
 
@@ -327,7 +397,7 @@
 	struct sockaddr_in saddr;
 	struct monitor_rtp_state *rtp_state;
 
-	if ((sock = udp_stream(server, port, &saddr)) < 0) {
+	if ((sock = udp_stream(server, 0, &saddr)) < 0) {
 		ast_log(LOG_WARNING, "Failed to create RTP stream to '%s:%d'\n", server, port);
 		return NULL;
 	}




More information about the asterisk-commits mailing list