1941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering/***
2941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering  This file is part of avahi.
3a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
4941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering  avahi is free software; you can redistribute it and/or modify it
5941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering  under the terms of the GNU Lesser General Public License as
6941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering  published by the Free Software Foundation; either version 2.1 of the
7941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering  License, or (at your option) any later version.
8a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
9941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering  avahi is distributed in the hope that it will be useful, but WITHOUT
10941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
12941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering  Public License for more details.
13a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
14941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering  You should have received a copy of the GNU Lesser General Public
15941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering  License along with avahi; if not, write to the Free Software
16941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering  USA.
18941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering***/
19941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
20941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering#ifdef HAVE_CONFIG_H
21941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering#include <config.h>
22941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering#endif
23941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
24941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering#include <pthread.h>
25941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering#include <assert.h>
26941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering#include <unistd.h>
27941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering#include <stdio.h>
28941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering#include <errno.h>
29941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering#include <string.h>
30941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering#include <signal.h>
31941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering#include <netinet/in.h>
32e559962871b8564afb6199f3b5fe24cd47607745Lennart Poettering#include <fcntl.h>
33941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
34270ea0a81dacf6a2073019d232b6f106e33eeb14Sebastien Estienne#include <sys/types.h>
35270ea0a81dacf6a2073019d232b6f106e33eeb14Sebastien Estienne#include <sys/socket.h>
36270ea0a81dacf6a2073019d232b6f106e33eeb14Sebastien Estienne
37941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering#include <avahi-common/simple-watch.h>
388e46e738cae449bf44232c66e973c8e9e15fbcb5Robert Ginda#include "avahi-common/avahi-malloc.h"
39941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering#include <avahi-common/error.h>
40941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering#include <avahi-common/domain.h>
41941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering#include <avahi-common/alternative.h>
420c54764cf19428a0c52724a75ddf3368e3899209Lennart Poettering
43941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering#include <avahi-client/client.h>
440c54764cf19428a0c52724a75ddf3368e3899209Lennart Poettering#include <avahi-client/publish.h>
450c54764cf19428a0c52724a75ddf3368e3899209Lennart Poettering#include <avahi-client/lookup.h>
46941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
47941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering#include "warn.h"
48941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering#include "dns_sd.h"
49941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
50941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringenum {
51786a6a7fa3840d06e64f7429e134ddb06cc1deddLennart Poettering    COMMAND_POLL = 'p',
52786a6a7fa3840d06e64f7429e134ddb06cc1deddLennart Poettering    COMMAND_QUIT = 'q',
539da0241b9c1bf751605ba11fa6d4c75e34fe5f2bLennart Poettering    COMMAND_POLL_DONE = 'P',
549da0241b9c1bf751605ba11fa6d4c75e34fe5f2bLennart Poettering    COMMAND_POLL_FAILED = 'F'
55941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering};
56941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
57e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poetteringstruct type_info {
58e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    char *type;
59e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    AvahiStringList *subtypes;
60e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    int n_subtypes;
61e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering};
62e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
63941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringstruct _DNSServiceRef_t {
64941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    int n_ref;
65a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
66941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AvahiSimplePoll *simple_poll;
67941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
68941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    int thread_fd, main_fd;
69941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
70941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    pthread_t thread;
71941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    int thread_running;
72941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
73941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    pthread_mutex_t mutex;
74a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
75941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    void *context;
76941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceBrowseReply service_browser_callback;
77941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceResolveReply service_resolver_callback;
78941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceDomainEnumReply domain_browser_callback;
79941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceRegisterReply service_register_callback;
80e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    DNSServiceQueryRecordReply query_resolver_callback;
81941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
82941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AvahiClient *client;
83941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AvahiServiceBrowser *service_browser;
84941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AvahiServiceResolver *service_resolver;
85941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AvahiDomainBrowser *domain_browser;
86e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    AvahiRecordBrowser *record_browser;
87941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
88e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    struct type_info type_info;
89e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    char *service_name, *service_name_chosen, *service_domain, *service_host;
90941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    uint16_t service_port;
91941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AvahiIfIndex service_interface;
92941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AvahiStringList *service_txt;
93941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
94941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AvahiEntryGroup *entry_group;
95941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering};
96941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
97941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering#define ASSERT_SUCCESS(r) { int __ret = (r); assert(__ret == 0); }
98941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
99941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringstatic DNSServiceErrorType map_error(int error) {
100941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    switch (error) {
101941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_OK :
102941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            return kDNSServiceErr_NoError;
103a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
104941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_BAD_STATE :
105941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            return kDNSServiceErr_BadState;
106a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
107941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_INVALID_HOST_NAME:
108941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_INVALID_DOMAIN_NAME:
109941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_INVALID_TTL:
110941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_IS_PATTERN:
111941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_INVALID_RECORD:
112941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_INVALID_SERVICE_NAME:
113941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_INVALID_SERVICE_TYPE:
114941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_INVALID_PORT:
115941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_INVALID_KEY:
116941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_INVALID_ADDRESS:
117c1d9b9cffd6f756339c1d98a2d2914d49195cb41Lennart Poettering        case AVAHI_ERR_INVALID_SERVICE_SUBTYPE:
118941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            return kDNSServiceErr_BadParam;
119941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
120941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
121f17d2832301b0f2fcd50fdcc6fec77666178158fLennart Poettering        case AVAHI_ERR_COLLISION:
122941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            return kDNSServiceErr_NameConflict;
123941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
124941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_TOO_MANY_CLIENTS:
125941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_TOO_MANY_OBJECTS:
126941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_TOO_MANY_ENTRIES:
127941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_ACCESS_DENIED:
128941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            return kDNSServiceErr_Refused;
129941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
130941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_INVALID_OPERATION:
131941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_INVALID_OBJECT:
132941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            return kDNSServiceErr_Invalid;
133941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
134941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_NO_MEMORY:
135941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            return kDNSServiceErr_NoMemory;
136941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
137941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_INVALID_INTERFACE:
138941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_INVALID_PROTOCOL:
139941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            return kDNSServiceErr_BadInterfaceIndex;
140a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
141941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_INVALID_FLAGS:
142941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            return kDNSServiceErr_BadFlags;
143a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
144941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_NOT_FOUND:
145941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            return kDNSServiceErr_NoSuchName;
146a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
147941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_VERSION_MISMATCH:
148941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            return kDNSServiceErr_Incompatible;
149941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
150941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_NO_NETWORK:
151941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_OS:
152941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_INVALID_CONFIG:
153941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_TIMEOUT:
154941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_DBUS_ERROR:
1554e2113a7d5b702ff070e8220b32662bb00ae02ddLennart Poettering        case AVAHI_ERR_DISCONNECTED:
156941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ERR_NO_DAEMON:
157941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            break;
158941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
159941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    }
160941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
161941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    return kDNSServiceErr_Unknown;
162941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering}
163941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
164e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poetteringstatic void type_info_init(struct type_info *i) {
165e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    assert(i);
166e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    i->type = NULL;
167e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    i->subtypes = NULL;
168e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    i->n_subtypes = 0;
169e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering}
170e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
171e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poetteringstatic void type_info_free(struct type_info *i) {
172e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    assert(i);
173e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
174e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    avahi_free(i->type);
175e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    avahi_string_list_free(i->subtypes);
176e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
177e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    type_info_init(i);
178e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering}
179e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
180e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poetteringstatic int type_info_parse(struct type_info *i, const char *t) {
181e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    char *token = NULL;
182a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
183e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    assert(i);
184e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    assert(t);
185e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
186e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    type_info_init(i);
187e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
188e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    for (;;) {
189e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        size_t l;
190e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
191e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        if (*t == 0)
192e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering            break;
193a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
194e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        l = strcspn(t, ",");
195e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
196e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        if (l <= 0)
197e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering            goto fail;
198a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
199e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        token = avahi_strndup(t, l);
200e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
201e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        if (!token)
202e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering            goto fail;
203e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
204e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        if (!i->type) {
205e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering            /* This is the first token, hence the main type */
206e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
207e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering            if (!avahi_is_valid_service_type_strict(token))
208e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering                goto fail;
209e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
210e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering            i->type = token;
211e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering            token = NULL;
212e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        } else {
213e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering            char *fst;
214a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
215e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering            /* This is not the first token, hence a subtype */
216e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
217e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering            if (!(fst = avahi_strdup_printf("%s._sub.%s", token, i->type)))
218e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering                goto fail;
219e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
220e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering            if (!avahi_is_valid_service_subtype(fst)) {
221e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering                avahi_free(fst);
222e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering                goto fail;
223e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering            }
224e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
225e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering            i->subtypes = avahi_string_list_add(i->subtypes, fst);
226e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering            avahi_free(fst);
227e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
228e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering            avahi_free(token);
229e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering            token = NULL;
230e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
231e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering            i->n_subtypes++;
232e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        }
233e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
234e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        t += l;
235e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
236e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        if (*t == ',')
237e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering            t++;
238e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    }
239e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
240e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    if (i->type)
241e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        return 0;
242a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
243e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poetteringfail:
244e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    type_info_free(i);
245e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    avahi_free(token);
246e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    return -1;
247e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering}
248e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
24926ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poetteringstatic const char *add_trailing_dot(const char *s, char *buf, size_t buf_len) {
25026ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering    if (!s)
25126ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering        return NULL;
25226ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering
25326ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering    if (*s == 0)
25426ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering        return s;
25526ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering
25626ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering    if (s[strlen(s)-1] == '.')
25726ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering        return s;
25826ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering
25926ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering    snprintf(buf, buf_len, "%s.", s);
26026ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering    return buf;
26126ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering}
26226ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering
263941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringstatic int read_command(int fd) {
264941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    ssize_t r;
265941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    char command;
266941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
267941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(fd >= 0);
268a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
269941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if ((r = read(fd, &command, 1)) != 1) {
270941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        fprintf(stderr, __FILE__": read() failed: %s\n", r < 0 ? strerror(errno) : "EOF");
271941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        return -1;
272941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    }
273941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
274941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    return command;
275941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering}
276941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
277941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringstatic int write_command(int fd, char reply) {
278941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(fd >= 0);
279941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
280941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (write(fd, &reply, 1) != 1) {
281941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        fprintf(stderr, __FILE__": write() failed: %s\n", strerror(errno));
282941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        return -1;
283941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    }
284941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
285941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    return 0;
286941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering}
287941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
288941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringstatic int poll_func(struct pollfd *ufds, unsigned int nfds, int timeout, void *userdata) {
289941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceRef sdref = userdata;
290941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    int ret;
291a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
292941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(sdref);
293a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
294941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    ASSERT_SUCCESS(pthread_mutex_unlock(&sdref->mutex));
295941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
296941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering/*     fprintf(stderr, "pre-syscall\n"); */
297941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    ret = poll(ufds, nfds, timeout);
298941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering/*     fprintf(stderr, "post-syscall\n"); */
299a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
300941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    ASSERT_SUCCESS(pthread_mutex_lock(&sdref->mutex));
301941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
302941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    return ret;
303941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering}
304941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
305941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringstatic void * thread_func(void *data) {
306941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceRef sdref = data;
307941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sigset_t mask;
308941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
309941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sigfillset(&mask);
310941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    pthread_sigmask(SIG_BLOCK, &mask, NULL);
311a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
312941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->thread = pthread_self();
313941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->thread_running = 1;
314941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
315941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    for (;;) {
316941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        char command;
317941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
318941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        if ((command = read_command(sdref->thread_fd)) < 0)
319941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            break;
320941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
321941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering/*         fprintf(stderr, "Command: %c\n", command); */
322a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
323941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        switch (command) {
324941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
3259da0241b9c1bf751605ba11fa6d4c75e34fe5f2bLennart Poettering            case COMMAND_POLL: {
3269da0241b9c1bf751605ba11fa6d4c75e34fe5f2bLennart Poettering                int ret;
327941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
328941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                ASSERT_SUCCESS(pthread_mutex_lock(&sdref->mutex));
3299da0241b9c1bf751605ba11fa6d4c75e34fe5f2bLennart Poettering
3309da0241b9c1bf751605ba11fa6d4c75e34fe5f2bLennart Poettering                for (;;) {
3319da0241b9c1bf751605ba11fa6d4c75e34fe5f2bLennart Poettering                    errno = 0;
332a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
3339da0241b9c1bf751605ba11fa6d4c75e34fe5f2bLennart Poettering                    if ((ret = avahi_simple_poll_run(sdref->simple_poll)) < 0) {
3349da0241b9c1bf751605ba11fa6d4c75e34fe5f2bLennart Poettering
3359da0241b9c1bf751605ba11fa6d4c75e34fe5f2bLennart Poettering                        if (errno == EINTR)
3369da0241b9c1bf751605ba11fa6d4c75e34fe5f2bLennart Poettering                            continue;
337a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
3389da0241b9c1bf751605ba11fa6d4c75e34fe5f2bLennart Poettering                        fprintf(stderr, __FILE__": avahi_simple_poll_run() failed: %s\n", strerror(errno));
3399da0241b9c1bf751605ba11fa6d4c75e34fe5f2bLennart Poettering                    }
3409da0241b9c1bf751605ba11fa6d4c75e34fe5f2bLennart Poettering
341941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                    break;
342941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                }
343941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
344941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                ASSERT_SUCCESS(pthread_mutex_unlock(&sdref->mutex));
345786a6a7fa3840d06e64f7429e134ddb06cc1deddLennart Poettering
3469da0241b9c1bf751605ba11fa6d4c75e34fe5f2bLennart Poettering                if (write_command(sdref->thread_fd, ret < 0 ? COMMAND_POLL_FAILED : COMMAND_POLL_DONE) < 0)
347786a6a7fa3840d06e64f7429e134ddb06cc1deddLennart Poettering                    break;
348a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
349941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                break;
3509da0241b9c1bf751605ba11fa6d4c75e34fe5f2bLennart Poettering            }
351941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
352941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            case COMMAND_QUIT:
353941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                return NULL;
354941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        }
355a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
356941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    }
357941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
358941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    return NULL;
359941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering}
360941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
361941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringstatic DNSServiceRef sdref_new(void) {
362941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    int fd[2] = { -1, -1 };
363941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceRef sdref = NULL;
364941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    pthread_mutexattr_t mutex_attr;
365941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
366941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (socketpair(AF_UNIX, SOCK_STREAM, 0, fd) < 0)
367941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        goto fail;
368941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
369941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (!(sdref = avahi_new(struct _DNSServiceRef_t, 1)))
370941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        goto fail;
371941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
372941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->n_ref = 1;
373941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->thread_fd = fd[0];
374941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->main_fd = fd[1];
375941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
376941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->client = NULL;
377941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->service_browser = NULL;
378941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->service_resolver = NULL;
379941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->domain_browser = NULL;
380941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->entry_group = NULL;
381941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
382e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    sdref->service_name = sdref->service_name_chosen = sdref->service_domain = sdref->service_host = NULL;
383941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->service_txt = NULL;
384941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
385e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    type_info_init(&sdref->type_info);
386e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
387941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    ASSERT_SUCCESS(pthread_mutexattr_init(&mutex_attr));
388941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    pthread_mutexattr_settype(&mutex_attr, PTHREAD_MUTEX_RECURSIVE);
38945513c3b363228f92572d853e63085b5db60c166Lennart Poettering    ASSERT_SUCCESS(pthread_mutex_init(&sdref->mutex, &mutex_attr));
390941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
391941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->thread_running = 0;
392941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
393941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (!(sdref->simple_poll = avahi_simple_poll_new()))
394941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        goto fail;
395941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
396941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    avahi_simple_poll_set_func(sdref->simple_poll, poll_func, sdref);
397941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
398941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    /* Start simple poll */
399941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (avahi_simple_poll_prepare(sdref->simple_poll, -1) < 0)
400941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        goto fail;
401941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
402786a6a7fa3840d06e64f7429e134ddb06cc1deddLennart Poettering    /* Queue an initial POLL command for the thread */
403941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (write_command(sdref->main_fd, COMMAND_POLL) < 0)
404941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        goto fail;
405a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
406941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (pthread_create(&sdref->thread, NULL, thread_func, sdref) != 0)
407941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        goto fail;
408941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
409941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->thread_running = 1;
410a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
411941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    return sdref;
412941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
413941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringfail:
414941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
415941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (sdref)
416941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        DNSServiceRefDeallocate(sdref);
417941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
418941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    return NULL;
419941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering}
420941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
421941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringstatic void sdref_free(DNSServiceRef sdref) {
422941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(sdref);
423a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
424941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (sdref->thread_running) {
425786a6a7fa3840d06e64f7429e134ddb06cc1deddLennart Poettering        ASSERT_SUCCESS(write_command(sdref->main_fd, COMMAND_QUIT));
426941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        avahi_simple_poll_wakeup(sdref->simple_poll);
427786a6a7fa3840d06e64f7429e134ddb06cc1deddLennart Poettering        ASSERT_SUCCESS(pthread_join(sdref->thread, NULL));
428941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    }
429941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
430941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (sdref->client)
431941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        avahi_client_free(sdref->client);
432941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
433786a6a7fa3840d06e64f7429e134ddb06cc1deddLennart Poettering    if (sdref->simple_poll)
434786a6a7fa3840d06e64f7429e134ddb06cc1deddLennart Poettering        avahi_simple_poll_free(sdref->simple_poll);
435786a6a7fa3840d06e64f7429e134ddb06cc1deddLennart Poettering
436941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (sdref->thread_fd >= 0)
437941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        close(sdref->thread_fd);
438941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
439941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (sdref->main_fd >= 0)
440941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        close(sdref->main_fd);
441941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
442786a6a7fa3840d06e64f7429e134ddb06cc1deddLennart Poettering    ASSERT_SUCCESS(pthread_mutex_destroy(&sdref->mutex));
443941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
444941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    avahi_free(sdref->service_name);
445941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    avahi_free(sdref->service_name_chosen);
446941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    avahi_free(sdref->service_domain);
447941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    avahi_free(sdref->service_host);
448941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
449e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    type_info_free(&sdref->type_info);
450a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
451941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    avahi_string_list_free(sdref->service_txt);
452a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
453941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    avahi_free(sdref);
454941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering}
455941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
456941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringstatic void sdref_ref(DNSServiceRef sdref) {
457941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(sdref);
458941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(sdref->n_ref >= 1);
459941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
460941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->n_ref++;
461941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering}
462941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
463941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringstatic void sdref_unref(DNSServiceRef sdref) {
464941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(sdref);
465941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(sdref->n_ref >= 1);
466941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
467941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (--(sdref->n_ref) <= 0)
468941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        sdref_free(sdref);
469941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering}
470941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
471941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringint DNSSD_API DNSServiceRefSockFD(DNSServiceRef sdref) {
472941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
473941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AVAHI_WARN_LINKAGE;
474a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
4755b7e4f49787da905b9ec7d01eaf76462ca3a6e28Lennart Poettering    if (!sdref || sdref->n_ref <= 0)
4765b7e4f49787da905b9ec7d01eaf76462ca3a6e28Lennart Poettering        return -1;
4775b7e4f49787da905b9ec7d01eaf76462ca3a6e28Lennart Poettering
478941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    return sdref->main_fd;
479941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering}
480941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
481941853354848fca4cc39bd72e6f34ca54443a9c8Lennart PoetteringDNSServiceErrorType DNSSD_API DNSServiceProcessResult(DNSServiceRef sdref) {
482941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceErrorType ret = kDNSServiceErr_Unknown;
483941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
484941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AVAHI_WARN_LINKAGE;
485941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
4865b7e4f49787da905b9ec7d01eaf76462ca3a6e28Lennart Poettering    if (!sdref || sdref->n_ref <= 0)
4875b7e4f49787da905b9ec7d01eaf76462ca3a6e28Lennart Poettering        return kDNSServiceErr_BadParam;
488a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
4890d0c9486e3fe26fdd67624ee57961ba2d5846ebbLennart Poettering    sdref_ref(sdref);
4905b7e4f49787da905b9ec7d01eaf76462ca3a6e28Lennart Poettering
4915b7e4f49787da905b9ec7d01eaf76462ca3a6e28Lennart Poettering    ASSERT_SUCCESS(pthread_mutex_lock(&sdref->mutex));
492a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
493941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    /* Cleanup notification socket */
49444781dc4d0c3dfdc5d78900d56e93d3450e82f55Lennart Poettering    if (read_command(sdref->main_fd) != COMMAND_POLL_DONE)
495941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        goto finish;
496a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
497941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (avahi_simple_poll_dispatch(sdref->simple_poll) < 0)
498941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        goto finish;
499941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
500941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (sdref->n_ref > 1) /* Perhaps we should die */
501941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
502941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        /* Dispatch events */
503941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        if (avahi_simple_poll_prepare(sdref->simple_poll, -1) < 0)
504941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            goto finish;
505941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
506941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (sdref->n_ref > 1)
507941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
508941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        /* Request the poll */
509941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        if (write_command(sdref->main_fd, COMMAND_POLL) < 0)
510941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            goto finish;
511a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
512941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    ret = kDNSServiceErr_NoError;
513a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
514941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringfinish:
515941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
5160d0c9486e3fe26fdd67624ee57961ba2d5846ebbLennart Poettering    ASSERT_SUCCESS(pthread_mutex_unlock(&sdref->mutex));
517a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
5185b7e4f49787da905b9ec7d01eaf76462ca3a6e28Lennart Poettering    sdref_unref(sdref);
5195b7e4f49787da905b9ec7d01eaf76462ca3a6e28Lennart Poettering
520941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    return ret;
521941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering}
522941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
523941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringvoid DNSSD_API DNSServiceRefDeallocate(DNSServiceRef sdref) {
524941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AVAHI_WARN_LINKAGE;
525941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
526caa787a5490efb94015ae3f26e79983573997a2dLennart Poettering    if (sdref)
527caa787a5490efb94015ae3f26e79983573997a2dLennart Poettering        sdref_unref(sdref);
528941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering}
529941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
530941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringstatic void service_browser_callback(
531941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AvahiServiceBrowser *b,
532941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AvahiIfIndex interface,
533854f901f491ccda79aee11edc3d59109cb229d28Lennart Poettering    AVAHI_GCC_UNUSED AvahiProtocol protocol,
534941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AvahiBrowserEvent event,
535941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    const char *name,
536941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    const char *type,
537941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    const char *domain,
538854f901f491ccda79aee11edc3d59109cb229d28Lennart Poettering    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
539941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    void *userdata) {
540941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
541941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceRef sdref = userdata;
54226ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering    char type_fixed[AVAHI_DOMAIN_NAME_MAX], domain_fixed[AVAHI_DOMAIN_NAME_MAX];
543941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(b);
544941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(sdref);
545941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(sdref->n_ref >= 1);
546941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
54726ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering    type = add_trailing_dot(type, type_fixed, sizeof(type_fixed));
54826ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering    domain  = add_trailing_dot(domain, domain_fixed, sizeof(domain_fixed));
549a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
550941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    switch (event) {
551941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_BROWSER_NEW:
552941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            sdref->service_browser_callback(sdref, kDNSServiceFlagsAdd, interface, kDNSServiceErr_NoError, name, type, domain, sdref->context);
553941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            break;
554941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
555941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_BROWSER_REMOVE:
556941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            sdref->service_browser_callback(sdref, 0, interface, kDNSServiceErr_NoError, name, type, domain, sdref->context);
557941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            break;
558941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
559941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_BROWSER_FAILURE:
560bb14e0a8aa3173c8a6d80b1a9c8b300a452ee9f1Lennart Poettering            sdref->service_browser_callback(sdref, 0, interface, map_error(avahi_client_errno(sdref->client)), NULL, NULL, NULL, sdref->context);
561941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            break;
562a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
563941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_BROWSER_CACHE_EXHAUSTED:
564941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_BROWSER_ALL_FOR_NOW:
565941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            break;
566941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    }
567941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering}
568941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
569941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringstatic void generic_client_callback(AvahiClient *s, AvahiClientState state, void* userdata) {
570941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceRef sdref = userdata;
571f17d2832301b0f2fcd50fdcc6fec77666178158fLennart Poettering    int error = kDNSServiceErr_Unknown;
572a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
573941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(s);
574941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(sdref);
575941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(sdref->n_ref >= 1);
576941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
577941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    switch (state) {
5786f37f0e1126ad3776b80dbd64701f38a58738921Lennart Poettering
5796f37f0e1126ad3776b80dbd64701f38a58738921Lennart Poettering        case AVAHI_CLIENT_FAILURE:
580941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
581941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            if (sdref->service_browser_callback)
582f17d2832301b0f2fcd50fdcc6fec77666178158fLennart Poettering                sdref->service_browser_callback(sdref, 0, 0, error, NULL, NULL, NULL, sdref->context);
583941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            else if (sdref->service_resolver_callback)
584f17d2832301b0f2fcd50fdcc6fec77666178158fLennart Poettering                sdref->service_resolver_callback(sdref, 0, 0, error, NULL, NULL, 0, 0, NULL, sdref->context);
585941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            else if (sdref->domain_browser_callback)
586f17d2832301b0f2fcd50fdcc6fec77666178158fLennart Poettering                sdref->domain_browser_callback(sdref, 0, 0, error, NULL, sdref->context);
587e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering            else if (sdref->query_resolver_callback)
588e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering                sdref->query_resolver_callback(sdref, 0, 0, error, NULL, 0, 0, 0, NULL, 0, sdref->context);
589941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
590941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            break;
591941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
592941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_CLIENT_S_RUNNING:
593941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_CLIENT_S_COLLISION:
594941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_CLIENT_S_REGISTERING:
5956ecd227ceadc32ed229246aa61df6361c7b58a95Lennart Poettering        case AVAHI_CLIENT_CONNECTING:
596941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            break;
597941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    }
598941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering}
599941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
600941853354848fca4cc39bd72e6f34ca54443a9c8Lennart PoetteringDNSServiceErrorType DNSSD_API DNSServiceBrowse(
601e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        DNSServiceRef *ret_sdref,
602e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        DNSServiceFlags flags,
603e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        uint32_t interface,
604e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        const char *regtype,
605e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        const char *domain,
606e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        DNSServiceBrowseReply callback,
607e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        void *context) {
608941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
609941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceErrorType ret = kDNSServiceErr_Unknown;
610941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    int error;
611941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceRef sdref = NULL;
612941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AvahiIfIndex ifindex;
613e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    struct type_info type_info;
614a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
615941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AVAHI_WARN_LINKAGE;
616c9109b4b6f4eca16ad867d91bd6683ac6355be76Trent Lloyd
617511bbee5e4da8e71b5da8521a162941398ebfdbaLennart Poettering    if (!ret_sdref || !regtype)
618c9109b4b6f4eca16ad867d91bd6683ac6355be76Trent Lloyd        return kDNSServiceErr_BadParam;
619c9109b4b6f4eca16ad867d91bd6683ac6355be76Trent Lloyd    *ret_sdref = NULL;
620c9109b4b6f4eca16ad867d91bd6683ac6355be76Trent Lloyd
6211c22aa6ce3490c7f5447179b4ec2e6113881660eLennart Poettering    if (interface == kDNSServiceInterfaceIndexLocalOnly || flags != 0) {
6221c22aa6ce3490c7f5447179b4ec2e6113881660eLennart Poettering        AVAHI_WARN_UNSUPPORTED;
623941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        return kDNSServiceErr_Unsupported;
6241c22aa6ce3490c7f5447179b4ec2e6113881660eLennart Poettering    }
625941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
626e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    type_info_init(&type_info);
627a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
628e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    if (type_info_parse(&type_info, regtype) < 0 || type_info.n_subtypes > 1) {
629e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        type_info_free(&type_info);
630e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
631e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        if (!avahi_is_valid_service_type_generic(regtype))
632e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering            return kDNSServiceErr_Unsupported;
633e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    } else
634e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        regtype = type_info.subtypes ? (char*) type_info.subtypes->text : type_info.type;
635a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
636e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    if (!(sdref = sdref_new())) {
637e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        type_info_free(&type_info);
638941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        return kDNSServiceErr_Unknown;
639e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    }
640941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
641941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->context = context;
642941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->service_browser_callback = callback;
643941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
644941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    ASSERT_SUCCESS(pthread_mutex_lock(&sdref->mutex));
645a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
6466ecd227ceadc32ed229246aa61df6361c7b58a95Lennart Poettering    if (!(sdref->client = avahi_client_new(avahi_simple_poll_get(sdref->simple_poll), 0, generic_client_callback, sdref, &error))) {
647941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        ret =  map_error(error);
648941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        goto finish;
649941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    }
650941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
651941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    ifindex = interface == kDNSServiceInterfaceIndexAny ? AVAHI_IF_UNSPEC : (AvahiIfIndex) interface;
652a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
653941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (!(sdref->service_browser = avahi_service_browser_new(sdref->client, ifindex, AVAHI_PROTO_UNSPEC, regtype, domain, 0, service_browser_callback, sdref))) {
654941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        ret = map_error(avahi_client_errno(sdref->client));
655941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        goto finish;
656941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    }
657a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
658941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    ret = kDNSServiceErr_NoError;
659941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    *ret_sdref = sdref;
660a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
661941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringfinish:
662941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
663941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    ASSERT_SUCCESS(pthread_mutex_unlock(&sdref->mutex));
664a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
665941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (ret != kDNSServiceErr_NoError)
666941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        DNSServiceRefDeallocate(sdref);
667941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
668e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    type_info_free(&type_info);
669e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
670941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    return ret;
671c8879d3cf7f23325346e1bd601924c6b1e0a21d1Lennart Poettering}
672941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
673941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringstatic void service_resolver_callback(
674941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AvahiServiceResolver *r,
675941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AvahiIfIndex interface,
676854f901f491ccda79aee11edc3d59109cb229d28Lennart Poettering    AVAHI_GCC_UNUSED AvahiProtocol protocol,
677941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AvahiResolverEvent event,
678941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    const char *name,
679941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    const char *type,
680941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    const char *domain,
681941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    const char *host_name,
682854f901f491ccda79aee11edc3d59109cb229d28Lennart Poettering    AVAHI_GCC_UNUSED const AvahiAddress *a,
683941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    uint16_t port,
684941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AvahiStringList *txt,
685854f901f491ccda79aee11edc3d59109cb229d28Lennart Poettering    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
686941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    void *userdata) {
687941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
688941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceRef sdref = userdata;
689941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
690941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(r);
691941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(sdref);
692941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(sdref->n_ref >= 1);
693941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
694941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    switch (event) {
695941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_RESOLVER_FOUND: {
696941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
69745513c3b363228f92572d853e63085b5db60c166Lennart Poettering            char host_name_fixed[AVAHI_DOMAIN_NAME_MAX];
69826ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering            char full_name[AVAHI_DOMAIN_NAME_MAX];
699941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            int ret;
700941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            char *p = NULL;
701941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            size_t l = 0;
702941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
70345513c3b363228f92572d853e63085b5db60c166Lennart Poettering            host_name = add_trailing_dot(host_name, host_name_fixed, sizeof(host_name_fixed));
70445513c3b363228f92572d853e63085b5db60c166Lennart Poettering
705941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            if ((p = avahi_new0(char, (l = avahi_string_list_serialize(txt, NULL, 0))+1)))
706941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                avahi_string_list_serialize(txt, p, l);
707941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
708d1dd07145bb3db5c6fd77c55aea762eb79ab3b5cLennart Poettering            ret = avahi_service_name_join(full_name, sizeof(full_name), name, type, domain);
709941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            assert(ret == AVAHI_OK);
71026ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering
71126ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering            strcat(full_name, ".");
712a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
71382aabd487bd00b79147ee23f4f76d692fdd0ced3Lennart Poettering            sdref->service_resolver_callback(sdref, 0, interface, kDNSServiceErr_NoError, full_name, host_name, htons(port), l, (unsigned char*) p, sdref->context);
714941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
715941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            avahi_free(p);
716941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            break;
717941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        }
718941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
719941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_RESOLVER_FAILURE:
720bb14e0a8aa3173c8a6d80b1a9c8b300a452ee9f1Lennart Poettering            sdref->service_resolver_callback(sdref, 0, interface, map_error(avahi_client_errno(sdref->client)), NULL, NULL, 0, 0, NULL, sdref->context);
72145513c3b363228f92572d853e63085b5db60c166Lennart Poettering            break;
722941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    }
723941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering}
724941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
725941853354848fca4cc39bd72e6f34ca54443a9c8Lennart PoetteringDNSServiceErrorType DNSSD_API DNSServiceResolve(
726941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceRef *ret_sdref,
727941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceFlags flags,
728941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    uint32_t interface,
729941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    const char *name,
730941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    const char *regtype,
731941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    const char *domain,
732941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceResolveReply callback,
733941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    void *context) {
734941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
735941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceErrorType ret = kDNSServiceErr_Unknown;
736941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    int error;
737941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceRef sdref = NULL;
738941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AvahiIfIndex ifindex;
739941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
740941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AVAHI_WARN_LINKAGE;
741941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
742511bbee5e4da8e71b5da8521a162941398ebfdbaLennart Poettering    if (!ret_sdref || !name || !regtype || !domain || !callback)
7435b7e4f49787da905b9ec7d01eaf76462ca3a6e28Lennart Poettering        return kDNSServiceErr_BadParam;
7445b7e4f49787da905b9ec7d01eaf76462ca3a6e28Lennart Poettering    *ret_sdref = NULL;
7455b7e4f49787da905b9ec7d01eaf76462ca3a6e28Lennart Poettering
7461c22aa6ce3490c7f5447179b4ec2e6113881660eLennart Poettering    if (interface == kDNSServiceInterfaceIndexLocalOnly || flags != 0) {
7471c22aa6ce3490c7f5447179b4ec2e6113881660eLennart Poettering        AVAHI_WARN_UNSUPPORTED;
748941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        return kDNSServiceErr_Unsupported;
7491c22aa6ce3490c7f5447179b4ec2e6113881660eLennart Poettering    }
750941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
751941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (!(sdref = sdref_new()))
752941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        return kDNSServiceErr_Unknown;
753941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
754941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->context = context;
755941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->service_resolver_callback = callback;
756941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
757941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    ASSERT_SUCCESS(pthread_mutex_lock(&sdref->mutex));
758a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
7596ecd227ceadc32ed229246aa61df6361c7b58a95Lennart Poettering    if (!(sdref->client = avahi_client_new(avahi_simple_poll_get(sdref->simple_poll), 0, generic_client_callback, sdref, &error))) {
760941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        ret =  map_error(error);
761941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        goto finish;
762941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    }
763941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
764941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    ifindex = interface == kDNSServiceInterfaceIndexAny ? AVAHI_IF_UNSPEC : (AvahiIfIndex) interface;
765a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
766941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (!(sdref->service_resolver = avahi_service_resolver_new(sdref->client, ifindex, AVAHI_PROTO_UNSPEC, name, regtype, domain, AVAHI_PROTO_UNSPEC, 0, service_resolver_callback, sdref))) {
767941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        ret = map_error(avahi_client_errno(sdref->client));
768941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        goto finish;
769941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    }
770a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
771941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
772941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    ret = kDNSServiceErr_NoError;
773941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    *ret_sdref = sdref;
774a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
775941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringfinish:
776941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
777941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    ASSERT_SUCCESS(pthread_mutex_unlock(&sdref->mutex));
778a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
779941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (ret != kDNSServiceErr_NoError)
780941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        DNSServiceRefDeallocate(sdref);
781941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
782941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    return ret;
783941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering}
784941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
785941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringint DNSSD_API DNSServiceConstructFullName (
786941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    char *fullName,
787a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering    const char *service,
788941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    const char *regtype,
789941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    const char *domain) {
790941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
791941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AVAHI_WARN_LINKAGE;
792941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
793511bbee5e4da8e71b5da8521a162941398ebfdbaLennart Poettering    if (!fullName || !regtype || !domain)
794511bbee5e4da8e71b5da8521a162941398ebfdbaLennart Poettering        return -1;
795941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
796d1dd07145bb3db5c6fd77c55aea762eb79ab3b5cLennart Poettering    if (avahi_service_name_join(fullName, kDNSServiceMaxDomainName, service, regtype, domain) < 0)
797941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        return -1;
798a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
799941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    return 0;
800941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering}
801941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
802941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringstatic void domain_browser_callback(
803941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AvahiDomainBrowser *b,
804941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AvahiIfIndex interface,
805854f901f491ccda79aee11edc3d59109cb229d28Lennart Poettering    AVAHI_GCC_UNUSED AvahiProtocol protocol,
806941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AvahiBrowserEvent event,
807941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    const char *domain,
808854f901f491ccda79aee11edc3d59109cb229d28Lennart Poettering    AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
809941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    void *userdata) {
810941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
811941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceRef sdref = userdata;
81226ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering    static char domain_fixed[AVAHI_DOMAIN_NAME_MAX];
813941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
814941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(b);
815941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(sdref);
816941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(sdref->n_ref >= 1);
817941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
81826ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering    domain  = add_trailing_dot(domain, domain_fixed, sizeof(domain_fixed));
81926ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering
820941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    switch (event) {
821941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_BROWSER_NEW:
822941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            sdref->domain_browser_callback(sdref, kDNSServiceFlagsAdd, interface, kDNSServiceErr_NoError, domain, sdref->context);
823941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            break;
824941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
825941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_BROWSER_REMOVE:
826941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            sdref->domain_browser_callback(sdref, 0, interface, kDNSServiceErr_NoError, domain, sdref->context);
827941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            break;
828941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
829941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_BROWSER_FAILURE:
830bb14e0a8aa3173c8a6d80b1a9c8b300a452ee9f1Lennart Poettering            sdref->domain_browser_callback(sdref, 0, interface, map_error(avahi_client_errno(sdref->client)), domain, sdref->context);
831941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            break;
832a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
833941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_BROWSER_CACHE_EXHAUSTED:
834941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_BROWSER_ALL_FOR_NOW:
835941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            break;
836941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    }
837941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering}
838941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
839941853354848fca4cc39bd72e6f34ca54443a9c8Lennart PoetteringDNSServiceErrorType DNSSD_API DNSServiceEnumerateDomains(
840941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceRef *ret_sdref,
841941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceFlags flags,
842941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    uint32_t interface,
843941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceDomainEnumReply callback,
844941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    void *context) {
845941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
846941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceErrorType ret = kDNSServiceErr_Unknown;
847941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    int error;
848941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceRef sdref = NULL;
849941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AvahiIfIndex ifindex;
850941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
851941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AVAHI_WARN_LINKAGE;
852941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
853511bbee5e4da8e71b5da8521a162941398ebfdbaLennart Poettering    if (!ret_sdref || !callback)
8545b7e4f49787da905b9ec7d01eaf76462ca3a6e28Lennart Poettering        return kDNSServiceErr_BadParam;
8555b7e4f49787da905b9ec7d01eaf76462ca3a6e28Lennart Poettering    *ret_sdref = NULL;
8565b7e4f49787da905b9ec7d01eaf76462ca3a6e28Lennart Poettering
857941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (interface == kDNSServiceInterfaceIndexLocalOnly ||
8581c22aa6ce3490c7f5447179b4ec2e6113881660eLennart Poettering        (flags != kDNSServiceFlagsBrowseDomains &&  flags != kDNSServiceFlagsRegistrationDomains)) {
8591c22aa6ce3490c7f5447179b4ec2e6113881660eLennart Poettering        AVAHI_WARN_UNSUPPORTED;
860941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        return kDNSServiceErr_Unsupported;
8611c22aa6ce3490c7f5447179b4ec2e6113881660eLennart Poettering    }
862941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
863941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (!(sdref = sdref_new()))
864941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        return kDNSServiceErr_Unknown;
865941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
866941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->context = context;
867941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->domain_browser_callback = callback;
868941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
869941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    ASSERT_SUCCESS(pthread_mutex_lock(&sdref->mutex));
870a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
8716ecd227ceadc32ed229246aa61df6361c7b58a95Lennart Poettering    if (!(sdref->client = avahi_client_new(avahi_simple_poll_get(sdref->simple_poll), 0, generic_client_callback, sdref, &error))) {
872941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        ret =  map_error(error);
873941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        goto finish;
874941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    }
875941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
876941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    ifindex = interface == kDNSServiceInterfaceIndexAny ? AVAHI_IF_UNSPEC : (AvahiIfIndex) interface;
877a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
878cc10c2a6a4a29d65a72fb33b7cf6206e5f04be30Lennart Poettering    if (!(sdref->domain_browser = avahi_domain_browser_new(sdref->client, ifindex, AVAHI_PROTO_UNSPEC, "local",
879941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                                                           flags == kDNSServiceFlagsRegistrationDomains ? AVAHI_DOMAIN_BROWSER_REGISTER : AVAHI_DOMAIN_BROWSER_BROWSE,
880941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                                                           0, domain_browser_callback, sdref))) {
881941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        ret = map_error(avahi_client_errno(sdref->client));
882941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        goto finish;
883941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    }
884a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
885941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    ret = kDNSServiceErr_NoError;
886941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    *ret_sdref = sdref;
887a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
888941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringfinish:
889941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
890941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    ASSERT_SUCCESS(pthread_mutex_unlock(&sdref->mutex));
891a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
892941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (ret != kDNSServiceErr_NoError)
893941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        DNSServiceRefDeallocate(sdref);
894941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
895941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    return ret;
896941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering}
897941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
898941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringstatic void reg_report_error(DNSServiceRef sdref, DNSServiceErrorType error) {
89926ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering    char regtype_fixed[AVAHI_DOMAIN_NAME_MAX], domain_fixed[AVAHI_DOMAIN_NAME_MAX];
90026ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering    const char *regtype, *domain;
901941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(sdref);
902941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(sdref->n_ref >= 1);
903941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
904d4fd0d73b1d646f3708f1fdcbca0d494dda7e475Lennart Poettering    if (!sdref->service_register_callback)
905d4fd0d73b1d646f3708f1fdcbca0d494dda7e475Lennart Poettering        return;
906941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
907e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    regtype = add_trailing_dot(sdref->type_info.type, regtype_fixed, sizeof(regtype_fixed));
90826ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering    domain = add_trailing_dot(sdref->service_domain, domain_fixed, sizeof(domain_fixed));
909a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
910941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->service_register_callback(
911941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        sdref, 0, error,
912941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        sdref->service_name_chosen ? sdref->service_name_chosen : sdref->service_name,
91326ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering        regtype,
91426ff12dc7f06b0031050938d297e6ef94931e8bfLennart Poettering        domain,
915941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        sdref->context);
916941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering}
917941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
918941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringstatic int reg_create_service(DNSServiceRef sdref) {
919941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    int ret;
920e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    AvahiStringList *l;
921a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
922941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(sdref);
923941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(sdref->n_ref >= 1);
924941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
925941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if ((ret = avahi_entry_group_add_service_strlst(
926941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        sdref->entry_group,
927941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        sdref->service_interface,
928941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        AVAHI_PROTO_UNSPEC,
929941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        0,
930941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        sdref->service_name_chosen,
931e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        sdref->type_info.type,
932941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        sdref->service_domain,
933941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        sdref->service_host,
934941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        sdref->service_port,
935941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        sdref->service_txt)) < 0)
936941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        return ret;
937941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
938e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    for (l = sdref->type_info.subtypes; l; l = l->next) {
9391adbc218354388dd59c68267c363d2fbcc75eaadLennart Poettering        /* Create a subtype entry */
9401adbc218354388dd59c68267c363d2fbcc75eaadLennart Poettering
9411adbc218354388dd59c68267c363d2fbcc75eaadLennart Poettering        if (avahi_entry_group_add_service_subtype(
9421adbc218354388dd59c68267c363d2fbcc75eaadLennart Poettering                sdref->entry_group,
9431adbc218354388dd59c68267c363d2fbcc75eaadLennart Poettering                sdref->service_interface,
9441adbc218354388dd59c68267c363d2fbcc75eaadLennart Poettering                AVAHI_PROTO_UNSPEC,
9451adbc218354388dd59c68267c363d2fbcc75eaadLennart Poettering                0,
9461adbc218354388dd59c68267c363d2fbcc75eaadLennart Poettering                sdref->service_name_chosen,
947e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering                sdref->type_info.type,
9481adbc218354388dd59c68267c363d2fbcc75eaadLennart Poettering                sdref->service_domain,
949e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering                (const char*) l->text) < 0)
9501adbc218354388dd59c68267c363d2fbcc75eaadLennart Poettering            return ret;
9511adbc218354388dd59c68267c363d2fbcc75eaadLennart Poettering    }
9521adbc218354388dd59c68267c363d2fbcc75eaadLennart Poettering
953941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if ((ret = avahi_entry_group_commit(sdref->entry_group)) < 0)
954941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        return ret;
955941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
956941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    return 0;
957941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering}
958941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
959941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringstatic void reg_client_callback(AvahiClient *s, AvahiClientState state, void* userdata) {
960941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceRef sdref = userdata;
961941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
962941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(s);
963941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(sdref);
964941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(sdref->n_ref >= 1);
965941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
966941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    /* We've not been setup completely */
967941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (!sdref->entry_group)
968941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        return;
969a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
970941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    switch (state) {
9716f37f0e1126ad3776b80dbd64701f38a58738921Lennart Poettering        case AVAHI_CLIENT_FAILURE:
972f17d2832301b0f2fcd50fdcc6fec77666178158fLennart Poettering            reg_report_error(sdref, kDNSServiceErr_Unknown);
973f17d2832301b0f2fcd50fdcc6fec77666178158fLennart Poettering            break;
974941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
975941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_CLIENT_S_RUNNING: {
976941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            int ret;
977941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
978941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            if (!sdref->service_name) {
979941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                const char *n;
980941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                /* If the service name is taken from the host name, copy that */
981941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
982941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                avahi_free(sdref->service_name_chosen);
983fee238b3a20c8fbb34af6b08995df2265131bee6Lennart Poettering                sdref->service_name_chosen = NULL;
984941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
985941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                if (!(n = avahi_client_get_host_name(sdref->client))) {
986941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                    reg_report_error(sdref, map_error(avahi_client_errno(sdref->client)));
987941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                    return;
988941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                }
989941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
990941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                if (!(sdref->service_name_chosen = avahi_strdup(n))) {
991941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                    reg_report_error(sdref, kDNSServiceErr_NoMemory);
992941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                    return;
993941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                }
994941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            }
995373dc531148992c6a5cf57b2fae29286afd70488Lennart Poettering
996373dc531148992c6a5cf57b2fae29286afd70488Lennart Poettering            if (!sdref->service_name_chosen) {
997373dc531148992c6a5cf57b2fae29286afd70488Lennart Poettering
998373dc531148992c6a5cf57b2fae29286afd70488Lennart Poettering                assert(sdref->service_name);
999a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1000373dc531148992c6a5cf57b2fae29286afd70488Lennart Poettering                if (!(sdref->service_name_chosen = avahi_strdup(sdref->service_name))) {
1001373dc531148992c6a5cf57b2fae29286afd70488Lennart Poettering                    reg_report_error(sdref, kDNSServiceErr_NoMemory);
1002373dc531148992c6a5cf57b2fae29286afd70488Lennart Poettering                    return;
1003373dc531148992c6a5cf57b2fae29286afd70488Lennart Poettering                }
1004373dc531148992c6a5cf57b2fae29286afd70488Lennart Poettering            }
1005a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1006941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            /* Register the service */
1007941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1008941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            if ((ret = reg_create_service(sdref)) < 0) {
1009941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                reg_report_error(sdref, map_error(ret));
1010941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                return;
1011941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            }
1012a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1013941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            break;
1014941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        }
1015a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1016941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_CLIENT_S_COLLISION:
1017c1e5b725e8e769c8ac1f5df97aac53896b05af43Lennart Poettering        case AVAHI_CLIENT_S_REGISTERING:
1018941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1019941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            /* Remove our entry */
1020941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            avahi_entry_group_reset(sdref->entry_group);
1021a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1022941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            break;
1023941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
10246ecd227ceadc32ed229246aa61df6361c7b58a95Lennart Poettering        case AVAHI_CLIENT_CONNECTING:
1025941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            /* Ignore */
1026941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            break;
1027941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    }
1028941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1029941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering}
1030941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1031941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringstatic void reg_entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata) {
1032941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceRef sdref = userdata;
1033941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1034941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    assert(g);
1035941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1036941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    switch (state) {
1037941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ENTRY_GROUP_ESTABLISHED:
1038fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering
1039941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            /* Inform the user */
1040941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            reg_report_error(sdref, kDNSServiceErr_NoError);
1041941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1042941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            break;
1043941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1044941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ENTRY_GROUP_COLLISION: {
1045941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            char *n;
1046941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            int ret;
1047a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1048941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            /* Remove our entry */
1049941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            avahi_entry_group_reset(sdref->entry_group);
1050941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1051941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            assert(sdref->service_name_chosen);
1052941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1053941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            /* Pick a new name */
1054941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            if (!(n = avahi_alternative_service_name(sdref->service_name_chosen))) {
1055941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                reg_report_error(sdref, kDNSServiceErr_NoMemory);
1056941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                return;
1057941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            }
1058941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            avahi_free(sdref->service_name_chosen);
1059941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            sdref->service_name_chosen = n;
1060941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1061941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            /* Register the service with that new name */
1062941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            if ((ret = reg_create_service(sdref)) < 0) {
1063941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                reg_report_error(sdref, map_error(ret));
1064941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                return;
1065941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            }
1066a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1067941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            break;
1068941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        }
1069941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1070941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ENTRY_GROUP_REGISTERING:
1071941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        case AVAHI_ENTRY_GROUP_UNCOMMITED:
1072941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            /* Ignore */
1073941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            break;
1074f17d2832301b0f2fcd50fdcc6fec77666178158fLennart Poettering
1075f17d2832301b0f2fcd50fdcc6fec77666178158fLennart Poettering        case AVAHI_ENTRY_GROUP_FAILURE:
1076f17d2832301b0f2fcd50fdcc6fec77666178158fLennart Poettering            /* Inform the user */
1077f17d2832301b0f2fcd50fdcc6fec77666178158fLennart Poettering            reg_report_error(sdref, map_error(avahi_client_errno(sdref->client)));
1078f17d2832301b0f2fcd50fdcc6fec77666178158fLennart Poettering            break;
1079a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1080941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    }
1081941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering}
1082941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1083941853354848fca4cc39bd72e6f34ca54443a9c8Lennart PoetteringDNSServiceErrorType DNSSD_API DNSServiceRegister (
1084e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        DNSServiceRef *ret_sdref,
1085e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        DNSServiceFlags flags,
1086e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        uint32_t interface,
1087a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering        const char *name,
1088e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        const char *regtype,
1089a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering        const char *domain,
1090a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering        const char *host,
1091e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        uint16_t port,
1092e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        uint16_t txtLen,
1093a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering        const void *txtRecord,
1094a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering        DNSServiceRegisterReply callback,
1095e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        void *context) {
1096941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1097941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceErrorType ret = kDNSServiceErr_Unknown;
1098941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    int error;
1099941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    DNSServiceRef sdref = NULL;
110020011324500a728851e4888c890a756ecf71394bLennart Poettering    AvahiStringList *txt = NULL;
1101e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    struct type_info type_info;
1102941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1103941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    AVAHI_WARN_LINKAGE;
1104941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1105511bbee5e4da8e71b5da8521a162941398ebfdbaLennart Poettering    if (!ret_sdref || !regtype)
1106c9109b4b6f4eca16ad867d91bd6683ac6355be76Trent Lloyd        return kDNSServiceErr_BadParam;
1107c9109b4b6f4eca16ad867d91bd6683ac6355be76Trent Lloyd    *ret_sdref = NULL;
1108a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1109511bbee5e4da8e71b5da8521a162941398ebfdbaLennart Poettering    if (!txtRecord) {
1110511bbee5e4da8e71b5da8521a162941398ebfdbaLennart Poettering        txtLen = 1;
1111511bbee5e4da8e71b5da8521a162941398ebfdbaLennart Poettering        txtRecord = "";
1112511bbee5e4da8e71b5da8521a162941398ebfdbaLennart Poettering    }
1113941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
11141c22aa6ce3490c7f5447179b4ec2e6113881660eLennart Poettering    if (interface == kDNSServiceInterfaceIndexLocalOnly || flags) {
11151c22aa6ce3490c7f5447179b4ec2e6113881660eLennart Poettering        AVAHI_WARN_UNSUPPORTED;
1116941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        return kDNSServiceErr_Unsupported;
11171c22aa6ce3490c7f5447179b4ec2e6113881660eLennart Poettering    }
1118941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1119a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering    if (txtLen > 0)
112020011324500a728851e4888c890a756ecf71394bLennart Poettering        if (avahi_string_list_parse(txtRecord, txtLen, &txt) < 0)
112120011324500a728851e4888c890a756ecf71394bLennart Poettering            return kDNSServiceErr_Invalid;
1122e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering
1123e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    if (type_info_parse(&type_info, regtype) < 0) {
1124e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        avahi_string_list_free(txt);
1125e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        return kDNSServiceErr_Invalid;
1126e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    }
1127a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
112820011324500a728851e4888c890a756ecf71394bLennart Poettering    if (!(sdref = sdref_new())) {
112920011324500a728851e4888c890a756ecf71394bLennart Poettering        avahi_string_list_free(txt);
1130e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering        type_info_free(&type_info);
1131941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        return kDNSServiceErr_Unknown;
113220011324500a728851e4888c890a756ecf71394bLennart Poettering    }
1133941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1134941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->context = context;
1135941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->service_register_callback = callback;
1136941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1137e521a9a2fad8314d5e7d5bbde47b2c852a1426a7Lennart Poettering    sdref->type_info = type_info;
1138941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->service_name = avahi_strdup(name);
1139d1dd07145bb3db5c6fd77c55aea762eb79ab3b5cLennart Poettering    sdref->service_domain = domain ? avahi_normalize_name_strdup(domain) : NULL;
1140d1dd07145bb3db5c6fd77c55aea762eb79ab3b5cLennart Poettering    sdref->service_host = host ? avahi_normalize_name_strdup(host) : NULL;
1141941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->service_interface = interface == kDNSServiceInterfaceIndexAny ? AVAHI_IF_UNSPEC : (AvahiIfIndex) interface;
1142941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    sdref->service_port = ntohs(port);
114320011324500a728851e4888c890a756ecf71394bLennart Poettering    sdref->service_txt = txt;
1144fee238b3a20c8fbb34af6b08995df2265131bee6Lennart Poettering
1145fee238b3a20c8fbb34af6b08995df2265131bee6Lennart Poettering    /* Some OOM checking would be cool here */
1146a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1147941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    ASSERT_SUCCESS(pthread_mutex_lock(&sdref->mutex));
1148a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
11496ecd227ceadc32ed229246aa61df6361c7b58a95Lennart Poettering    if (!(sdref->client = avahi_client_new(avahi_simple_poll_get(sdref->simple_poll), 0, reg_client_callback, sdref, &error))) {
1150941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        ret =  map_error(error);
1151941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        goto finish;
1152941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    }
1153941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1154941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (!sdref->service_domain) {
1155941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        const char *d;
1156941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1157941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        if (!(d = avahi_client_get_domain_name(sdref->client))) {
1158941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            ret = map_error(avahi_client_errno(sdref->client));
1159941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            goto finish;
1160941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        }
1161941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1162941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        if (!(sdref->service_domain = avahi_strdup(d))) {
1163941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            ret = kDNSServiceErr_NoMemory;
1164941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            goto finish;
1165941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        }
1166941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    }
1167941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1168941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (!(sdref->entry_group = avahi_entry_group_new(sdref->client, reg_entry_group_callback, sdref))) {
1169941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        ret = map_error(avahi_client_errno(sdref->client));
1170941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        goto finish;
1171941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    }
1172941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1173941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (avahi_client_get_state(sdref->client) == AVAHI_CLIENT_S_RUNNING) {
1174941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        const char *n;
1175941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1176941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        if (sdref->service_name)
1177941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            n = sdref->service_name;
1178941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        else {
1179941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            if (!(n = avahi_client_get_host_name(sdref->client))) {
1180941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                ret = map_error(avahi_client_errno(sdref->client));
1181941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering                goto finish;
1182941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            }
1183941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        }
1184941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1185941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        if (!(sdref->service_name_chosen = avahi_strdup(n))) {
1186941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            ret = kDNSServiceErr_NoMemory;
1187941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            goto finish;
1188941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        }
1189941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1190a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1191941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        if ((error = reg_create_service(sdref)) < 0) {
1192941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            ret = map_error(error);
1193941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering            goto finish;
1194941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        }
1195941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    }
1196a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1197941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    ret = kDNSServiceErr_NoError;
1198941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    *ret_sdref = sdref;
1199a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1200941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poetteringfinish:
1201941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1202941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    ASSERT_SUCCESS(pthread_mutex_unlock(&sdref->mutex));
1203a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1204941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    if (ret != kDNSServiceErr_NoError)
1205941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering        DNSServiceRefDeallocate(sdref);
1206941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1207941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering    return ret;
1208941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering}
1209941853354848fca4cc39bd72e6f34ca54443a9c8Lennart Poettering
1210fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart PoetteringDNSServiceErrorType DNSSD_API DNSServiceUpdateRecord(
1211fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering         DNSServiceRef sdref,
1212a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering         DNSRecordRef rref,
1213fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering         DNSServiceFlags flags,
1214fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering         uint16_t rdlen,
1215fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering         const void *rdata,
1216fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering         AVAHI_GCC_UNUSED uint32_t ttl) {
1217fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering
1218fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering    int ret = kDNSServiceErr_Unknown;
1219fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering    AvahiStringList *txt = NULL;
1220fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering
1221fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering    AVAHI_WARN_LINKAGE;
1222fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering
12235b7e4f49787da905b9ec7d01eaf76462ca3a6e28Lennart Poettering    if (!sdref || sdref->n_ref <= 0)
12245b7e4f49787da905b9ec7d01eaf76462ca3a6e28Lennart Poettering        return kDNSServiceErr_BadParam;
12255b7e4f49787da905b9ec7d01eaf76462ca3a6e28Lennart Poettering
1226fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering    if (flags || rref) {
1227fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering        AVAHI_WARN_UNSUPPORTED;
1228fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering        return kDNSServiceErr_Unsupported;
1229fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering    }
1230fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering
1231a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering    if (rdlen > 0)
1232fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering        if (avahi_string_list_parse(rdata, rdlen, &txt) < 0)
1233fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering            return kDNSServiceErr_Invalid;
1234fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering
1235fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering    ASSERT_SUCCESS(pthread_mutex_lock(&sdref->mutex));
1236fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering
1237fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering    if (!avahi_string_list_equal(txt, sdref->service_txt)) {
1238fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering
1239fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering        avahi_string_list_free(sdref->service_txt);
1240fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering        sdref->service_txt = txt;
1241fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering
1242fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering        if (avahi_client_get_state(sdref->client) == AVAHI_CLIENT_S_RUNNING &&
1243fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering            sdref->entry_group &&
1244fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering            (avahi_entry_group_get_state(sdref->entry_group) == AVAHI_ENTRY_GROUP_ESTABLISHED ||
1245fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering            avahi_entry_group_get_state(sdref->entry_group) == AVAHI_ENTRY_GROUP_REGISTERING))
1246fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering
1247fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering            if (avahi_entry_group_update_service_txt_strlst(
1248fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering                        sdref->entry_group,
1249fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering                        sdref->service_interface,
1250fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering                        AVAHI_PROTO_UNSPEC,
1251fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering                        0,
1252fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering                        sdref->service_name_chosen,
1253fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering                        sdref->type_info.type,
1254fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering                        sdref->service_domain,
1255fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering                        sdref->service_txt) < 0) {
1256a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1257fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering                ret = map_error(avahi_client_errno(sdref->client));
1258fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering                goto finish;
1259fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering            }
1260fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering
1261fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering    } else
1262fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering        avahi_string_list_free(txt);
1263fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering
1264fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering    ret = kDNSServiceErr_NoError;
1265a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1266fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poetteringfinish:
1267fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering    ASSERT_SUCCESS(pthread_mutex_unlock(&sdref->mutex));
1268a97605e07ad7f44f2f65e15be64880e61a39ab43Lennart Poettering
1269fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering    return ret;
1270fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering}
1271fc3830c24fd0341d762a2c4f05198f27fc3ccac0Lennart Poettering
1272e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poetteringstatic void query_resolver_callback(
1273e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        AvahiRecordBrowser *r,
1274e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        AvahiIfIndex interface,
1275e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        AVAHI_GCC_UNUSED AvahiProtocol protocol,
1276e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        AvahiBrowserEvent event,
1277e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        const char *name,
1278e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        uint16_t clazz,
1279e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        uint16_t type,
1280e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        const void* rdata,
1281e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        size_t size,
1282e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
1283e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        void *userdata) {
1284e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering
1285e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    DNSServiceRef sdref = userdata;
1286e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering
1287e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    assert(r);
1288e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    assert(sdref);
1289e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    assert(sdref->n_ref >= 1);
1290e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering
1291e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    switch (event) {
1292e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering
1293e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    case AVAHI_BROWSER_NEW:
1294e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    case AVAHI_BROWSER_REMOVE: {
1295e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering
1296e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        DNSServiceFlags qflags = 0;
1297e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        if (event == AVAHI_BROWSER_NEW)
1298e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering            qflags |= kDNSServiceFlagsAdd;
1299e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering
1300e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        sdref->query_resolver_callback(sdref, qflags, interface, kDNSServiceErr_NoError, name, type, clazz, size, rdata, 0, sdref->context);
1301e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        break;
1302e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    }
1303e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering
1304e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    case AVAHI_BROWSER_ALL_FOR_NOW:
1305e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    case AVAHI_BROWSER_CACHE_EXHAUSTED:
1306e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        /* not implemented */
1307e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        break;
1308e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering
1309e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    case AVAHI_BROWSER_FAILURE:
1310e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        sdref->query_resolver_callback(sdref, 0, interface, map_error(avahi_client_errno(sdref->client)), NULL, 0, 0, 0, NULL, 0, sdref->context);
1311e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        break;
1312e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    }
1313e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering}
1314e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering
1315e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart PoetteringDNSServiceErrorType DNSSD_API DNSServiceQueryRecord (
1316e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    DNSServiceRef *ret_sdref,
1317e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    DNSServiceFlags flags,
1318e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    uint32_t interface,
1319e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    const char *fullname,
1320e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    uint16_t type,
1321e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    uint16_t clazz,
1322e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    DNSServiceQueryRecordReply callback,
1323e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    void *context) {
1324e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering
1325e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    DNSServiceErrorType ret = kDNSServiceErr_Unknown;
1326e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    int error;
1327e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    DNSServiceRef sdref = NULL;
1328e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    AvahiIfIndex ifindex;
1329e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering
1330e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    AVAHI_WARN_LINKAGE;
1331e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering
1332e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    if (!ret_sdref || !fullname)
1333e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        return kDNSServiceErr_BadParam;
1334e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    *ret_sdref = NULL;
1335e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering
1336e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    if (interface == kDNSServiceInterfaceIndexLocalOnly || flags != 0) {
1337e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        AVAHI_WARN_UNSUPPORTED;
1338e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        return kDNSServiceErr_Unsupported;
1339e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    }
1340e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering
1341e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    if (!(sdref = sdref_new()))
1342e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        return kDNSServiceErr_Unknown;
1343e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering
1344e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    sdref->context = context;
1345e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    sdref->query_resolver_callback = callback;
1346e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering
1347e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    ASSERT_SUCCESS(pthread_mutex_lock(&sdref->mutex));
1348e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering
1349e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    if (!(sdref->client = avahi_client_new(avahi_simple_poll_get(sdref->simple_poll), 0, generic_client_callback, sdref, &error))) {
1350e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        ret =  map_error(error);
1351e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        goto finish;
1352e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    }
1353e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering
1354e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    ifindex = interface == kDNSServiceInterfaceIndexAny ? AVAHI_IF_UNSPEC : (AvahiIfIndex) interface;
1355e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering
1356e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    if (!(sdref->record_browser = avahi_record_browser_new(sdref->client, ifindex, AVAHI_PROTO_UNSPEC, fullname, clazz, type, 0, query_resolver_callback, sdref))) {
1357e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        ret = map_error(avahi_client_errno(sdref->client));
1358e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        goto finish;
1359e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    }
1360e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering
1361e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    ret = kDNSServiceErr_NoError;
1362e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    *ret_sdref = sdref;
1363e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering
1364e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poetteringfinish:
1365e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering
1366e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    ASSERT_SUCCESS(pthread_mutex_unlock(&sdref->mutex));
1367e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering
1368e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    if (ret != kDNSServiceErr_NoError)
1369e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering        DNSServiceRefDeallocate(sdref);
1370e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering
1371e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering    return ret;
1372e31663c4a2fb2f8bf22efc237c3092242cc9bac2Lennart Poettering}
1373