[pulseaudio-discuss] [PATCH 3/3] rtp: Introduce source IP configuration with srcip

Robin H. Johnson robbat2 at gentoo.org
Sat Nov 17 15:31:18 PST 2012


From: "Robin H. Johnson" <robbat2 at gentoo.org>

On a multi-homed system, the user may wish RTP to be used only on
specific interfaces. The default binding of 0.0.0.0 for the source
address causes SAP multicast on all interfaces, which is not ideal.

Introduce a new module argument, srcip, that allows selection of the
source IP, and thus interface.

Signed-off-by: Robin H. Johnson <robbat2 at gentoo.org>
---
 src/modules/rtp/module-rtp-send.c | 48 ++++++++++++++++++++++++++++++++++++---
 1 file changed, 45 insertions(+), 3 deletions(-)

diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c
index 1826283..bd8159e 100644
--- a/src/modules/rtp/module-rtp-send.c
+++ b/src/modules/rtp/module-rtp-send.c
@@ -64,6 +64,7 @@ PA_MODULE_USAGE(
         "channels=<number of channels> "
         "rate=<sample rate> "
         "dstip=<destination IP address> "
+        "srcip=<destination IP address> "
         "port=<port number> "
         "mtu=<maximum transfer unit> "
         "loop=<loopback to local host?> "
@@ -74,6 +75,7 @@ PA_MODULE_USAGE(
 #define DEFAULT_TTL 1
 #define SAP_PORT 9875
 #define DEFAULT_DESTINATION "224.0.0.56"
+#define DEFAULT_SOURCE_IP "0.0.0.0"
 #define MEMBLOCKQ_MAXLENGTH (1024*170)
 #define DEFAULT_MTU 1280
 #define SAP_INTERVAL (5*PA_USEC_PER_SEC)
@@ -85,6 +87,7 @@ static const char* const valid_modargs[] = {
     "rate",
     "destination", /* Compatbility */
     "dstip",
+    "srcip",
     "port",
     "mtu" ,
     "loop",
@@ -165,6 +168,7 @@ int pa__init(pa_module*m) {
     struct userdata *u;
     pa_modargs *ma = NULL;
     const char *dst_addr;
+    const char *src_addr;
     uint32_t port = DEFAULT_PORT, mtu;
     uint32_t ttl = DEFAULT_TTL;
     sa_family_t af;
@@ -172,9 +176,9 @@ int pa__init(pa_module*m) {
     pa_source *s;
     pa_sample_spec ss;
     pa_channel_map cm;
-    struct sockaddr_in dst_sa4, dst_sap_sa4;
+    struct sockaddr_in dst_sa4, dst_sap_sa4, src_sa4, src_sap_sa4;
 #ifdef HAVE_IPV6
-    struct sockaddr_in6 dst_sa6, dst_sap_sa6;
+    struct sockaddr_in6 dst_sa6, dst_sap_sa6, src_sa6, src_sap_sa6;
 #endif
     struct sockaddr_storage sa_dst;
     pa_source_output *o = NULL;
@@ -242,6 +246,23 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
+    src_addr = pa_modargs_get_value(ma, "srcip", DEFAULT_SOURCE_IP);
+    
+    if (inet_pton(AF_INET, src_addr, &src_sa4.sin_addr) > 0) {
+        src_sa4.sin_family = af = AF_INET;
+        src_sa4.sin_port = htons(0);
+        src_sap_sa4 = src_sa4;
+#ifdef HAVE_IPV6
+    } else if (inet_pton(AF_INET6, src_addr, &src_sa6.sin6_addr) > 0) {
+        src_sa6.sin6_family = af = AF_INET6;
+        src_sa6.sin6_port = htons(0);
+        src_sap_sa6 = src_sa6;
+#endif
+    } else {
+        pa_log("Invalid source address '%s'", src_addr);
+        goto fail;
+    }
+
     dst_addr = pa_modargs_get_value(ma, "destination", NULL);
 	if(dst_addr == NULL) {
 		dst_addr = pa_modargs_get_value(ma, "dstip", DEFAULT_DESTINATION);
@@ -269,6 +290,16 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
+    if (af == AF_INET && bind(fd, (struct sockaddr*) &src_sa4, sizeof(src_sa4)) < 0) {
+        pa_log("bind() failed: %s", pa_cstrerror(errno));
+        goto fail;
+#ifdef HAVE_IPV6
+    } else if (af == AF_INET6 && bind(fd, (struct sockaddr*) &src_sa6, sizeof(src_sa6)) < 0) {
+        pa_log("bind() failed: %s", pa_cstrerror(errno));
+        goto fail;
+#endif
+    }
+
     if (af == AF_INET && connect(fd, (struct sockaddr*) &dst_sa4, sizeof(dst_sa4)) < 0) {
         pa_log("connect() failed: %s", pa_cstrerror(errno));
         goto fail;
@@ -284,6 +315,16 @@ int pa__init(pa_module*m) {
         goto fail;
     }
 
+    if (af == AF_INET && bind(sap_fd, (struct sockaddr*) &src_sap_sa4, sizeof(src_sap_sa4)) < 0) {
+        pa_log("bind() failed: %s", pa_cstrerror(errno));
+        goto fail;
+#ifdef HAVE_IPV6
+    } else if (af == AF_INET6 && bind(sap_fd, (struct sockaddr*) &src_sap_sa6, sizeof(src_sap_sa6)) < 0) {
+        pa_log("bind() failed: %s", pa_cstrerror(errno));
+        goto fail;
+#endif
+    }
+
     if (af == AF_INET && connect(sap_fd, (struct sockaddr*) &dst_sap_sa4, sizeof(dst_sap_sa4)) < 0) {
         pa_log("connect() failed: %s", pa_cstrerror(errno));
         goto fail;
@@ -323,6 +364,7 @@ int pa__init(pa_module*m) {
     pa_proplist_sets(data.proplist, PA_PROP_MEDIA_NAME, "RTP Monitor Stream");
     pa_proplist_sets(data.proplist, "rtp.destination", dst_addr); /* Compatability, can we drop it? */
     pa_proplist_sets(data.proplist, "rtp.dstip", dst_addr);
+    pa_proplist_sets(data.proplist, "rtp.srcip", src_addr);
     pa_proplist_setf(data.proplist, "rtp.mtu", "%lu", (unsigned long) mtu);
     pa_proplist_setf(data.proplist, "rtp.port", "%lu", (unsigned long) port);
     pa_proplist_setf(data.proplist, "rtp.ttl", "%lu", (unsigned long) ttl);
@@ -389,7 +431,7 @@ int pa__init(pa_module*m) {
     pa_rtp_context_init_send(&u->rtp_context, fd, m->core->cookie, payload, pa_frame_size(&ss));
     pa_sap_context_init_send(&u->sap_context, sap_fd, p);
 
-    pa_log_info("RTP stream initialized with mtu %u on %s:%u ttl=%u, SSRC=0x%08x, payload=%u, initial sequence #%u", mtu, dst_addr, port, ttl, u->rtp_context.ssrc, payload, u->rtp_context.sequence);
+    pa_log_info("RTP stream initialized with mtu %u on %s:%u from %s ttl=%u, SSRC=0x%08x, payload=%u, initial sequence #%u", mtu, dst_addr, port, src_addr, ttl, u->rtp_context.ssrc, payload, u->rtp_context.sequence);
     pa_log_info("SDP-Data:\n%s\nEOF", p);
 
     pa_sap_send(&u->sap_context, 0);
-- 
1.8.0



More information about the pulseaudio-discuss mailing list