Migration support
[handlervirt.git] / node / avahi.c
blob3e6d6450d237313e7781aa9527d75e147a0a097a
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 */
55 if (avahi_client_get_state(client) != AVAHI_CLIENT_FAILURE) {
56 /* And create them again with the new name */
57 struct timeval tv;
59 create_services(client);
61 avahi_simple_poll_get(simple_poll)->timeout_update(e, avahi_elapse_time(&tv, 1000*POLL, 0));
65 static void browse_callback(
66 AvahiServiceBrowser *b,
67 AvahiIfIndex interface,
68 AvahiProtocol protocol,
69 AvahiBrowserEvent event,
70 const char *name,
71 const char *type,
72 const char *domain,
73 AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
74 AVAHI_GCC_UNUSED void* userdata) {
76 assert(b);
78 /* Called whenever a new services becomes available on the LAN or is removed from the LAN */
80 switch (event) {
81 case AVAHI_BROWSER_FAILURE:
82 pull_tender(name);
83 fprintf(stderr, "(Browser) %s\n", avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b))));
84 avahi_service_browser_free(b);
85 return;
87 case AVAHI_BROWSER_NEW: {
88 AvahiClient *c = avahi_service_browser_get_client(b);
89 fprintf(stderr, "(Browser) NEW: service '%s' of type '%s' in domain '%s'\n", name, type, domain);
91 /* We ignore the returned resolver object. In the callback
92 function we free it. If the server is terminated before
93 the callback function is called the server will free
94 the resolver for us. */
96 if (!(avahi_service_resolver_new(c, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_callback, NULL)))
97 fprintf(stderr, "Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_client_errno(c)));
99 break;
102 case AVAHI_BROWSER_REMOVE:
103 pull_tender(name);
104 fprintf(stderr, "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'\n", name, type, domain);
105 break;
107 case AVAHI_BROWSER_ALL_FOR_NOW:
108 case AVAHI_BROWSER_CACHE_EXHAUSTED:
109 fprintf(stderr, "(Browser) %s\n", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW");
110 break;
115 void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata) {
116 /* Called whenever the client or server state changes */
118 switch (state) {
119 case AVAHI_CLIENT_S_RUNNING: {
120 /* The server has startup successfully and registered its host
121 * name on the network, so it's time to create our services */
122 struct timeval tv;
124 if (! (offerServiceBrowser = avahi_service_browser_new(c, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_offer._tcp", NULL, 0, browse_callback, NULL))) {
125 fprintf(stderr, "Failed to create service browser: %s\n", avahi_strerror(avahi_client_errno(c)));
128 /* After 10s do some weird modification to the service */
129 avahi_simple_poll_get(simple_poll)->timeout_new(
130 avahi_simple_poll_get(simple_poll),
131 avahi_elapse_time(&tv, 1000*POLL, 0),
132 modify_callback,
135 break;
138 case AVAHI_CLIENT_FAILURE: {
139 int error;
140 AvahiClient *client;
142 if (c) {
143 fprintf(stderr, "Client failure: %s\n", avahi_strerror(avahi_client_errno(c)));
144 avahi_client_free(c);
146 remove_everything();
147 pull_all();
149 /* Allocate a new client */
150 client = avahi_client_new(avahi_simple_poll_get(simple_poll), AVAHI_CLIENT_NO_FAIL, client_callback, NULL, &error);
151 break;
154 case AVAHI_CLIENT_S_COLLISION:
155 /* Let's drop our registered services. When the server is back
156 * in AVAHI_SERVER_RUNNING state we will register them
157 * again with the new host name. */
159 case AVAHI_CLIENT_S_REGISTERING:
160 /* The server records are now being established. This
161 * might be caused by a host name change. We need to wait
162 * for our own records to register until the host name is
163 * properly esatblished. */
164 break;
166 case AVAHI_CLIENT_CONNECTING:
171 void entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, AVAHI_GCC_UNUSED void *userdata) {
172 switch (state) {
173 case AVAHI_ENTRY_GROUP_ESTABLISHED :
174 /* The entry group has been established successfully */
175 break;
177 case AVAHI_ENTRY_GROUP_COLLISION : {
178 /* A service name collision with a remote service
179 * happened. */
180 break;
183 case AVAHI_ENTRY_GROUP_FAILURE :
184 /* Some kind of failure happened while we were registering our services */
185 // avahi_simple_poll_quit(simple_poll);
186 break;
188 case AVAHI_ENTRY_GROUP_UNCOMMITED:
189 case AVAHI_ENTRY_GROUP_REGISTERING: