mirror of
				https://gitlab.freedesktop.org/pulseaudio/pulseaudio.git
				synced 2025-11-03 09:01:50 -05:00 
			
		
		
		
	rtp: Introduce source IP configuration
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, that allows selection of the source IP, and thus interface. (changes in v2: s/srcip/source_ip) Signed-off-by: Robin H. Johnson <robbat2@gentoo.org>
This commit is contained in:
		
							parent
							
								
									d18c3664b5
								
							
						
					
					
						commit
						088ed8a8d6
					
				
					 1 changed files with 45 additions and 3 deletions
				
			
		| 
						 | 
					@ -64,6 +64,7 @@ PA_MODULE_USAGE(
 | 
				
			||||||
        "channels=<number of channels> "
 | 
					        "channels=<number of channels> "
 | 
				
			||||||
        "rate=<sample rate> "
 | 
					        "rate=<sample rate> "
 | 
				
			||||||
        "destination_ip=<destination IP address> "
 | 
					        "destination_ip=<destination IP address> "
 | 
				
			||||||
 | 
					        "source_ip=<source IP address> "
 | 
				
			||||||
        "port=<port number> "
 | 
					        "port=<port number> "
 | 
				
			||||||
        "mtu=<maximum transfer unit> "
 | 
					        "mtu=<maximum transfer unit> "
 | 
				
			||||||
        "loop=<loopback to local host?> "
 | 
					        "loop=<loopback to local host?> "
 | 
				
			||||||
| 
						 | 
					@ -73,6 +74,7 @@ PA_MODULE_USAGE(
 | 
				
			||||||
#define DEFAULT_PORT 46000
 | 
					#define DEFAULT_PORT 46000
 | 
				
			||||||
#define DEFAULT_TTL 1
 | 
					#define DEFAULT_TTL 1
 | 
				
			||||||
#define SAP_PORT 9875
 | 
					#define SAP_PORT 9875
 | 
				
			||||||
 | 
					#define DEFAULT_SOURCE_IP "0.0.0.0"
 | 
				
			||||||
#define DEFAULT_DESTINATION_IP "224.0.0.56"
 | 
					#define DEFAULT_DESTINATION_IP "224.0.0.56"
 | 
				
			||||||
#define MEMBLOCKQ_MAXLENGTH (1024*170)
 | 
					#define MEMBLOCKQ_MAXLENGTH (1024*170)
 | 
				
			||||||
#define DEFAULT_MTU 1280
 | 
					#define DEFAULT_MTU 1280
 | 
				
			||||||
| 
						 | 
					@ -85,6 +87,7 @@ static const char* const valid_modargs[] = {
 | 
				
			||||||
    "rate",
 | 
					    "rate",
 | 
				
			||||||
    "destination", /* Compatbility */
 | 
					    "destination", /* Compatbility */
 | 
				
			||||||
    "destination_ip",
 | 
					    "destination_ip",
 | 
				
			||||||
 | 
					    "source_ip",
 | 
				
			||||||
    "port",
 | 
					    "port",
 | 
				
			||||||
    "mtu" ,
 | 
					    "mtu" ,
 | 
				
			||||||
    "loop",
 | 
					    "loop",
 | 
				
			||||||
| 
						 | 
					@ -165,6 +168,7 @@ int pa__init(pa_module*m) {
 | 
				
			||||||
    struct userdata *u;
 | 
					    struct userdata *u;
 | 
				
			||||||
    pa_modargs *ma = NULL;
 | 
					    pa_modargs *ma = NULL;
 | 
				
			||||||
    const char *dst_addr;
 | 
					    const char *dst_addr;
 | 
				
			||||||
 | 
					    const char *src_addr;
 | 
				
			||||||
    uint32_t port = DEFAULT_PORT, mtu;
 | 
					    uint32_t port = DEFAULT_PORT, mtu;
 | 
				
			||||||
    uint32_t ttl = DEFAULT_TTL;
 | 
					    uint32_t ttl = DEFAULT_TTL;
 | 
				
			||||||
    sa_family_t af;
 | 
					    sa_family_t af;
 | 
				
			||||||
| 
						 | 
					@ -172,9 +176,9 @@ int pa__init(pa_module*m) {
 | 
				
			||||||
    pa_source *s;
 | 
					    pa_source *s;
 | 
				
			||||||
    pa_sample_spec ss;
 | 
					    pa_sample_spec ss;
 | 
				
			||||||
    pa_channel_map cm;
 | 
					    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
 | 
					#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
 | 
					#endif
 | 
				
			||||||
    struct sockaddr_storage sa_dst;
 | 
					    struct sockaddr_storage sa_dst;
 | 
				
			||||||
    pa_source_output *o = NULL;
 | 
					    pa_source_output *o = NULL;
 | 
				
			||||||
| 
						 | 
					@ -242,6 +246,23 @@ int pa__init(pa_module*m) {
 | 
				
			||||||
        goto fail;
 | 
					        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);
 | 
					    dst_addr = pa_modargs_get_value(ma, "destination", NULL);
 | 
				
			||||||
    if (dst_addr == NULL)
 | 
					    if (dst_addr == NULL)
 | 
				
			||||||
        dst_addr = pa_modargs_get_value(ma, "destination_ip", DEFAULT_DESTINATION_IP);
 | 
					        dst_addr = pa_modargs_get_value(ma, "destination_ip", DEFAULT_DESTINATION_IP);
 | 
				
			||||||
| 
						 | 
					@ -268,6 +289,16 @@ int pa__init(pa_module*m) {
 | 
				
			||||||
        goto fail;
 | 
					        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) {
 | 
					    if (af == AF_INET && connect(fd, (struct sockaddr*) &dst_sa4, sizeof(dst_sa4)) < 0) {
 | 
				
			||||||
        pa_log("connect() failed: %s", pa_cstrerror(errno));
 | 
					        pa_log("connect() failed: %s", pa_cstrerror(errno));
 | 
				
			||||||
        goto fail;
 | 
					        goto fail;
 | 
				
			||||||
| 
						 | 
					@ -283,6 +314,16 @@ int pa__init(pa_module*m) {
 | 
				
			||||||
        goto fail;
 | 
					        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) {
 | 
					    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));
 | 
					        pa_log("connect() failed: %s", pa_cstrerror(errno));
 | 
				
			||||||
        goto fail;
 | 
					        goto fail;
 | 
				
			||||||
| 
						 | 
					@ -320,6 +361,7 @@ int pa__init(pa_module*m) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_source_output_new_data_init(&data);
 | 
					    pa_source_output_new_data_init(&data);
 | 
				
			||||||
    pa_proplist_sets(data.proplist, PA_PROP_MEDIA_NAME, "RTP Monitor Stream");
 | 
					    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_sets(data.proplist, "rtp.destination", dst_addr);
 | 
				
			||||||
    pa_proplist_setf(data.proplist, "rtp.mtu", "%lu", (unsigned long) mtu);
 | 
					    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.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_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_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_log_info("SDP-Data:\n%s\nEOF", p);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pa_sap_send(&u->sap_context, 0);
 | 
					    pa_sap_send(&u->sap_context, 0);
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue