pulse-server: use running servers to publish zeroconf

Loop over the servers and use its family and port to publish the
zeroconf services.

This avoids exposing the services when we don't have any TCP servers
running to accept connections.

It also avoids exposing the services twice with both IP4 and IP6
addresses.

It also exposes the services with a port that is actually usable, in
case it's not the same as the default port.
This commit is contained in:
Wim Taymans 2022-11-17 17:07:38 +01:00
parent 80983b9fb6
commit ab5fe8957b

View file

@ -24,6 +24,7 @@
*/
#include <sys/utsname.h>
#include <arpa/inet.h>
#include <pipewire/pipewire.h>
@ -32,6 +33,7 @@
#include "../manager.h"
#include "../module.h"
#include "../pulse-server.h"
#include "../server.h"
#include "../../module-zeroconf-discover/avahi-poll.h"
#include <avahi-client/client.h>
@ -94,8 +96,6 @@ struct module_zeroconf_publish_data {
struct spa_hook core_listener;
struct spa_hook manager_listener;
unsigned int port;
AvahiPoll *avahi_poll;
AvahiClient *client;
@ -389,16 +389,43 @@ static AvahiStringList *get_service_txt(const struct service *s)
return txt;
}
static int find_port(struct service *s, int *proto, uint16_t *port)
{
struct module_zeroconf_publish_data *d = s->userdata;
struct impl *impl = d->module->impl;
struct server *server;
spa_list_for_each(server, &impl->servers, link) {
if (server->addr.ss_family == AF_INET) {
*proto = AVAHI_PROTO_INET;
*port = ntohs(((struct sockaddr_in*) &server->addr)->sin_port);
return 0;
} else if (server->addr.ss_family == AF_INET6) {
*proto = AVAHI_PROTO_INET6;
*port = ntohs(((struct sockaddr_in6*) &server->addr)->sin6_port);
return 0;
}
}
return -ENODEV;
}
static void publish_service(struct service *s)
{
if (!s->userdata->client || avahi_client_get_state(s->userdata->client) != AVAHI_CLIENT_S_RUNNING)
struct module_zeroconf_publish_data *d = s->userdata;
int proto;
uint16_t port;
if (find_port(s, &proto, &port) < 0)
return;
if (!d->client || avahi_client_get_state(d->client) != AVAHI_CLIENT_S_RUNNING)
return;
if (!s->entry_group) {
s->entry_group = avahi_entry_group_new(s->userdata->client, service_entry_group_callback, s);
s->entry_group = avahi_entry_group_new(d->client, service_entry_group_callback, s);
if (s->entry_group == NULL) {
pw_log_error("avahi_entry_group_new(): %s",
avahi_strerror(avahi_client_errno(s->userdata->client)));
avahi_strerror(avahi_client_errno(d->client)));
return;
}
} else {
@ -410,22 +437,22 @@ static void publish_service(struct service *s)
if (avahi_entry_group_add_service_strlst(
s->entry_group,
AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
AVAHI_IF_UNSPEC, proto,
0,
s->service_name,
s->service_type,
NULL,
NULL,
s->userdata->port,
port,
s->txt) < 0) {
pw_log_error("avahi_entry_group_add_service_strlst(): %s",
avahi_strerror(avahi_client_errno(s->userdata->client)));
avahi_strerror(avahi_client_errno(d->client)));
return;
}
if (avahi_entry_group_add_service_subtype(
s->entry_group,
AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
AVAHI_IF_UNSPEC, proto,
0,
s->service_name,
s->service_type,
@ -434,33 +461,33 @@ static void publish_service(struct service *s)
(s->subtype == SUBTYPE_HARDWARE ? SERVICE_SUBTYPE_SOURCE_HARDWARE : (s->subtype == SUBTYPE_VIRTUAL ? SERVICE_SUBTYPE_SOURCE_VIRTUAL : SERVICE_SUBTYPE_SOURCE_MONITOR))) < 0) {
pw_log_error("avahi_entry_group_add_service_subtype(): %s",
avahi_strerror(avahi_client_errno(s->userdata->client)));
avahi_strerror(avahi_client_errno(d->client)));
return;
}
if (!s->is_sink && s->subtype != SUBTYPE_MONITOR) {
if (avahi_entry_group_add_service_subtype(
s->entry_group,
AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
AVAHI_IF_UNSPEC, proto,
0,
s->service_name,
SERVICE_TYPE_SOURCE,
NULL,
SERVICE_SUBTYPE_SOURCE_NON_MONITOR) < 0) {
pw_log_error("avahi_entry_group_add_service_subtype(): %s",
avahi_strerror(avahi_client_errno(s->userdata->client)));
avahi_strerror(avahi_client_errno(d->client)));
return;
}
}
if (avahi_entry_group_commit(s->entry_group) < 0) {
pw_log_error("avahi_entry_group_commit(): %s",
avahi_strerror(avahi_client_errno(s->userdata->client)));
avahi_strerror(avahi_client_errno(d->client)));
return;
}
spa_list_remove(&s->link);
spa_list_append(&s->userdata->published, &s->link);
spa_list_append(&d->published, &s->link);
pw_log_info("created service: %s", s->service_name);
}
@ -642,7 +669,6 @@ static int module_zeroconf_publish_unload(struct module *module)
static const struct spa_dict_item module_zeroconf_publish_info[] = {
{ PW_KEY_MODULE_AUTHOR, "Sanchayan Maity <sanchayan@asymptotic.io" },
{ PW_KEY_MODULE_DESCRIPTION, "mDNS/DNS-SD Service Publish" },
{ PW_KEY_MODULE_USAGE, "port=<TCP port number>" },
{ PW_KEY_MODULE_VERSION, PACKAGE_VERSION },
};
@ -652,7 +678,6 @@ static int module_zeroconf_publish_prepare(struct module * const module)
struct module_zeroconf_publish_data * const data = module->user_data;
data->module = module;
data->port = pw_properties_get_uint32(module->props, "port", PW_PROTOCOL_PULSE_DEFAULT_PORT);
spa_list_init(&data->pending);
spa_list_init(&data->published);