diff --git a/src/modules/rtp/module-rtp-send.c b/src/modules/rtp/module-rtp-send.c index 00cc6c919..acabcf5bf 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= " "rate= " "destination_ip= " + "source_ip= " "port= " "mtu= " "loop= " @@ -73,6 +74,7 @@ PA_MODULE_USAGE( #define DEFAULT_PORT 46000 #define DEFAULT_TTL 1 #define SAP_PORT 9875 +#define DEFAULT_SOURCE_IP "0.0.0.0" #define DEFAULT_DESTINATION_IP "224.0.0.56" #define MEMBLOCKQ_MAXLENGTH (1024*170) #define DEFAULT_MTU 1280 @@ -85,6 +87,7 @@ static const char* const valid_modargs[] = { "rate", "destination", /* Compatbility */ "destination_ip", + "source_ip", "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, "source_ip", 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, "destination_ip", DEFAULT_DESTINATION_IP); @@ -268,6 +289,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; @@ -283,6 +314,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; @@ -320,6 +361,7 @@ int pa__init(pa_module*m) { pa_source_output_new_data_init(&data); pa_proplist_sets(data.proplist, PA_PROP_MEDIA_NAME, "RTP Monitor Stream"); + pa_proplist_sets(data.proplist, "rtp.source", src_addr); pa_proplist_sets(data.proplist, "rtp.destination", dst_addr); pa_proplist_setf(data.proplist, "rtp.mtu", "%lu", (unsigned long) mtu); pa_proplist_setf(data.proplist, "rtp.port", "%lu", (unsigned long) port); @@ -387,7 +429,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);