mirror of
https://gitlab.freedesktop.org/pipewire/pipewire.git
synced 2025-11-05 13:30:02 -05:00
raop: Deduplicate sink creation
Currently, RAOP sinks referencing the same remote ip and port may be created multiple times: One each for IPv4 and IPv6, times the number of network interfaces used for mDNS discovery. A recent change added `(IPv4)`and `(IPv6)`identifiers to the sinks' pretty names, however that is misleading, as often times the service advertised through an mDNSv6 record is actually an IPv4 service (i.e. the IP reference contained in the IPv6 record may be an IPv4 address). With this change, sink creation is skipped if a sink with the same advertised name already exists.
This commit is contained in:
parent
0e831c52d8
commit
0bb0b524c7
2 changed files with 31 additions and 40 deletions
|
|
@ -125,12 +125,10 @@ struct impl {
|
||||||
};
|
};
|
||||||
|
|
||||||
struct tunnel_info {
|
struct tunnel_info {
|
||||||
AvahiIfIndex interface;
|
|
||||||
AvahiProtocol protocol;
|
|
||||||
const char *name;
|
const char *name;
|
||||||
const char *host_name;
|
const char *host_name;
|
||||||
const char *type;
|
const char *ip;
|
||||||
const char *domain;
|
const char *port;
|
||||||
};
|
};
|
||||||
|
|
||||||
#define TUNNEL_INFO(...) ((struct tunnel_info){ __VA_ARGS__ })
|
#define TUNNEL_INFO(...) ((struct tunnel_info){ __VA_ARGS__ })
|
||||||
|
|
@ -152,12 +150,10 @@ static struct tunnel *make_tunnel(struct impl *impl, const struct tunnel_info *i
|
||||||
if (t == NULL)
|
if (t == NULL)
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
||||||
t->info.interface = info->interface;
|
|
||||||
t->info.protocol = info->protocol;
|
|
||||||
t->info.name = strdup(info->name);
|
t->info.name = strdup(info->name);
|
||||||
t->info.host_name = strdup(info->host_name);
|
t->info.host_name = strdup(info->host_name);
|
||||||
t->info.type = strdup(info->type);
|
t->info.ip = strdup(info->ip);
|
||||||
t->info.domain = strdup(info->domain);
|
t->info.port = strdup(info->port);
|
||||||
spa_list_append(&impl->tunnel_list, &t->link);
|
spa_list_append(&impl->tunnel_list, &t->link);
|
||||||
|
|
||||||
return t;
|
return t;
|
||||||
|
|
@ -167,11 +163,7 @@ static struct tunnel *find_tunnel(struct impl *impl, const struct tunnel_info *i
|
||||||
{
|
{
|
||||||
struct tunnel *t;
|
struct tunnel *t;
|
||||||
spa_list_for_each(t, &impl->tunnel_list, link) {
|
spa_list_for_each(t, &impl->tunnel_list, link) {
|
||||||
if (t->info.interface == info->interface &&
|
if (spa_streq(t->info.name, info->name))
|
||||||
t->info.protocol == info->protocol &&
|
|
||||||
spa_streq(t->info.name, info->name) &&
|
|
||||||
spa_streq(t->info.type, info->type) &&
|
|
||||||
spa_streq(t->info.domain, info->domain))
|
|
||||||
return t;
|
return t;
|
||||||
}
|
}
|
||||||
return NULL;
|
return NULL;
|
||||||
|
|
@ -298,8 +290,8 @@ static void submodule_destroy(void *data)
|
||||||
|
|
||||||
free((char *) t->info.name);
|
free((char *) t->info.name);
|
||||||
free((char *) t->info.host_name);
|
free((char *) t->info.host_name);
|
||||||
free((char *) t->info.type);
|
free((char *) t->info.ip);
|
||||||
free((char *) t->info.domain);
|
free((char *) t->info.port);
|
||||||
|
|
||||||
free(t);
|
free(t);
|
||||||
}
|
}
|
||||||
|
|
@ -385,23 +377,18 @@ static void resolver_cb(AvahiServiceResolver *r, AvahiIfIndex interface, AvahiPr
|
||||||
{
|
{
|
||||||
struct impl *impl = userdata;
|
struct impl *impl = userdata;
|
||||||
struct tunnel_info tinfo;
|
struct tunnel_info tinfo;
|
||||||
const char *str;
|
const char *str, *port_str;
|
||||||
AvahiStringList *l;
|
AvahiStringList *l;
|
||||||
struct pw_properties *props = NULL;
|
struct pw_properties *props = NULL;
|
||||||
char at[AVAHI_ADDRESS_STR_MAX];
|
char at[AVAHI_ADDRESS_STR_MAX];
|
||||||
int ipv;
|
|
||||||
|
|
||||||
if (event != AVAHI_RESOLVER_FOUND) {
|
if (event != AVAHI_RESOLVER_FOUND) {
|
||||||
pw_log_error("Resolving of '%s' failed: %s", name,
|
pw_log_error("Resolving of '%s' failed: %s", name,
|
||||||
avahi_strerror(avahi_client_errno(impl->client)));
|
avahi_strerror(avahi_client_errno(impl->client)));
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
tinfo = TUNNEL_INFO(.interface = interface,
|
|
||||||
.protocol = protocol,
|
avahi_address_snprint(at, sizeof(at), a);
|
||||||
.host_name = host_name,
|
|
||||||
.name = name,
|
|
||||||
.type = type,
|
|
||||||
.domain = domain);
|
|
||||||
|
|
||||||
props = pw_properties_new(NULL, NULL);
|
props = pw_properties_new(NULL, NULL);
|
||||||
if (props == NULL) {
|
if (props == NULL) {
|
||||||
|
|
@ -409,11 +396,7 @@ static void resolver_cb(AvahiServiceResolver *r, AvahiIfIndex interface, AvahiPr
|
||||||
goto done;
|
goto done;
|
||||||
}
|
}
|
||||||
|
|
||||||
avahi_address_snprint(at, sizeof(at), a);
|
|
||||||
ipv = protocol == AVAHI_PROTO_INET ? 4 : 6;
|
|
||||||
|
|
||||||
pw_properties_setf(props, "raop.ip", "%s", at);
|
pw_properties_setf(props, "raop.ip", "%s", at);
|
||||||
pw_properties_setf(props, "raop.ip.version", "%d", ipv);
|
|
||||||
pw_properties_setf(props, "raop.port", "%u", port);
|
pw_properties_setf(props, "raop.port", "%u", port);
|
||||||
pw_properties_setf(props, "raop.name", "%s", name);
|
pw_properties_setf(props, "raop.name", "%s", name);
|
||||||
pw_properties_setf(props, "raop.hostname", "%s", host_name);
|
pw_properties_setf(props, "raop.hostname", "%s", host_name);
|
||||||
|
|
@ -430,6 +413,13 @@ static void resolver_cb(AvahiServiceResolver *r, AvahiIfIndex interface, AvahiPr
|
||||||
avahi_free(value);
|
avahi_free(value);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
port_str = pw_properties_get(props, "raop.port");
|
||||||
|
|
||||||
|
tinfo = TUNNEL_INFO(.name = name,
|
||||||
|
.host_name = host_name,
|
||||||
|
.ip = at,
|
||||||
|
.port = port_str);
|
||||||
|
|
||||||
if ((str = pw_properties_get(impl->properties, "stream.rules")) == NULL)
|
if ((str = pw_properties_get(impl->properties, "stream.rules")) == NULL)
|
||||||
str = DEFAULT_CREATE_RULES;
|
str = DEFAULT_CREATE_RULES;
|
||||||
if (str != NULL) {
|
if (str != NULL) {
|
||||||
|
|
@ -462,18 +452,16 @@ static void browser_cb(AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProt
|
||||||
if (flags & AVAHI_LOOKUP_RESULT_LOCAL)
|
if (flags & AVAHI_LOOKUP_RESULT_LOCAL)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
info = TUNNEL_INFO(.interface = interface,
|
info = TUNNEL_INFO(.name = name);
|
||||||
.protocol = protocol,
|
|
||||||
.name = name,
|
|
||||||
.type = type,
|
|
||||||
.domain = domain);
|
|
||||||
|
|
||||||
t = find_tunnel(impl, &info);
|
t = find_tunnel(impl, &info);
|
||||||
|
|
||||||
switch (event) {
|
switch (event) {
|
||||||
case AVAHI_BROWSER_NEW:
|
case AVAHI_BROWSER_NEW:
|
||||||
if (t != NULL)
|
if (t != NULL) {
|
||||||
|
pw_log_debug("found duplicate mdns entry - skipping tunnel creation");
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
if (!(avahi_service_resolver_new(impl->client,
|
if (!(avahi_service_resolver_new(impl->client,
|
||||||
interface, protocol,
|
interface, protocol,
|
||||||
name, type, domain,
|
name, type, domain,
|
||||||
|
|
|
||||||
|
|
@ -1861,7 +1861,7 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
|
||||||
struct pw_context *context = pw_impl_module_get_context(module);
|
struct pw_context *context = pw_impl_module_get_context(module);
|
||||||
struct pw_properties *props = NULL;
|
struct pw_properties *props = NULL;
|
||||||
struct impl *impl;
|
struct impl *impl;
|
||||||
const char *str, *name, *hostname, *ipv;
|
const char *str, *name, *hostname, *ip, *port;
|
||||||
int res;
|
int res;
|
||||||
|
|
||||||
PW_LOG_TOPIC_INIT(mod_topic);
|
PW_LOG_TOPIC_INIT(mod_topic);
|
||||||
|
|
@ -1902,6 +1902,11 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
|
||||||
impl->context = context;
|
impl->context = context;
|
||||||
impl->loop = pw_context_get_main_loop(context);
|
impl->loop = pw_context_get_main_loop(context);
|
||||||
|
|
||||||
|
if ((ip = pw_properties_get(props, "raop.ip")) == NULL)
|
||||||
|
goto error;
|
||||||
|
if ((port = pw_properties_get(props, "raop.port")) == NULL)
|
||||||
|
goto error;
|
||||||
|
|
||||||
if (pw_properties_get(props, PW_KEY_NODE_VIRTUAL) == NULL)
|
if (pw_properties_get(props, PW_KEY_NODE_VIRTUAL) == NULL)
|
||||||
pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true");
|
pw_properties_set(props, PW_KEY_NODE_VIRTUAL, "true");
|
||||||
|
|
||||||
|
|
@ -1916,17 +1921,15 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
|
||||||
if (strlen(str) > 0)
|
if (strlen(str) > 0)
|
||||||
name = str;
|
name = str;
|
||||||
}
|
}
|
||||||
if ((ipv = pw_properties_get(props, "raop.ip.version")) == NULL)
|
|
||||||
ipv = "4";
|
|
||||||
if ((hostname = pw_properties_get(props, "raop.hostname")) == NULL)
|
if ((hostname = pw_properties_get(props, "raop.hostname")) == NULL)
|
||||||
hostname = name;
|
hostname = name;
|
||||||
|
|
||||||
|
if (pw_properties_get(props, PW_KEY_NODE_NAME) == NULL)
|
||||||
|
pw_properties_setf(props, PW_KEY_NODE_NAME, "raop_sink.%s.%s.%s",
|
||||||
|
hostname, ip, port);
|
||||||
if (pw_properties_get(props, PW_KEY_NODE_DESCRIPTION) == NULL)
|
if (pw_properties_get(props, PW_KEY_NODE_DESCRIPTION) == NULL)
|
||||||
pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION,
|
pw_properties_setf(props, PW_KEY_NODE_DESCRIPTION,
|
||||||
"%s (IPv%s)", name, ipv);
|
"%s", name);
|
||||||
if (pw_properties_get(props, PW_KEY_NODE_NAME) == NULL)
|
|
||||||
pw_properties_setf(props, PW_KEY_NODE_NAME, "raop_sink.%s.ipv%s",
|
|
||||||
hostname, ipv);
|
|
||||||
if (pw_properties_get(props, PW_KEY_NODE_LATENCY) == NULL)
|
if (pw_properties_get(props, PW_KEY_NODE_LATENCY) == NULL)
|
||||||
pw_properties_set(props, PW_KEY_NODE_LATENCY, "352/44100");
|
pw_properties_set(props, PW_KEY_NODE_LATENCY, "352/44100");
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue