1 /***
2 This file is part of avahi.
3
4 avahi is free software; you can redistribute it and/or modify it
5 under the terms of the GNU Lesser General Public License as
6 published by the Free Software Foundation; either version 2.1 of the
7 License, or (at your option) any later version.
8
9 avahi is distributed in the hope that it will be useful, but WITHOUT
10 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
11 or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General
12 Public License for more details.
13
14 You should have received a copy of the GNU Lesser General Public
15 License along with avahi; if not, write to the Free Software
16 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
17 USA.
18 ***/
19
20 #ifdef HAVE_CONFIG_H
21 #include <config.h>
22 #endif
23
24 #include <stdio.h>
25 #include <assert.h>
26 #include <stdlib.h>
27 #include <time.h>
28
29 #include <avahi-client/client.h>
30 #include <avahi-client/lookup.h>
31
32 #include <avahi-common/simple-watch.h>
33 #include "avahi-common/avahi-malloc.h"
34 #include <avahi-common/error.h>
35
36 static AvahiSimplePoll *simple_poll = NULL;
37
resolve_callback(AvahiServiceResolver * r,AVAHI_GCC_UNUSED AvahiIfIndex interface,AVAHI_GCC_UNUSED AvahiProtocol protocol,AvahiResolverEvent event,const char * name,const char * type,const char * domain,const char * host_name,const AvahiAddress * address,uint16_t port,AvahiStringList * txt,AvahiLookupResultFlags flags,AVAHI_GCC_UNUSED void * userdata)38 static void resolve_callback(
39 AvahiServiceResolver *r,
40 AVAHI_GCC_UNUSED AvahiIfIndex interface,
41 AVAHI_GCC_UNUSED AvahiProtocol protocol,
42 AvahiResolverEvent event,
43 const char *name,
44 const char *type,
45 const char *domain,
46 const char *host_name,
47 const AvahiAddress *address,
48 uint16_t port,
49 AvahiStringList *txt,
50 AvahiLookupResultFlags flags,
51 AVAHI_GCC_UNUSED void* userdata) {
52
53 assert(r);
54
55 /* Called whenever a service has been resolved successfully or timed out */
56
57 switch (event) {
58 case AVAHI_RESOLVER_FAILURE:
59 fprintf(stderr, "(Resolver) Failed to resolve service '%s' of type '%s' in domain '%s': %s\n", name, type, domain, avahi_strerror(avahi_client_errno(avahi_service_resolver_get_client(r))));
60 break;
61
62 case AVAHI_RESOLVER_FOUND: {
63 char a[AVAHI_ADDRESS_STR_MAX], *t;
64
65 fprintf(stderr, "Service '%s' of type '%s' in domain '%s':\n", name, type, domain);
66
67 avahi_address_snprint(a, sizeof(a), address);
68 t = avahi_string_list_to_string(txt);
69 fprintf(stderr,
70 "\t%s:%u (%s)\n"
71 "\tTXT=%s\n"
72 "\tcookie is %u\n"
73 "\tis_local: %i\n"
74 "\tour_own: %i\n"
75 "\twide_area: %i\n"
76 "\tmulticast: %i\n"
77 "\tcached: %i\n",
78 host_name, port, a,
79 t,
80 avahi_string_list_get_service_cookie(txt),
81 !!(flags & AVAHI_LOOKUP_RESULT_LOCAL),
82 !!(flags & AVAHI_LOOKUP_RESULT_OUR_OWN),
83 !!(flags & AVAHI_LOOKUP_RESULT_WIDE_AREA),
84 !!(flags & AVAHI_LOOKUP_RESULT_MULTICAST),
85 !!(flags & AVAHI_LOOKUP_RESULT_CACHED));
86
87 avahi_free(t);
88 }
89 }
90
91 avahi_service_resolver_free(r);
92 }
93
browse_callback(AvahiServiceBrowser * b,AvahiIfIndex interface,AvahiProtocol protocol,AvahiBrowserEvent event,const char * name,const char * type,const char * domain,AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,void * userdata)94 static void browse_callback(
95 AvahiServiceBrowser *b,
96 AvahiIfIndex interface,
97 AvahiProtocol protocol,
98 AvahiBrowserEvent event,
99 const char *name,
100 const char *type,
101 const char *domain,
102 AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
103 void* userdata) {
104
105 AvahiClient *c = userdata;
106 assert(b);
107
108 /* Called whenever a new services becomes available on the LAN or is removed from the LAN */
109
110 switch (event) {
111 case AVAHI_BROWSER_FAILURE:
112
113 fprintf(stderr, "(Browser) %s\n", avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b))));
114 avahi_simple_poll_quit(simple_poll);
115 return;
116
117 case AVAHI_BROWSER_NEW:
118 fprintf(stderr, "(Browser) NEW: service '%s' of type '%s' in domain '%s'\n", name, type, domain);
119
120 /* We ignore the returned resolver object. In the callback
121 function we free it. If the server is terminated before
122 the callback function is called the server will free
123 the resolver for us. */
124
125 if (!(avahi_service_resolver_new(c, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_callback, c)))
126 fprintf(stderr, "Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_client_errno(c)));
127
128 break;
129
130 case AVAHI_BROWSER_REMOVE:
131 fprintf(stderr, "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'\n", name, type, domain);
132 break;
133
134 case AVAHI_BROWSER_ALL_FOR_NOW:
135 case AVAHI_BROWSER_CACHE_EXHAUSTED:
136 fprintf(stderr, "(Browser) %s\n", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW");
137 break;
138 }
139 }
140
client_callback(AvahiClient * c,AvahiClientState state,AVAHI_GCC_UNUSED void * userdata)141 static void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata) {
142 assert(c);
143
144 /* Called whenever the client or server state changes */
145
146 if (state == AVAHI_CLIENT_FAILURE) {
147 fprintf(stderr, "Server connection failure: %s\n", avahi_strerror(avahi_client_errno(c)));
148 avahi_simple_poll_quit(simple_poll);
149 }
150 }
151
main(AVAHI_GCC_UNUSED int argc,AVAHI_GCC_UNUSED char * argv[])152 int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char*argv[]) {
153 AvahiClient *client = NULL;
154 AvahiServiceBrowser *sb = NULL;
155 int error;
156 int ret = 1;
157
158 /* Allocate main loop object */
159 if (!(simple_poll = avahi_simple_poll_new())) {
160 fprintf(stderr, "Failed to create simple poll object.\n");
161 goto fail;
162 }
163
164 /* Allocate a new client */
165 client = avahi_client_new(avahi_simple_poll_get(simple_poll), 0, client_callback, NULL, &error);
166
167 /* Check wether creating the client object succeeded */
168 if (!client) {
169 fprintf(stderr, "Failed to create client: %s\n", avahi_strerror(error));
170 goto fail;
171 }
172
173 /* Create the service browser */
174 if (!(sb = avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_http._tcp", NULL, 0, browse_callback, client))) {
175 fprintf(stderr, "Failed to create service browser: %s\n", avahi_strerror(avahi_client_errno(client)));
176 goto fail;
177 }
178
179 /* Run the main loop */
180 avahi_simple_poll_loop(simple_poll);
181
182 ret = 0;
183
184 fail:
185
186 /* Cleanup things */
187 if (sb)
188 avahi_service_browser_free(sb);
189
190 if (client)
191 avahi_client_free(client);
192
193 if (simple_poll)
194 avahi_simple_poll_free(simple_poll);
195
196 return ret;
197 }
198