1896156392e7c9645f9719d6e4267c5b5bbb1122
[handlervirt.git] / node / avahi.c
blob1896156392e7c9645f9719d6e4267c5b5bbb1122
1 #include <stdio.h>
2 #include <time.h>
3 #include <errno.h>
5 #include <avahi-client/client.h>
6 #include <avahi-client/lookup.h>
7 #include <avahi-common/simple-watch.h>
9 #include <avahi-common/alternative.h>
10 #include <avahi-common/simple-watch.h>
11 #include <avahi-common/malloc.h>
12 #include <avahi-common/error.h>
13 #include <avahi-common/timeval.h>
15 #include "node.h"
17 static void resolve_callback(
18 AvahiServiceResolver *r,
19 AVAHI_GCC_UNUSED AvahiIfIndex interface,
20 AVAHI_GCC_UNUSED AvahiProtocol protocol,
21 AvahiResolverEvent event,
22 const char *name,
23 const char *type,
24 const char *domain,
25 const char *host_name,
26 const AvahiAddress *address,
27 uint16_t port,
28 AvahiStringList *txt,
29 AvahiLookupResultFlags flags,
30 AVAHI_GCC_UNUSED void* userdata) {
32 assert(r);
34 /* Called whenever a service has been resolved successfully or timed out */
36 switch (event) {
37 case AVAHI_RESOLVER_FAILURE:
38 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))));
39 break;
41 case AVAHI_RESOLVER_FOUND:
42 parse_tender(r, name, txt);
43 break;
46 avahi_service_resolver_free(r);
49 static void modify_callback(AvahiTimeout *e, void *userdata) {
50 AvahiClient *client = userdata;
52 /* If the server is currently running, we need to remove our
53 * service and create it anew */
54 if (avahi_client_get_state(client) == AVAHI_CLIENT_S_RUNNING) {
55 /* And create them again with the new name */
56 struct timeval tv;
58 create_services(client);
60 avahi_simple_poll_get(simple_poll)->timeout_update(e, avahi_elapse_time(&tv, 1000*POLL, 0));
64 static void browse_callback(
65 AvahiServiceBrowser *b,
66 AvahiIfIndex interface,
67 AvahiProtocol protocol,
68 AvahiBrowserEvent event,
69 const char *name,
70 const char *type,
71 const char *domain,
72 AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
73 AVAHI_GCC_UNUSED void* userdata) {
75 assert(b);
77 /* Called whenever a new services becomes available on the LAN or is removed from the LAN */
79 switch (event) {
80 case AVAHI_BROWSER_FAILURE:
81 fprintf(stderr, "(Browser) %s\n", avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b))));
82 avahi_service_browser_free(b);
83 return;
85 case AVAHI_BROWSER_NEW: {
86 AvahiClient *c = avahi_service_browser_get_client(b);
87 fprintf(stderr, "(Browser) NEW: service '%s' of type '%s' in domain '%s'\n", name, type, domain);
89 /* We ignore the returned resolver object. In the callback
90 function we free it. If the server is terminated before
91 the callback function is called the server will free
92 the resolver for us. */
94 if (!(avahi_service_resolver_new(c, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_callback, NULL)))
95 fprintf(stderr, "Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_client_errno(c)));
97 break;
100 case AVAHI_BROWSER_REMOVE:
101 pull_tender(name);
102 fprintf(stderr, "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'\n", name, type, domain);
103 break;
105 case AVAHI_BROWSER_ALL_FOR_NOW:
106 case AVAHI_BROWSER_CACHE_EXHAUSTED:
107 fprintf(stderr, "(Browser) %s\n", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW");
108 break;
113 void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata) {
114 /* Called whenever the client or server state changes */
116 switch (state) {
117 case AVAHI_CLIENT_S_RUNNING: {
118 /* The server has startup successfully and registered its host
119 * name on the network, so it's time to create our services */
120 struct timeval tv;
122 if (!avahi_service_browser_new(c, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_offer._tcp", NULL, 0, browse_callback, NULL)) {
123 fprintf(stderr, "Failed to create service browser: %s\n", avahi_strerror(avahi_client_errno(c)));
126 /* After 10s do some weird modification to the service */
127 avahi_simple_poll_get(simple_poll)->timeout_new(
128 avahi_simple_poll_get(simple_poll),
129 avahi_elapse_time(&tv, 1000*POLL, 0),
130 modify_callback,
133 break;
136 case AVAHI_CLIENT_FAILURE: {
137 int error;
138 AvahiClient *client;
140 if (c) {
141 fprintf(stderr, "Client failure: %s\n", avahi_strerror(avahi_client_errno(c)));
142 avahi_client_free(c);
145 /* Allocate a new client */
146 client = avahi_client_new(avahi_simple_poll_get(simple_poll), AVAHI_CLIENT_NO_FAIL, client_callback, NULL, &error);
147 break;
150 case AVAHI_CLIENT_S_COLLISION:
151 /* Let's drop our registered services. When the server is back
152 * in AVAHI_SERVER_RUNNING state we will register them
153 * again with the new host name. */
155 case AVAHI_CLIENT_S_REGISTERING:
156 /* The server records are now being established. This
157 * might be caused by a host name change. We need to wait
158 * for our own records to register until the host name is
159 * properly esatblished. */
160 break;
162 case AVAHI_CLIENT_CONNECTING:
167 void entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, AVAHI_GCC_UNUSED void *userdata) {
168 switch (state) {
169 case AVAHI_ENTRY_GROUP_ESTABLISHED :
170 /* The entry group has been established successfully */
171 break;
173 case AVAHI_ENTRY_GROUP_COLLISION : {
174 /* A service name collision with a remote service
175 * happened. */
176 break;
179 case AVAHI_ENTRY_GROUP_FAILURE :
180 /* Some kind of failure happened while we were registering our services */
181 // avahi_simple_poll_quit(simple_poll);
182 break;
184 case AVAHI_ENTRY_GROUP_UNCOMMITED:
185 case AVAHI_ENTRY_GROUP_REGISTERING: