mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-04 13:30:12 -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