mirror of
				https://gitlab.freedesktop.org/pipewire/pipewire.git
				synced 2025-11-03 09:01:54 -05:00 
			
		
		
		
	module-rtp: handle non-multicast addresses
Handle errors when creating a session by destroying the session.
This commit is contained in:
		
							parent
							
								
									0397d7b2be
								
							
						
					
					
						commit
						ecc53cfcdb
					
				
					 1 changed files with 52 additions and 31 deletions
				
			
		| 
						 | 
					@ -417,7 +417,7 @@ unexpected_ssrc:
 | 
				
			||||||
	return;
 | 
						return;
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int make_multicast_socket(const struct sockaddr* sa, socklen_t salen, char *ifname)
 | 
					static int make_socket(const struct sockaddr* sa, socklen_t salen, char *ifname)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	int af, fd, val, res;
 | 
						int af, fd, val, res;
 | 
				
			||||||
	struct ifreq req;
 | 
						struct ifreq req;
 | 
				
			||||||
| 
						 | 
					@ -452,22 +452,26 @@ static int make_multicast_socket(const struct sockaddr* sa, socklen_t salen, cha
 | 
				
			||||||
	res = 0;
 | 
						res = 0;
 | 
				
			||||||
	if (af == AF_INET) {
 | 
						if (af == AF_INET) {
 | 
				
			||||||
		static const uint32_t ipv4_mcast_mask = 0xe0000000;
 | 
							static const uint32_t ipv4_mcast_mask = 0xe0000000;
 | 
				
			||||||
		const struct sockaddr_in *sa4 = (struct sockaddr_in*)sa;
 | 
							struct sockaddr_in *sa4 = (struct sockaddr_in*)sa;
 | 
				
			||||||
		if ((ntohl(sa4->sin_addr.s_addr) & ipv4_mcast_mask) == ipv4_mcast_mask) {
 | 
							if ((ntohl(sa4->sin_addr.s_addr) & ipv4_mcast_mask) == ipv4_mcast_mask) {
 | 
				
			||||||
			struct ip_mreqn mr4;
 | 
								struct ip_mreqn mr4;
 | 
				
			||||||
			memset(&mr4, 0, sizeof(mr4));
 | 
								memset(&mr4, 0, sizeof(mr4));
 | 
				
			||||||
			mr4.imr_multiaddr = sa4->sin_addr;
 | 
								mr4.imr_multiaddr = sa4->sin_addr;
 | 
				
			||||||
			mr4.imr_ifindex = req.ifr_ifindex;
 | 
								mr4.imr_ifindex = req.ifr_ifindex;
 | 
				
			||||||
			res = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr4, sizeof(mr4));
 | 
								res = setsockopt(fd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mr4, sizeof(mr4));
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								sa4->sin_addr.s_addr = INADDR_ANY;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else if (af == AF_INET6) {
 | 
						} else if (af == AF_INET6) {
 | 
				
			||||||
		const struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)sa;
 | 
							struct sockaddr_in6 *sa6 = (struct sockaddr_in6*)sa;
 | 
				
			||||||
		if (sa6->sin6_addr.s6_addr[0] == 0xff) {
 | 
							if (sa6->sin6_addr.s6_addr[0] == 0xff) {
 | 
				
			||||||
			struct ipv6_mreq mr6;
 | 
								struct ipv6_mreq mr6;
 | 
				
			||||||
			memset(&mr6, 0, sizeof(mr6));
 | 
								memset(&mr6, 0, sizeof(mr6));
 | 
				
			||||||
			mr6.ipv6mr_multiaddr = sa6->sin6_addr;
 | 
								mr6.ipv6mr_multiaddr = sa6->sin6_addr;
 | 
				
			||||||
			mr6.ipv6mr_interface = req.ifr_ifindex;
 | 
								mr6.ipv6mr_interface = req.ifr_ifindex;
 | 
				
			||||||
			res = setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mr6, sizeof(mr6));
 | 
								res = setsockopt(fd, IPPROTO_IPV6, IPV6_JOIN_GROUP, &mr6, sizeof(mr6));
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
							        sa6->sin6_addr = in6addr_any;
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	} else {
 | 
						} else {
 | 
				
			||||||
		res = -EINVAL;
 | 
							res = -EINVAL;
 | 
				
			||||||
| 
						 | 
					@ -482,7 +486,7 @@ static int make_multicast_socket(const struct sockaddr* sa, socklen_t salen, cha
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if (bind(fd, sa, salen) < 0) {
 | 
						if (bind(fd, sa, salen) < 0) {
 | 
				
			||||||
		res = -errno;
 | 
							res = -errno;
 | 
				
			||||||
		pw_log_warn("bind() failed: %m");
 | 
							pw_log_error("bind() failed: %m");
 | 
				
			||||||
		goto error;
 | 
							goto error;
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return fd;
 | 
						return fd;
 | 
				
			||||||
| 
						 | 
					@ -502,6 +506,20 @@ static void session_touch(struct session *sess)
 | 
				
			||||||
	sess->timestamp = SPA_TIMESPEC_TO_NSEC(&ts);
 | 
						sess->timestamp = SPA_TIMESPEC_TO_NSEC(&ts);
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					static void session_free(struct session *sess)
 | 
				
			||||||
 | 
					{
 | 
				
			||||||
 | 
						pw_log_info("free session %s %s", sess->info.origin, sess->info.session);
 | 
				
			||||||
 | 
						if (sess->impl) {
 | 
				
			||||||
 | 
							sess->impl->n_sessions--;
 | 
				
			||||||
 | 
							spa_list_remove(&sess->link);
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if (sess->stream)
 | 
				
			||||||
 | 
							pw_stream_destroy(sess->stream);
 | 
				
			||||||
 | 
						if (sess->source)
 | 
				
			||||||
 | 
							pw_loop_destroy_source(sess->impl->loop, sess->source);
 | 
				
			||||||
 | 
						free(sess);
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static int session_new(struct impl *impl, struct sdp_info *info)
 | 
					static int session_new(struct impl *impl, struct sdp_info *info)
 | 
				
			||||||
{
 | 
					{
 | 
				
			||||||
	struct session *session;
 | 
						struct session *session;
 | 
				
			||||||
| 
						 | 
					@ -521,7 +539,6 @@ static int session_new(struct impl *impl, struct sdp_info *info)
 | 
				
			||||||
	if (session == NULL)
 | 
						if (session == NULL)
 | 
				
			||||||
		return -errno;
 | 
							return -errno;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	session->impl = impl;
 | 
					 | 
				
			||||||
	session->info = *info;
 | 
						session->info = *info;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	session->target_buffer = msec_to_bytes(info, impl->sess_latency_msec);
 | 
						session->target_buffer = msec_to_bytes(info, impl->sess_latency_msec);
 | 
				
			||||||
| 
						 | 
					@ -531,8 +548,10 @@ static int session_new(struct impl *impl, struct sdp_info *info)
 | 
				
			||||||
	spa_dll_set_bw(&session->dll, SPA_DLL_BW_MIN, 128, session->info.info.rate);
 | 
						spa_dll_set_bw(&session->dll, SPA_DLL_BW_MIN, 128, session->info.info.rate);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	props = pw_properties_copy(impl->stream_props);
 | 
						props = pw_properties_copy(impl->stream_props);
 | 
				
			||||||
	if (props == NULL)
 | 
						if (props == NULL) {
 | 
				
			||||||
		return -errno;
 | 
							res = -errno;
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%d", info->info.rate);
 | 
						pw_properties_setf(props, PW_KEY_NODE_RATE, "1/%d", info->info.rate);
 | 
				
			||||||
	pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%d/%d",
 | 
						pw_properties_setf(props, PW_KEY_NODE_LATENCY, "%d/%d",
 | 
				
			||||||
| 
						 | 
					@ -551,8 +570,11 @@ static int session_new(struct impl *impl, struct sdp_info *info)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	session->stream = pw_stream_new(impl->core,
 | 
						session->stream = pw_stream_new(impl->core,
 | 
				
			||||||
			"rtp-source playback", props);
 | 
								"rtp-source playback", props);
 | 
				
			||||||
	if (session->stream == NULL)
 | 
						if (session->stream == NULL) {
 | 
				
			||||||
		return -errno;
 | 
							res = -errno;
 | 
				
			||||||
 | 
							pw_log_error("can't create stream: %m");
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_stream_add_listener(session->stream,
 | 
						pw_stream_add_listener(session->stream,
 | 
				
			||||||
			&session->stream_listener,
 | 
								&session->stream_listener,
 | 
				
			||||||
| 
						 | 
					@ -563,43 +585,42 @@ static int session_new(struct impl *impl, struct sdp_info *info)
 | 
				
			||||||
	params[n_params++] = spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat,
 | 
						params[n_params++] = spa_format_audio_raw_build(&b, SPA_PARAM_EnumFormat,
 | 
				
			||||||
			&info->info);
 | 
								&info->info);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
	if ((res = pw_stream_connect(session->stream,
 | 
						if ((res = pw_stream_connect(session->stream,
 | 
				
			||||||
			PW_DIRECTION_OUTPUT,
 | 
								PW_DIRECTION_OUTPUT,
 | 
				
			||||||
			PW_ID_ANY,
 | 
								PW_ID_ANY,
 | 
				
			||||||
			PW_STREAM_FLAG_MAP_BUFFERS |
 | 
								PW_STREAM_FLAG_MAP_BUFFERS |
 | 
				
			||||||
			PW_STREAM_FLAG_AUTOCONNECT |
 | 
								PW_STREAM_FLAG_AUTOCONNECT |
 | 
				
			||||||
			PW_STREAM_FLAG_RT_PROCESS,
 | 
								PW_STREAM_FLAG_RT_PROCESS,
 | 
				
			||||||
			params, n_params)) < 0)
 | 
								params, n_params)) < 0) {
 | 
				
			||||||
		return res;
 | 
							pw_log_error("can't connect stream: %s", spa_strerror(res));
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((fd = make_multicast_socket((const struct sockaddr *)&info->sa,
 | 
						if ((fd = make_socket((const struct sockaddr *)&info->sa,
 | 
				
			||||||
					info->salen, impl->ifname)) < 0)
 | 
										info->salen, impl->ifname)) < 0) {
 | 
				
			||||||
		return fd;
 | 
							res = fd;
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_info("starting RTP listener");
 | 
					 | 
				
			||||||
	session->source = pw_loop_add_io(impl->loop, fd,
 | 
						session->source = pw_loop_add_io(impl->loop, fd,
 | 
				
			||||||
				SPA_IO_IN, true, on_rtp_io, session);
 | 
									SPA_IO_IN, true, on_rtp_io, session);
 | 
				
			||||||
	if (session->source == NULL)
 | 
						if (session->source == NULL) {
 | 
				
			||||||
		return -errno;
 | 
							res = -errno;
 | 
				
			||||||
 | 
							pw_log_error("can't create io source: %m");
 | 
				
			||||||
 | 
							goto error;
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pw_log_info("starting RTP listener");
 | 
				
			||||||
	session_touch(session);
 | 
						session_touch(session);
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						session->impl = impl;
 | 
				
			||||||
	spa_list_append(&impl->sessions, &session->link);
 | 
						spa_list_append(&impl->sessions, &session->link);
 | 
				
			||||||
	impl->n_sessions++;
 | 
						impl->n_sessions++;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return 0;
 | 
						return 0;
 | 
				
			||||||
}
 | 
					error:
 | 
				
			||||||
 | 
						session_free(session);
 | 
				
			||||||
static void session_free(struct session *sess)
 | 
						return res;
 | 
				
			||||||
{
 | 
					 | 
				
			||||||
	pw_log_info("free session %s %s", sess->info.origin, sess->info.session);
 | 
					 | 
				
			||||||
	sess->impl->n_sessions--;
 | 
					 | 
				
			||||||
	spa_list_remove(&sess->link);
 | 
					 | 
				
			||||||
	if (sess->stream)
 | 
					 | 
				
			||||||
		pw_stream_destroy(sess->stream);
 | 
					 | 
				
			||||||
	if (sess->source)
 | 
					 | 
				
			||||||
		pw_loop_destroy_source(sess->impl->loop, sess->source);
 | 
					 | 
				
			||||||
	free(sess);
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
static struct session *session_find(struct impl *impl, struct sdp_info *info)
 | 
					static struct session *session_find(struct impl *impl, struct sdp_info *info)
 | 
				
			||||||
| 
						 | 
					@ -870,7 +891,7 @@ static int start_sap_listener(struct impl *impl)
 | 
				
			||||||
	} else
 | 
						} else
 | 
				
			||||||
		return -EINVAL;
 | 
							return -EINVAL;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if ((fd = make_multicast_socket(sa, salen, impl->ifname)) < 0)
 | 
						if ((fd = make_socket(sa, salen, impl->ifname)) < 0)
 | 
				
			||||||
		return fd;
 | 
							return fd;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	pw_log_info("starting SAP listener");
 | 
						pw_log_info("starting SAP listener");
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue