]> git.meshlink.io Git - catta/blob - avahi-core/browse-service.c
* split off lookup.h and publish.h from core.h
[catta] / avahi-core / browse-service.c
1 /* $Id$ */
2
3 /***
4   This file is part of avahi.
5  
6   avahi is free software; you can redistribute it and/or modify it
7   under the terms of the GNU Lesser General Public License as
8   published by the Free Software Foundation; either version 2.1 of the
9   License, or (at your option) any later version.
10  
11   avahi is distributed in the hope that it will be useful, but WITHOUT
12   ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
13   or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
14   Public License for more details.
15  
16   You should have received a copy of the GNU Lesser General Public
17   License along with avahi; if not, write to the Free Software
18   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
19   USA.
20 ***/
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <string.h>
27
28 #include <avahi-common/domain.h>
29 #include <avahi-common/malloc.h>
30 #include <avahi-common/error.h>
31
32 #include "browse.h"
33 #include "log.h"
34
35 struct AvahiSServiceBrowser {
36     AvahiServer *server;
37     char *domain_name;
38     char *service_type;
39     
40     AvahiSRecordBrowser *record_browser;
41
42     AvahiSServiceBrowserCallback callback;
43     void* userdata;
44
45     AVAHI_LLIST_FIELDS(AvahiSServiceBrowser, browser);
46 };
47
48 static void record_browser_callback(
49     AvahiSRecordBrowser*rr,
50     AvahiIfIndex interface,
51     AvahiProtocol protocol,
52     AvahiBrowserEvent event,
53     AvahiRecord *record,
54     AvahiLookupResultFlags flags,
55     void* userdata) {
56     
57     AvahiSServiceBrowser *b = userdata;
58     char *n = NULL, *c = NULL, *s = NULL;
59     char service[128];
60
61     assert(rr);
62     assert(b);
63
64     if (record) {
65         char *e;
66         assert(record->key->type == AVAHI_DNS_TYPE_PTR);
67         
68         c = n = avahi_normalize_name(record->data.ptr.name);
69         
70         if (!(avahi_unescape_label((const char**) &c, service, sizeof(service))))
71             goto fail;
72         
73         for (s = e = c; *c == '_';) {
74             c += strcspn(c, ".");
75             
76             if (*c == 0)
77                 goto fail;
78             
79             assert(*c == '.');
80             e = c;
81             c++;
82         }
83         
84         *e = 0;
85
86         if (!avahi_domain_equal(c, b->domain_name))
87             goto fail;
88     }
89     
90     b->callback(b, interface, protocol, event, record ? service : NULL, s, c, flags, b->userdata);
91     avahi_free(n);
92
93     return;
94
95 fail:
96     avahi_log_warn("Invalid service '%s'", n);
97     avahi_free(n);
98 }
99
100 AvahiSServiceBrowser *avahi_s_service_browser_new(
101     AvahiServer *server,
102     AvahiIfIndex interface,
103     AvahiProtocol protocol,
104     const char *service_type,
105     const char *domain,
106     AvahiLookupFlags flags,
107     AvahiSServiceBrowserCallback callback,
108     void* userdata) {
109
110     AvahiSServiceBrowser *b;
111     AvahiKey *k;
112     char *n = NULL;
113     
114     assert(server);
115     assert(callback);
116     assert(service_type);
117
118     if (!avahi_is_valid_service_type(service_type)) {
119         avahi_server_set_errno(server, AVAHI_ERR_INVALID_SERVICE_TYPE);
120         return NULL;
121     }
122
123     if (domain && !avahi_is_valid_domain_name(domain)) {
124         avahi_server_set_errno(server, AVAHI_ERR_INVALID_DOMAIN_NAME);
125         return NULL;
126     }
127
128     if (!domain)
129         domain = server->domain_name;
130     
131     if (!AVAHI_VALID_FLAGS(flags, AVAHI_LOOKUP_USE_WIDE_AREA|AVAHI_LOOKUP_USE_MULTICAST)) {
132         avahi_server_set_errno(server, AVAHI_ERR_INVALID_FLAGS);
133         return NULL;
134     }
135     
136     if (!(b = avahi_new(AvahiSServiceBrowser, 1))) {
137         avahi_server_set_errno(server, AVAHI_ERR_NO_MEMORY);
138         return NULL;
139     }
140     
141     b->server = server;
142     b->domain_name = avahi_normalize_name(domain);
143     b->service_type = avahi_normalize_name(service_type);
144     b->callback = callback;
145     b->userdata = userdata;
146     AVAHI_LLIST_PREPEND(AvahiSServiceBrowser, browser, server->service_browsers, b);
147
148     n = avahi_strdup_printf("%s.%s", b->service_type, b->domain_name);
149     k = avahi_key_new(n, AVAHI_DNS_CLASS_IN, AVAHI_DNS_TYPE_PTR);
150     avahi_free(n);
151     
152     b->record_browser = avahi_s_record_browser_new(server, interface, protocol, k, flags, record_browser_callback, b);
153
154     avahi_key_unref(k);
155
156     if (!b->record_browser) {
157         avahi_s_service_browser_free(b);
158         return NULL;
159     }
160     
161     return b;
162 }
163
164 void avahi_s_service_browser_free(AvahiSServiceBrowser *b) {
165     assert(b);
166
167     AVAHI_LLIST_REMOVE(AvahiSServiceBrowser, browser, b->server->service_browsers, b);
168
169     if (b->record_browser)
170         avahi_s_record_browser_free(b->record_browser);
171     
172     avahi_free(b->domain_name);
173     avahi_free(b->service_type);
174     avahi_free(b);
175 }