zeroconf: sanitize the properties

Use some constants for the zeroconf properties. Make the right ones are
used in all places.
This commit is contained in:
Wim Taymans 2026-02-27 17:20:26 +01:00
parent 3a1b790588
commit dee2d5ee06
10 changed files with 165 additions and 133 deletions

View file

@ -273,10 +273,10 @@ static void fill_service_data(struct module_zeroconf_publish_data *d, struct ser
pw_properties_set(s->props, "channel_map", channel_map_snprint(cm, sizeof(cm), &s->cm));
pw_properties_set(s->props, "subtype", subtype);
pw_properties_setf(s->props, "zeroconf.session", "%s@%s: %s",
pw_properties_setf(s->props, PW_KEY_ZEROCONF_NAME, "%s@%s: %s",
pw_get_user_name(), pw_get_host_name(), desc);
pw_properties_set(s->props, "zeroconf.service", service_type);
pw_properties_setf(s->props, "zeroconf.subtypes", "[ %s%s%s ]",
pw_properties_set(s->props, PW_KEY_ZEROCONF_TYPE, service_type);
pw_properties_setf(s->props, PW_KEY_ZEROCONF_SUBTYPES, "[ %s%s%s ]",
n_subtype > 0 ? subtype_service[0] : "",
n_subtype > 1 ? ", " : "",
n_subtype > 1 ? subtype_service[1] : "");
@ -337,8 +337,8 @@ static void publish_service(struct service *s)
pw_log_debug("found server:%p proto:%d port:%d", server, proto, port);
pw_properties_setf(s->props, "zeroconf.proto", "%d", proto);
pw_properties_setf(s->props, "zeroconf.port", "%d", port);
pw_properties_setf(s->props, PW_KEY_ZEROCONF_PROTO, "%d", proto);
pw_properties_setf(s->props, PW_KEY_ZEROCONF_PORT, "%d", port);
if ((res = pw_zeroconf_set_announce(s->userdata->zeroconf, s, &s->props->dict)) < 0) {
pw_log_error("failed to announce service %s: %s", device, spa_strerror(res));

View file

@ -280,22 +280,22 @@ static int rule_matched(void *data, const char *location, const char *action,
static void pw_properties_from_zeroconf(const char *key, const char *value,
struct pw_properties *props)
{
if (spa_streq(key, "zeroconf.ifindex")) {
if (spa_streq(key, PW_KEY_ZEROCONF_IFINDEX)) {
pw_properties_set(props, "raop.ifindex", value);
}
else if (spa_streq(key, "zeroconf.address")) {
else if (spa_streq(key, PW_KEY_ZEROCONF_ADDRESS)) {
pw_properties_set(props, "raop.ip", value);
}
else if (spa_streq(key, "zeroconf.port")) {
else if (spa_streq(key, PW_KEY_ZEROCONF_PORT)) {
pw_properties_set(props, "raop.port", value);
}
else if (spa_streq(key, "zeroconf.name")) {
else if (spa_streq(key, PW_KEY_ZEROCONF_NAME)) {
pw_properties_set(props, "raop.name", value);
}
else if (spa_streq(key, "zeroconf.hostname")) {
else if (spa_streq(key, PW_KEY_ZEROCONF_HOSTNAME)) {
pw_properties_set(props, "raop.hostname", value);
}
else if (spa_streq(key, "zeroconf.domain")) {
else if (spa_streq(key, PW_KEY_ZEROCONF_DOMAIN)) {
pw_properties_set(props, "raop.domain", value);
}
else if (spa_streq(key, "device")) {
@ -372,7 +372,7 @@ static void on_zeroconf_added(void *data, const void *user, const struct spa_dic
const struct spa_dict_item *it;
struct pw_properties *props = NULL;
name = spa_dict_lookup(info, "zeroconf.name");
name = spa_dict_lookup(info, PW_KEY_ZEROCONF_NAME);
t = find_tunnel(impl, name);
if (t == NULL) {
@ -384,7 +384,7 @@ static void on_zeroconf_added(void *data, const void *user, const struct spa_dic
if (t->module != NULL) {
pw_log_info("found duplicate mdns entry for %s on IP %s - "
"skipping tunnel creation", name,
spa_dict_lookup(info, "zeroconf.address"));
spa_dict_lookup(info, PW_KEY_ZEROCONF_ADDRESS));
goto done;
}
@ -423,7 +423,7 @@ static void on_zeroconf_removed(void *data, const void *user, const struct spa_d
const char *name;
struct tunnel *t;
name = spa_dict_lookup(info, "zeroconf.name");
name = spa_dict_lookup(info, PW_KEY_ZEROCONF_NAME);
if ((t = find_tunnel(impl, name)) == NULL)
return;
@ -468,7 +468,7 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
if ((local = pw_properties_get(impl->properties, "raop.discover-local")) == NULL)
local = "false";
pw_properties_set(impl->properties, "zeroconf.discover-local", local);
pw_properties_set(impl->properties, PW_KEY_ZEROCONF_DISCOVER_LOCAL, local);
pw_impl_module_add_listener(module, &impl->module_listener, &module_events, impl);
@ -483,7 +483,7 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
pw_zeroconf_set_browse(impl->zeroconf, NULL,
&SPA_DICT_ITEMS(
SPA_DICT_ITEM("zeroconf.service", SERVICE_TYPE_SINK)));
SPA_DICT_ITEM(PW_KEY_ZEROCONF_TYPE, SERVICE_TYPE_SINK)));
return 0;
error_errno:

View file

@ -1269,7 +1269,7 @@ static const struct pw_core_events core_events = {
.error = on_core_error,
};
static const char *get_service_name(struct impl *impl)
static const char *get_service_type(struct impl *impl)
{
const char *str;
str = pw_properties_get(impl->props, "sess.media");
@ -1283,33 +1283,33 @@ static const char *get_service_name(struct impl *impl)
static void on_zeroconf_added(void *data, const void *user, const struct spa_dict *info)
{
struct impl *impl = data;
const char *str, *service_name, *address, *hostname;
const char *str, *service_type, *address, *hostname;
struct service_info sinfo;
struct session *sess;
int ifindex = -1, protocol = 0, res, port = 0;
struct pw_properties *props = NULL;
bool compatible = true;
if ((str = spa_dict_lookup(info, "zeroconf.ifindex")))
if ((str = spa_dict_lookup(info, PW_KEY_ZEROCONF_IFINDEX)))
ifindex = atoi(str);
if ((str = spa_dict_lookup(info, "zeroconf.protocol")))
if ((str = spa_dict_lookup(info, PW_KEY_ZEROCONF_PROTO)))
protocol = atoi(str);
if ((str = spa_dict_lookup(info, "zeroconf.port")))
if ((str = spa_dict_lookup(info, PW_KEY_ZEROCONF_PORT)))
port = atoi(str);
sinfo = SERVICE_INFO(.ifindex = ifindex,
.protocol = protocol,
.name = spa_dict_lookup(info, "zeroconf.session"),
.type = spa_dict_lookup(info, "zeroconf.service"),
.domain = spa_dict_lookup(info, "zeroconf.domain"));
.name = spa_dict_lookup(info, PW_KEY_ZEROCONF_NAME),
.type = spa_dict_lookup(info, PW_KEY_ZEROCONF_TYPE),
.domain = spa_dict_lookup(info, PW_KEY_ZEROCONF_DOMAIN));
sess = find_session_by_info(impl, &sinfo);
if (sess != NULL)
return;
/* check for compatible session */
service_name = get_service_name(impl);
compatible = spa_streq(service_name, sinfo.type);
service_type = get_service_type(impl);
compatible = spa_streq(service_type, sinfo.type);
props = pw_properties_copy(impl->stream_props);
if (props == NULL) {
@ -1317,7 +1317,7 @@ static void on_zeroconf_added(void *data, const void *user, const struct spa_dic
goto error;
}
if (spa_streq(service_name, "_pipewire-audio._udp")) {
if (spa_streq(service_type, "_pipewire-audio._udp")) {
uint32_t mask = 0;
const struct spa_dict_item *it;
spa_dict_for_each(it, info) {
@ -1378,8 +1378,8 @@ static void on_zeroconf_added(void *data, const void *user, const struct spa_dic
goto error;
}
address = spa_dict_lookup(info, "zeroconf.address");
hostname = spa_dict_lookup(info, "zeroconf.hostname");
address = spa_dict_lookup(info, PW_KEY_ZEROCONF_ADDRESS);
hostname = spa_dict_lookup(info, PW_KEY_ZEROCONF_HOSTNAME);
pw_log_info("create session: %s %s:%u %s", sinfo.name, address, port, sinfo.type);
@ -1425,16 +1425,16 @@ static void on_zeroconf_removed(void *data, const void *user, const struct spa_d
const char *str;
int ifindex = -1, protocol = 0;
if ((str = spa_dict_lookup(info, "zeroconf.ifindex")))
if ((str = spa_dict_lookup(info, PW_KEY_ZEROCONF_IFINDEX)))
ifindex = atoi(str);
if ((str = spa_dict_lookup(info, "zeroconf.protocol")))
if ((str = spa_dict_lookup(info, PW_KEY_ZEROCONF_PROTO)))
protocol = atoi(str);
sinfo = SERVICE_INFO(.ifindex = ifindex,
.protocol = protocol,
.name = spa_dict_lookup(info, "zeroconf.session"),
.type = spa_dict_lookup(info, "zeroconf.service"),
.domain = spa_dict_lookup(info, "zeroconf.domain"));
.name = spa_dict_lookup(info, PW_KEY_ZEROCONF_NAME),
.type = spa_dict_lookup(info, PW_KEY_ZEROCONF_TYPE),
.domain = spa_dict_lookup(info, PW_KEY_ZEROCONF_DOMAIN));
sess = find_session_by_info(impl, &sinfo);
if (sess == NULL)
@ -1445,18 +1445,18 @@ static void on_zeroconf_removed(void *data, const void *user, const struct spa_d
static int make_browser(struct impl *impl)
{
const char *service_name;
const char *service_type;
int res;
service_name = get_service_name(impl);
if (service_name == NULL)
service_type = get_service_type(impl);
if (service_type == NULL)
return -EINVAL;
if ((res = pw_zeroconf_set_browse(impl->zeroconf, impl,
&SPA_DICT_ITEMS(
SPA_DICT_ITEM("zeroconf.service", service_name)))) < 0) {
SPA_DICT_ITEM(PW_KEY_ZEROCONF_TYPE, service_type)))) < 0) {
pw_log_error("can't make browser for %s: %s",
service_name, spa_strerror(res));
service_type, spa_strerror(res));
return res;
}
return 0;
@ -1465,15 +1465,15 @@ static int make_browser(struct impl *impl)
static int make_announce(struct impl *impl)
{
int res;
const char *service_name, *str;
const char *service_type, *str;
struct pw_properties *props;
props = pw_properties_new(NULL, NULL);
if ((service_name = get_service_name(impl)) == NULL)
if ((service_type = get_service_type(impl)) == NULL)
return -ENOTSUP;
if (spa_streq(service_name, "_pipewire-audio._udp")) {
if (spa_streq(service_type, "_pipewire-audio._udp")) {
str = pw_properties_get(impl->props, "sess.media");
pw_properties_set(props, "subtype", str);
if ((str = pw_properties_get(impl->stream_props, PW_KEY_AUDIO_FORMAT)) != NULL)
@ -1494,9 +1494,9 @@ static int make_announce(struct impl *impl)
}
}
pw_properties_set(props, "zeroconf.session", impl->session_name);
pw_properties_set(props, "zeroconf.service", service_name);
pw_properties_setf(props, "zeroconf.port", "%u", impl->ctrl_port);
pw_properties_set(props, PW_KEY_ZEROCONF_NAME, impl->session_name);
pw_properties_set(props, PW_KEY_ZEROCONF_TYPE, service_type);
pw_properties_setf(props, PW_KEY_ZEROCONF_PORT, "%u", impl->ctrl_port);
res = pw_zeroconf_set_announce(impl->zeroconf, impl, &props->dict);
@ -1555,7 +1555,7 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
impl->discover_local = pw_properties_get_bool(impl->props,
"sess.discover-local", false);
pw_properties_set(impl->props, "zeroconf.discover-local",
pw_properties_set(impl->props, PW_KEY_ZEROCONF_DISCOVER_LOCAL,
impl->discover_local ? "true" : "false");
stream_props = pw_properties_new(NULL, NULL);

View file

@ -1116,7 +1116,7 @@ static void on_zeroconf_added(void *data, const void *user, const struct spa_dic
struct client *c;
struct pw_properties *props;
name = spa_dict_lookup(info, "zeroconf.hostname");
name = spa_dict_lookup(info, PW_KEY_ZEROCONF_NAME);
if (impl->single_server && !spa_list_is_empty(&impl->clients))
return;
@ -1127,8 +1127,8 @@ static void on_zeroconf_added(void *data, const void *user, const struct spa_dic
props = pw_properties_copy(impl->stream_props);
pw_properties_update(props, info);
addr = spa_dict_lookup(info, "zeroconf.address");
port = spa_dict_lookup(info, "zeroconf.port");
addr = spa_dict_lookup(info, PW_KEY_ZEROCONF_ADDRESS);
port = spa_dict_lookup(info, PW_KEY_ZEROCONF_PORT);
path = spa_dict_lookup(info, "path");
pw_properties_set(props, "sendspin.ip", addr);
@ -1144,7 +1144,7 @@ static void on_zeroconf_removed(void *data, const void *user, const struct spa_d
const char *name;
struct client *c;
name = spa_dict_lookup(info, "zeroconf.hostname");
name = spa_dict_lookup(info, PW_KEY_ZEROCONF_NAME);
if ((c = client_find(impl, name)) == NULL)
return;
@ -1341,9 +1341,9 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
str = pw_properties_get(props, "sendspin.client-id");
pw_zeroconf_set_announce(impl->zeroconf, NULL,
&SPA_DICT_ITEMS(
SPA_DICT_ITEM("zeroconf.service", PW_SENDSPIN_CLIENT_SERVICE),
SPA_DICT_ITEM("zeroconf.session", str),
SPA_DICT_ITEM("zeroconf.port", port),
SPA_DICT_ITEM(PW_KEY_ZEROCONF_TYPE, PW_SENDSPIN_CLIENT_SERVICE_TYPE),
SPA_DICT_ITEM(PW_KEY_ZEROCONF_NAME, str),
SPA_DICT_ITEM(PW_KEY_ZEROCONF_PORT, port),
SPA_DICT_ITEM("path", path)));
}
}
@ -1371,7 +1371,7 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
if (impl->zeroconf) {
pw_zeroconf_set_browse(impl->zeroconf, NULL,
&SPA_DICT_ITEMS(
SPA_DICT_ITEM("zeroconf.service", PW_SENDSPIN_SERVER_SERVICE)));
SPA_DICT_ITEM(PW_KEY_ZEROCONF_TYPE, PW_SENDSPIN_SERVER_SERVICE_TYPE)));
}
}

View file

@ -1117,7 +1117,7 @@ static void on_zeroconf_added(void *data, const void *user, const struct spa_dic
struct client *c;
struct pw_properties *props;
name = spa_dict_lookup(info, "zeroconf.hostname");
name = spa_dict_lookup(info, PW_KEY_ZEROCONF_NAME);
if ((c = client_find(impl, name)) != NULL)
return;
@ -1125,8 +1125,8 @@ static void on_zeroconf_added(void *data, const void *user, const struct spa_dic
props = pw_properties_copy(impl->stream_props);
pw_properties_update(props, info);
addr = spa_dict_lookup(info, "zeroconf.address");
port = spa_dict_lookup(info, "zeroconf.port");
addr = spa_dict_lookup(info, PW_KEY_ZEROCONF_ADDRESS);
port = spa_dict_lookup(info, PW_KEY_ZEROCONF_PORT);
path = spa_dict_lookup(info, "path");
pw_properties_set(props, "sendspin.ip", addr);
@ -1142,7 +1142,7 @@ static void on_zeroconf_removed(void *data, const void *user, const struct spa_d
const char *name;
struct client *c;
name = spa_dict_lookup(info, "zeroconf.hostname");
name = spa_dict_lookup(info, PW_KEY_ZEROCONF_NAME);
if ((c = client_find(impl, name)) == NULL)
return;
@ -1368,16 +1368,16 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
str = pw_properties_get(props, "sendspin.group-name");
pw_zeroconf_set_announce(impl->zeroconf, NULL,
&SPA_DICT_ITEMS(
SPA_DICT_ITEM("zeroconf.service", PW_SENDSPIN_SERVER_SERVICE),
SPA_DICT_ITEM("zeroconf.session", str),
SPA_DICT_ITEM("zeroconf.port", port),
SPA_DICT_ITEM(PW_KEY_ZEROCONF_TYPE, PW_SENDSPIN_SERVER_SERVICE_TYPE),
SPA_DICT_ITEM(PW_KEY_ZEROCONF_NAME, str),
SPA_DICT_ITEM(PW_KEY_ZEROCONF_PORT, port),
SPA_DICT_ITEM("path", path)));
}
}
if (impl->zeroconf) {
pw_zeroconf_set_browse(impl->zeroconf, NULL,
&SPA_DICT_ITEMS(
SPA_DICT_ITEM("zeroconf.service", PW_SENDSPIN_CLIENT_SERVICE)));
SPA_DICT_ITEM(PW_KEY_ZEROCONF_TYPE, PW_SENDSPIN_CLIENT_SERVICE_TYPE)));
}
pw_impl_module_add_listener(module, &impl->module_listener, &module_events, impl);

View file

@ -13,8 +13,8 @@
extern "C" {
#endif
#define PW_SENDSPIN_SERVER_SERVICE "_sendspin-server._tcp"
#define PW_SENDSPIN_CLIENT_SERVICE "_sendspin._tcp"
#define PW_SENDSPIN_SERVER_SERVICE_TYPE "_sendspin-server._tcp"
#define PW_SENDSPIN_CLIENT_SERVICE_TYPE "_sendspin._tcp"
#define PW_SENDSPIN_DEFAULT_SERVER_PORT 8927
#define PW_SENDSPIN_DEFAULT_CLIENT_PORT 8928

View file

@ -614,14 +614,14 @@ static void on_zeroconf_added(void *data, const void *user, const struct spa_dic
int res, family, port = 0, ifindex = 0, protocol = 4;
const struct spa_dict_item *it;
name = spa_dict_lookup(info, "zeroconf.name");
address = spa_dict_lookup(info, "zeroconf.address");
if ((str = spa_dict_lookup(info, "zeroconf.protocol")))
protocol = atoi(str);
if ((str = spa_dict_lookup(info, "zeroconf.port")))
port = atoi(str);
if ((str = spa_dict_lookup(info, "zeroconf.ifindex")))
if ((str = spa_dict_lookup(info, PW_KEY_ZEROCONF_IFINDEX)))
ifindex = atoi(str);
if ((str = spa_dict_lookup(info, PW_KEY_ZEROCONF_PROTO)))
protocol = atoi(str);
name = spa_dict_lookup(info, PW_KEY_ZEROCONF_NAME);
address = spa_dict_lookup(info, PW_KEY_ZEROCONF_ADDRESS);
if ((str = spa_dict_lookup(info, PW_KEY_ZEROCONF_PORT)))
port = atoi(str);
tinfo = TUNNEL_INFO(.name = name, .port = port);
@ -648,8 +648,8 @@ static void on_zeroconf_added(void *data, const void *user, const struct spa_dic
pw_properties_setf(props, "snapcast.ifindex", "%u", ifindex);
pw_properties_setf(props, "snapcast.port", "%u", port);
pw_properties_set(props, "snapcast.name", name);
pw_properties_set(props, "snapcast.hostname", spa_dict_lookup(info, "zeroconf.hostname"));
pw_properties_set(props, "snapcast.domain", spa_dict_lookup(info, "zeroconf.domain"));
pw_properties_set(props, "snapcast.hostname", spa_dict_lookup(info, PW_KEY_ZEROCONF_HOSTNAME));
pw_properties_set(props, "snapcast.domain", spa_dict_lookup(info, PW_KEY_ZEROCONF_DOMAIN));
free((char*)t->info.host);
t->info.host = strdup(pw_properties_get(props, "snapcast.ip"));
@ -724,7 +724,7 @@ static void on_zeroconf_removed(void *data, const void *user, const struct spa_d
struct tunnel_info tinfo;
const char *name;
name = spa_dict_lookup(info, "zeroconf.name");
name = spa_dict_lookup(info, PW_KEY_ZEROCONF_NAME);
tinfo = TUNNEL_INFO(.name = name);
@ -740,7 +740,7 @@ static int make_browser(struct impl *impl, const char *service_type)
int res;
if ((res = pw_zeroconf_set_browse(impl->zeroconf, service_type,
&SPA_DICT_ITEMS(
SPA_DICT_ITEM("zeroconf.service", service_type)))) < 0) {
SPA_DICT_ITEM(PW_KEY_ZEROCONF_TYPE, service_type)))) < 0) {
pw_log_error("can't make browser for %s: %s",
service_type, spa_strerror(res));
return res;
@ -786,7 +786,7 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
impl->discover_local = pw_properties_get_bool(impl->properties,
"snapcast.discover-local", false);
pw_properties_set(props, "zeroconf.discover-local",
pw_properties_set(props, PW_KEY_ZEROCONF_DISCOVER_LOCAL,
impl->discover_local ? "true" : "false");
impl->zeroconf = pw_zeroconf_new(impl->context, &props->dict);

View file

@ -239,8 +239,8 @@ static void on_zeroconf_added(void *data, const void *user_data, const struct sp
struct pw_impl_module *mod;
struct pw_properties *props = NULL;
name = spa_dict_lookup(info, "zeroconf.name");
type = spa_dict_lookup(info, "zeroconf.type");
name = spa_dict_lookup(info, PW_KEY_ZEROCONF_NAME);
type = spa_dict_lookup(info, PW_KEY_ZEROCONF_TYPE);
mode = strstr(type, "sink") ? "sink" : "source";
tinfo = TUNNEL_INFO(.name = name, .mode = mode);
@ -266,7 +266,7 @@ static void on_zeroconf_added(void *data, const void *user_data, const struct sp
spa_dict_for_each(it, info)
pw_properties_from_zeroconf(it->key, it->value, props);
host_name = spa_dict_lookup(info, "zeroconf.hostname");
host_name = spa_dict_lookup(info, PW_KEY_ZEROCONF_HOSTNAME);
if ((device = pw_properties_get(props, PW_KEY_TARGET_OBJECT)) != NULL)
pw_properties_setf(props, PW_KEY_NODE_NAME,
@ -278,8 +278,8 @@ static void on_zeroconf_added(void *data, const void *user_data, const struct sp
pw_properties_set(props, "tunnel.mode", mode);
pw_properties_setf(props, "pulse.server.address", " [%s]:%s",
spa_dict_lookup(info, "zeroconf.address"),
spa_dict_lookup(info, "zeroconf.port"));
spa_dict_lookup(info, PW_KEY_ZEROCONF_ADDRESS),
spa_dict_lookup(info, PW_KEY_ZEROCONF_PORT));
desc = pw_properties_get(props, "tunnel.remote.description");
if (desc == NULL)
@ -347,8 +347,8 @@ static void on_zeroconf_removed(void *data, const void *user, const struct spa_d
struct tunnel *t;
struct tunnel_info tinfo;
name = spa_dict_lookup(info, "zeroconf.name");
type = spa_dict_lookup(info, "zeroconf.type");
name = spa_dict_lookup(info, PW_KEY_ZEROCONF_NAME);
type = spa_dict_lookup(info, PW_KEY_ZEROCONF_TYPE);
mode = strstr(type, "sink") ? "sink" : "source";
tinfo = TUNNEL_INFO(.name = name, .mode = mode);
@ -397,7 +397,7 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
discover_local = pw_properties_get_bool(impl->properties,
"pulse.discover-local", false);
pw_properties_setf(impl->properties, "zeroconf.discover-local",
pw_properties_setf(impl->properties, PW_KEY_ZEROCONF_DISCOVER_LOCAL,
discover_local ? "true" : "false");
pw_impl_module_add_listener(module, &impl->module_listener, &module_events, impl);
@ -413,11 +413,11 @@ int pipewire__module_init(struct pw_impl_module *module, const char *args)
pw_zeroconf_set_browse(impl->zeroconf, SERVICE_TYPE_SINK,
&SPA_DICT_ITEMS(
SPA_DICT_ITEM("zeroconf.service", SERVICE_TYPE_SINK)));
SPA_DICT_ITEM(PW_KEY_ZEROCONF_TYPE, SERVICE_TYPE_SINK)));
pw_zeroconf_set_browse(impl->zeroconf, SERVICE_TYPE_SOURCE,
&SPA_DICT_ITEMS(
SPA_DICT_ITEM("zeroconf.service", SERVICE_TYPE_SOURCE)));
SPA_DICT_ITEM(PW_KEY_ZEROCONF_TYPE, SERVICE_TYPE_SOURCE)));
return 0;

View file

@ -42,6 +42,8 @@ struct service_info {
#define SERVICE_INFO(...) ((struct service_info){ __VA_ARGS__ })
#define STR_TO_PROTO(s) (atoi(s) == 6 ? AVAHI_PROTO_INET6 : AVAHI_PROTO_INET)
struct entry {
struct pw_zeroconf *zc;
struct spa_list link;
@ -198,17 +200,18 @@ static struct service *service_new(struct entry *e,
spa_strstartswith(at, link_local_range))
snprintf(if_suffix, sizeof(if_suffix), "%%%d", info->interface);
if (a->proto != AVAHI_PROTO_UNSPEC)
pw_properties_setf(s->props, "zeroconf.proto", "%s",
a->proto == AVAHI_PROTO_INET ? "4" : "6");
if (info->interface != AVAHI_IF_UNSPEC)
pw_properties_setf(s->props, "zeroconf.ifindex", "%d", info->interface);
pw_properties_setf(s->props, "zeroconf.name", "%s", info->name);
pw_properties_setf(s->props, "zeroconf.type", "%s", info->type);
pw_properties_setf(s->props, "zeroconf.domain", "%s", info->domain);
pw_properties_setf(s->props, "zeroconf.hostname", "%s", info->host_name);
pw_properties_setf(s->props, "zeroconf.address", "%s%s", at, if_suffix);
pw_properties_setf(s->props, "zeroconf.port", "%u", info->port);
pw_properties_setf(s->props, PW_KEY_ZEROCONF_IFINDEX, "%d", info->interface);
if (a->proto != AVAHI_PROTO_UNSPEC)
pw_properties_set(s->props, PW_KEY_ZEROCONF_PROTO,
a->proto == AVAHI_PROTO_INET ? "4" : "6");
pw_properties_set(s->props, PW_KEY_ZEROCONF_NAME, info->name);
pw_properties_set(s->props, PW_KEY_ZEROCONF_TYPE, info->type);
pw_properties_set(s->props, PW_KEY_ZEROCONF_DOMAIN, info->domain);
pw_properties_set(s->props, PW_KEY_ZEROCONF_HOSTNAME, info->host_name);
pw_properties_setf(s->props, PW_KEY_ZEROCONF_ADDRESS, "%s%s", at, if_suffix);
pw_properties_setf(s->props, PW_KEY_ZEROCONF_PORT, "%u", info->port);
for (l = txt; l; l = l->next) {
char *key, *value;
@ -271,6 +274,8 @@ static void browser_cb(AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProt
struct pw_zeroconf *zc = e->zc;
struct service_info info;
struct service *s;
int aproto = AVAHI_PROTO_UNSPEC;
const char *str;
if ((flags & AVAHI_LOOKUP_RESULT_LOCAL) && !zc->discover_local)
return;
@ -287,10 +292,14 @@ static void browser_cb(AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProt
case AVAHI_BROWSER_NEW:
if (s != NULL)
return;
if ((str = pw_properties_get(e->props, PW_KEY_ZEROCONF_RESOLVE_PROTO)))
aproto = STR_TO_PROTO(str);
if (!(avahi_service_resolver_new(zc->client,
interface, protocol,
name, type, domain,
AVAHI_PROTO_UNSPEC, 0,
aproto, 0,
resolver_cb, e))) {
int res = avahi_client_errno(zc->client);
pw_log_error("can't make service resolver: %s", avahi_strerror(res));
@ -312,23 +321,28 @@ static void browser_cb(AvahiServiceBrowser *b, AvahiIfIndex interface, AvahiProt
static int do_browse(struct pw_zeroconf *zc, struct entry *e)
{
const struct spa_dict_item *it;
const char *service_name = NULL;
int res;
const char *type = NULL, *domain = NULL;
int res, ifindex = AVAHI_IF_UNSPEC, proto = AVAHI_PROTO_UNSPEC;
if (e->browser == NULL) {
spa_dict_for_each(it, &e->props->dict) {
if (spa_streq(it->key, "zeroconf.service"))
service_name = it->value;
if (spa_streq(it->key, PW_KEY_ZEROCONF_IFINDEX))
ifindex = atoi(it->value);
else if (spa_streq(it->key, PW_KEY_ZEROCONF_PROTO))
proto = STR_TO_PROTO(it->value);
else if (spa_streq(it->key, PW_KEY_ZEROCONF_TYPE))
type = it->value;
else if (spa_streq(it->key, PW_KEY_ZEROCONF_DOMAIN))
domain = it->value;
}
if (service_name == NULL) {
if (type == NULL) {
res = -EINVAL;
pw_log_error("can't make browser: no service provided");
pw_log_error("can't make browser: no "PW_KEY_ZEROCONF_TYPE" provided");
pw_zeroconf_emit_error(zc, res, spa_strerror(res));
return res;
}
e->browser = avahi_service_browser_new(zc->client,
AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC,
service_name, NULL, 0,
ifindex, proto, type, domain, 0,
browser_cb, e);
if (e->browser == NULL) {
res = avahi_client_errno(zc->client);
@ -349,7 +363,7 @@ static void entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state,
zc->refcount++;
name = pw_properties_get(e->props, "zeroconf.session");
name = pw_properties_get(e->props, PW_KEY_ZEROCONF_NAME);
switch (state) {
case AVAHI_ENTRY_GROUP_ESTABLISHED:
@ -375,7 +389,7 @@ static int do_announce(struct pw_zeroconf *zc, struct entry *e)
AvahiStringList *txt = NULL;
int res, ifindex = AVAHI_IF_UNSPEC, proto = AVAHI_PROTO_UNSPEC;
const struct spa_dict_item *it;
const char *session_name = "unnamed", *service = NULL, *subtypes = NULL;
const char *name = "unnamed", *type = NULL, *subtypes = NULL;
const char *domain = NULL, *host = NULL;
uint16_t port = 0;
@ -392,36 +406,36 @@ static int do_announce(struct pw_zeroconf *zc, struct entry *e)
avahi_entry_group_reset(e->group);
spa_dict_for_each(it, &e->props->dict) {
if (spa_streq(it->key, "zeroconf.session"))
session_name = it->value;
else if (spa_streq(it->key, "zeroconf.port"))
port = atoi(it->value);
else if (spa_streq(it->key, "zeroconf.service"))
service = it->value;
else if (spa_streq(it->key, "zeroconf.domain"))
domain = it->value;
else if (spa_streq(it->key, "zeroconf.host"))
host = it->value;
else if (spa_streq(it->key, "zeroconf.ifindex"))
if (spa_streq(it->key, PW_KEY_ZEROCONF_IFINDEX))
ifindex = atoi(it->value);
else if (spa_streq(it->key, "zeroconf.proto"))
proto = atoi(it->value) == 6 ? AVAHI_PROTO_INET6 : AVAHI_PROTO_INET;
else if (spa_streq(it->key, "zeroconf.subtypes"))
else if (spa_streq(it->key, PW_KEY_ZEROCONF_PROTO))
proto = STR_TO_PROTO(it->value);
else if (spa_streq(it->key, PW_KEY_ZEROCONF_NAME))
name = it->value;
else if (spa_streq(it->key, PW_KEY_ZEROCONF_TYPE))
type = it->value;
else if (spa_streq(it->key, PW_KEY_ZEROCONF_DOMAIN))
domain = it->value;
else if (spa_streq(it->key, PW_KEY_ZEROCONF_HOST))
host = it->value;
else if (spa_streq(it->key, PW_KEY_ZEROCONF_PORT))
port = atoi(it->value);
else if (spa_streq(it->key, PW_KEY_ZEROCONF_SUBTYPES))
subtypes = it->value;
else
else if (!spa_strstartswith(it->key, "zeroconf."))
txt = avahi_string_list_add_pair(txt, it->key, it->value);
}
if (service == NULL) {
if (type == NULL) {
res = -EINVAL;
pw_log_error("can't announce: no service provided");
pw_log_error("can't announce: no "PW_KEY_ZEROCONF_TYPE" provided");
pw_zeroconf_emit_error(zc, res, spa_strerror(res));
avahi_string_list_free(txt);
return res;
}
res = avahi_entry_group_add_service_strlst(e->group,
ifindex, proto,
(AvahiPublishFlags)0, session_name,
service, domain, host, port, txt);
(AvahiPublishFlags)0, name,
type, domain, host, port, txt);
avahi_string_list_free(txt);
if (res < 0) {
@ -444,11 +458,11 @@ static int do_announce(struct pw_zeroconf *zc, struct entry *e)
while (spa_json_get_string(&iter, v, sizeof(v)) > 0) {
res = avahi_entry_group_add_service_subtype(e->group,
ifindex, proto,
(AvahiPublishFlags)0, session_name,
service, domain, v);
(AvahiPublishFlags)0, name,
type, domain, v);
if (res < 0) {
res = avahi_client_errno(zc->client);
pw_log_error("can't add subtype: %s", avahi_strerror(res));
pw_log_error("can't add subtype %s: %s", v, avahi_strerror(res));
pw_zeroconf_emit_error(zc, res, avahi_strerror(res));
return -EIO;
}
@ -518,9 +532,13 @@ static struct entry *entry_new(struct pw_zeroconf *zc, uint32_t type, const void
e->props = pw_properties_new_dict(info);
spa_list_append(&zc->entries, &e->link);
spa_list_init(&e->services);
pw_log_debug("created %s for \"%s\"",
type == TYPE_ANNOUNCE ? "announce" : "browse",
pw_properties_get(e->props, "zeroconf.session"));
if (type == TYPE_ANNOUNCE)
pw_log_debug("created announce for \"%s\"",
pw_properties_get(e->props, PW_KEY_ZEROCONF_NAME));
else
pw_log_debug("created browse for \"%s\"",
pw_properties_get(e->props, PW_KEY_ZEROCONF_TYPE));
return e;
}
@ -576,7 +594,7 @@ struct pw_zeroconf * pw_zeroconf_new(struct pw_context *context,
const char *k = props->items[i].key;
const char *v = props->items[i].value;
if (spa_streq(k, "zeroconf.discover-local") && v)
if (spa_streq(k, PW_KEY_ZEROCONF_DISCOVER_LOCAL) && v)
zc->discover_local = spa_atob(v);
}

View file

@ -13,6 +13,20 @@
extern "C" {
#endif
#define PW_KEY_ZEROCONF_DISCOVER_LOCAL "zeroconf.discover-local" /* discover local services, true by default */
#define PW_KEY_ZEROCONF_IFINDEX "zeroconf.ifindex" /* interface index */
#define PW_KEY_ZEROCONF_PROTO "zeroconf.proto" /* protocol version, "4" ot "6" */
#define PW_KEY_ZEROCONF_NAME "zeroconf.name" /* session name */
#define PW_KEY_ZEROCONF_TYPE "zeroconf.type" /* service type, like "_http._tcp", not NULL */
#define PW_KEY_ZEROCONF_DOMAIN "zeroconf.domain" /* domain to register in, recommended NULL */
#define PW_KEY_ZEROCONF_HOST "zeroconf.host" /* host to register on, recommended NULL */
#define PW_KEY_ZEROCONF_SUBTYPES "zeroconf.subtypes" /* subtypes to register, array of strings */
#define PW_KEY_ZEROCONF_RESOLVE_PROTO "zeroconf.resolve-proto" /* protocol to resolve to, "4" or "6" */
#define PW_KEY_ZEROCONF_HOSTNAME "zeroconf.hostname" /* hostname of resolved service */
#define PW_KEY_ZEROCONF_PORT "zeroconf.port" /* port of resolved service */
#define PW_KEY_ZEROCONF_ADDRESS "zeroconf.address" /* address of resolved service */
struct pw_zeroconf;
struct pw_zeroconf_events {