[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