• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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