Migration support
[handlervirt.git] / announce.c
blob91057d2099f4c6e55e643f81fe60080133473090
1 #include <stdio.h>
2 #include <string.h>
3 #include <stdlib.h>
4 #include <errno.h>
6 #include <avahi-client/client.h>
7 #include <avahi-client/publish.h>
8 #include <avahi-client/lookup.h>
10 #include <avahi-common/alternative.h>
11 #include <avahi-common/simple-watch.h>
12 #include <avahi-common/malloc.h>
13 #include <avahi-common/error.h>
14 #include <avahi-common/timeval.h>
16 struct tender {
17 char *name;
18 char *domain;
19 unsigned long int memory;
20 float cost;
21 AvahiEntryGroup *group;
24 static AvahiSimplePoll *simple_poll = NULL;
26 static void entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata);
28 static void resolve_callback(
29 AvahiServiceResolver *r,
30 AVAHI_GCC_UNUSED AvahiIfIndex interface,
31 AVAHI_GCC_UNUSED AvahiProtocol protocol,
32 AvahiResolverEvent event,
33 const char *name,
34 const char *type,
35 const char *domain,
36 const char *host_name,
37 const AvahiAddress *address,
38 uint16_t port,
39 AvahiStringList *txt,
40 AvahiLookupResultFlags flags,
41 void* userdata) {
43 assert(r);
45 struct tender *tender = (struct tender*) userdata;
47 /* Called whenever a service has been resolved successfully or timed out */
49 switch (event) {
50 case AVAHI_RESOLVER_FAILURE:
51 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))));
52 break;
54 case AVAHI_RESOLVER_FOUND: {
55 char a[AVAHI_ADDRESS_STR_MAX], *t;
56 AvahiStringList *needle;
58 fprintf(stderr, "Service '%s' of type '%s' in domain '%s':\n", name, type, domain);
60 avahi_address_snprint(a, sizeof(a), address);
61 t = avahi_string_list_to_string(txt);
62 fprintf(stderr,
63 "\t%s:%u (%s)\n"
64 "\tTXT=%s\n"
65 "\tcookie is %u\n"
66 "\tis_local: %i\n"
67 "\tour_own: %i\n"
68 "\twide_area: %i\n"
69 "\tmulticast: %i\n"
70 "\tcached: %i\n",
71 host_name, port, a,
73 avahi_string_list_get_service_cookie(txt),
74 !!(flags & AVAHI_LOOKUP_RESULT_LOCAL),
75 !!(flags & AVAHI_LOOKUP_RESULT_OUR_OWN),
76 !!(flags & AVAHI_LOOKUP_RESULT_WIDE_AREA),
77 !!(flags & AVAHI_LOOKUP_RESULT_MULTICAST),
78 !!(flags & AVAHI_LOOKUP_RESULT_CACHED));
80 avahi_free(t);
82 if (tender != NULL) {
83 unsigned int len = strlen(tender->name);
85 if (strlen(name) > len && name[len] == '.' && strncmp(tender->name, name, len) == 0) {
86 if ((needle = avahi_string_list_find (txt, "cost")) != NULL) {
88 float amount;
89 char *cost;
90 avahi_string_list_get_pair (needle, NULL, &cost, NULL);
91 amount = atof(cost);
93 printf("%s: I'll run the VM for the competing cost of L$W %f\n", host_name, amount);
94 if (errno != ERANGE && amount < tender->cost) {
95 tender->cost = amount;
96 free(tender->domain);
97 tender->domain = strdup(&name[++len]);
100 avahi_free(cost);
107 avahi_service_resolver_free(r);
110 static void browse_callback(
111 AvahiServiceBrowser *b,
112 AvahiIfIndex interface,
113 AvahiProtocol protocol,
114 AvahiBrowserEvent event,
115 const char *name,
116 const char *type,
117 const char *domain,
118 AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
119 void* userdata) {
121 assert(b);
122 AvahiClient *c = avahi_service_browser_get_client(b);
124 /* Called whenever a new services becomes available on the LAN or is removed from the LAN */
126 switch (event) {
127 case AVAHI_BROWSER_FAILURE:
129 fprintf(stderr, "(Browser) %s\n", avahi_strerror(avahi_client_errno(avahi_service_browser_get_client(b))));
130 avahi_simple_poll_quit(simple_poll);
131 return;
133 case AVAHI_BROWSER_NEW:
134 fprintf(stderr, "(Browser) NEW: service '%s' of type '%s' in domain '%s'\n", name, type, domain);
136 /* We ignore the returned resolver object. In the callback
137 function we free it. If the server is terminated before
138 the callback function is called the server will free
139 the resolver for us. */
141 if (!(avahi_service_resolver_new(c, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_callback, userdata)))
142 fprintf(stderr, "Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_client_errno(c)));
144 break;
146 case AVAHI_BROWSER_REMOVE:
147 fprintf(stderr, "(Browser) REMOVE: service '%s' of type '%s' in domain '%s'\n", name, type, domain);
148 break;
150 case AVAHI_BROWSER_ALL_FOR_NOW:
151 case AVAHI_BROWSER_CACHE_EXHAUSTED:
152 fprintf(stderr, "(Browser) %s\n", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW");
153 break;
157 static void entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, AVAHI_GCC_UNUSED void *userdata) {
158 switch (state) {
159 case AVAHI_ENTRY_GROUP_ESTABLISHED :
160 /* The entry group has been established successfully */
161 break;
163 case AVAHI_ENTRY_GROUP_COLLISION : {
164 /* A service name collision with a remote service
165 * happened. */
166 break;
169 case AVAHI_ENTRY_GROUP_FAILURE :
170 /* Some kind of failure happened while we were registering our services */
171 avahi_simple_poll_quit(simple_poll);
172 break;
174 case AVAHI_ENTRY_GROUP_UNCOMMITED:
175 case AVAHI_ENTRY_GROUP_REGISTERING:
180 static void client_callback(AvahiClient *c, AvahiClientState state, AVAHI_GCC_UNUSED void * userdata) {
181 assert(c);
183 /* Called whenever the client or server state changes */
185 switch (state) {
186 case AVAHI_CLIENT_S_RUNNING:
187 /* The server has startup successfully and registered its host
188 * name on the network, so it's time to create our services */
189 break;
191 case AVAHI_CLIENT_FAILURE:
192 fprintf(stderr, "Client failure: %s\n", avahi_strerror(avahi_client_errno(c)));
193 avahi_simple_poll_quit(simple_poll);
194 break;
196 case AVAHI_CLIENT_S_COLLISION:
197 /* Let's drop our registered services. When the server is back
198 * in AVAHI_SERVER_RUNNING state we will register them
199 * again with the new host name. */
201 case AVAHI_CLIENT_S_REGISTERING:
202 /* The server records are now being established. This
203 * might be caused by a host name change. We need to wait
204 * for our own records to register until the host name is
205 * properly esatblished. */
206 break;
208 case AVAHI_CLIENT_CONNECTING:
213 static void result_callback(AvahiTimeout *e, void *userdata) {
214 struct tender *tender = (struct tender*) userdata;
216 if (tender->domain == NULL) {
217 struct timeval tv;
218 printf("Waiting for offers!\n");
219 avahi_simple_poll_get(simple_poll)->timeout_update(e, avahi_elapse_time(&tv, 1000*5, 0));
220 } else {
221 printf("And %s will go to %s for the price of %f Lea$eweb Dollars\n", tender->name, tender->domain, tender->cost);
222 avahi_entry_group_free(tender->group);
223 free(tender->name);
224 tender->name = NULL;
225 free(tender->domain);
226 tender->domain = NULL;
227 free(tender);
228 tender = NULL;
234 int main(AVAHI_GCC_UNUSED int argc, AVAHI_GCC_UNUSED char*argv[]) {
235 AvahiClient *client = NULL;
236 AvahiServiceBrowser *sb = NULL;
237 int error;
238 int ret = 1;
239 struct timeval tv;
241 struct tender *this = (struct tender *) malloc(sizeof(struct tender));;
243 /* Allocate main loop object */
244 if (!(simple_poll = avahi_simple_poll_new())) {
245 fprintf(stderr, "Failed to create simple poll object.\n");
246 goto fail;
249 /* Allocate a new client */
250 client = avahi_client_new(avahi_simple_poll_get(simple_poll), 0, client_callback, NULL, &error);
252 /* Check wether creating the client object succeeded */
253 if (!client) {
254 fprintf(stderr, "Failed to create client: %s\n", avahi_strerror(error));
255 goto fail;
258 char txt[254];
259 this->name = strdup("klant1_testdomein");
260 this->memory = 128000;
261 this->domain = NULL;
262 this->cost = 100000;
263 this->group =avahi_entry_group_new(client, entry_group_callback, NULL);
264 snprintf(txt, 254, "memory=%lu", this->memory);
265 avahi_entry_group_add_service(this->group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, this->name, "_offer._tcp", NULL, NULL, 651, txt, NULL, NULL);
266 avahi_entry_group_commit(this->group);
268 /* Create the service browser */
269 if (!(sb = avahi_service_browser_new(client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, "_tender._tcp", NULL, 0, browse_callback, this))) {
270 fprintf(stderr, "Failed to create service browser: %s\n", avahi_strerror(avahi_client_errno(client)));
271 goto fail;
274 /* After 5s we quit the bidding and hopefully return the lowest bid in the network */
275 avahi_simple_poll_get(simple_poll)->timeout_new(avahi_simple_poll_get(simple_poll),
276 avahi_elapse_time(&tv, 1000*5, 0),
277 result_callback,
278 this);
281 /* Run the main loop */
282 avahi_simple_poll_loop(simple_poll);
284 ret = 0;
286 fail:
288 /* Cleanup things */
289 if (sb)
290 avahi_service_browser_free(sb);
292 if (client)
293 avahi_client_free(client);
295 if (simple_poll)
296 avahi_simple_poll_free(simple_poll);
298 return ret;