[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