SIGTERM again
[handlervirt.git] / handler_virt_tender.c
blob529c75c39ce93429bcbc0b0a03edf51e8b2f28f8
1 #include "handler_virt_tender.h"
2 #include <float.h>
3 #include <string.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <unistd.h>
8 #ifdef NOTRACE
9 #define TRACE(...)
10 #else
11 #include <cherokee/cherokee.h>
12 #endif
14 #include <avahi-client/client.h>
15 #include <avahi-client/publish.h>
16 #include <avahi-client/lookup.h>
18 #include <avahi-common/alternative.h>
19 #include <avahi-common/simple-watch.h>
20 #include <avahi-common/malloc.h>
21 #include <avahi-common/error.h>
22 #include <avahi-common/timeval.h>
23 #include <avahi-common/thread-watch.h>
25 static void entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, AVAHI_GCC_UNUSED void *userdata) {
26 switch (state) {
27 case AVAHI_ENTRY_GROUP_ESTABLISHED :
28 /* The entry group has been established successfully */
29 break;
31 case AVAHI_ENTRY_GROUP_COLLISION : {
32 /* A service name collision with a remote service
33 * happened. */
34 break;
37 case AVAHI_ENTRY_GROUP_FAILURE :
38 /* Some kind of failure happened while we were registering our services */
39 break;
41 case AVAHI_ENTRY_GROUP_UNCOMMITED:
42 case AVAHI_ENTRY_GROUP_REGISTERING:
47 static void tender_resolve_callback(
48 AvahiServiceResolver *r,
49 AVAHI_GCC_UNUSED AvahiIfIndex interface,
50 AVAHI_GCC_UNUSED AvahiProtocol protocol,
51 AvahiResolverEvent event,
52 const char *name,
53 const char *type,
54 const char *domain,
55 const char *host_name,
56 const AvahiAddress *address,
57 uint16_t port,
58 AvahiStringList *txt,
59 AvahiLookupResultFlags flags,
60 void* userdata) {
62 tender_t *tender = userdata;
64 assert(r);
66 /* Called whenever a service has been resolved successfully or timed out */
68 switch (event) {
69 case AVAHI_RESOLVER_FAILURE:
70 TRACE("avahi", "(Resolver) FAILURE!\n");
71 avahi_service_resolver_free(r);
72 break;
74 case AVAHI_RESOLVER_FOUND: {
75 char a[AVAHI_ADDRESS_STR_MAX], *t;
76 AvahiStringList *needle;
78 TRACE("avahi", "(Resolver) Service '%s' of type '%s' in domain '%s':\n", name, type, domain);
80 avahi_address_snprint(a, sizeof(a), address);
81 t = avahi_string_list_to_string(txt);
82 TRACE("avahi",
83 "\t%s:%u (%s)\n"
84 "\tTXT=%s\n"
85 "\tcookie is %u\n"
86 "\tis_local: %i\n"
87 "\tour_own: %i\n"
88 "\twide_area: %i\n"
89 "\tmulticast: %i\n"
90 "\tcached: %i\n",
91 host_name, port, a,
93 avahi_string_list_get_service_cookie(txt),
94 !!(flags & AVAHI_LOOKUP_RESULT_LOCAL),
95 !!(flags & AVAHI_LOOKUP_RESULT_OUR_OWN),
96 !!(flags & AVAHI_LOOKUP_RESULT_WIDE_AREA),
97 !!(flags & AVAHI_LOOKUP_RESULT_MULTICAST),
98 !!(flags & AVAHI_LOOKUP_RESULT_CACHED));
101 avahi_free(t);
103 if (tender->name) {
104 unsigned int len = strlen(tender->name);
105 if (strlen(name) > len && name[len] == '.' && strncmp(tender->name, name, len) == 0) {
106 if ((needle = avahi_string_list_find (txt, "cost")) != NULL) {
108 float amount;
109 char *cost;
110 avahi_string_list_get_pair (needle, NULL, &cost, NULL);
111 amount = atof(cost);
113 TRACE("tender", "%s will run %s for the cost of L$W %f\n", host_name, tender->name, amount);
114 if (amount < tender->cost) {
115 /* TODO: LOCK */
116 tender->cost = amount;
117 free(tender->dom);
118 tender->dom = strdup(host_name);
119 TRACE("tender", "We will consider %ss offer!\n", tender->dom);
122 avahi_free(cost);
126 break;
131 static void tender_browse_callback(
132 AvahiServiceBrowser *b,
133 AvahiIfIndex interface,
134 AvahiProtocol protocol,
135 AvahiBrowserEvent event,
136 const char *name,
137 const char *type,
138 const char *domain,
139 AVAHI_GCC_UNUSED AvahiLookupResultFlags flags,
140 void* userdata) {
141 AvahiClient *c;
142 assert(b);
144 c = avahi_service_browser_get_client(b);
146 /* Called whenever a new services becomes available on the LAN or is removed from the LAN */
148 switch (event) {
149 case AVAHI_BROWSER_FAILURE:
150 TRACE("avahi", "(Browser) %s\n", avahi_strerror(avahi_client_errno(c)));
151 return;
153 case AVAHI_BROWSER_NEW:
154 TRACE("avahi", "(Browser) NEW: service '%s' of type '%s' in domain '%s'\n", name, type, domain);
156 /* We ignore the returned resolver object. In the callback
157 function we free it. If the server is terminated before
158 the callback function is called the server will free
159 the resolver for us. */
161 if (!(avahi_service_resolver_new(c, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, tender_resolve_callback, userdata)))
162 TRACE("avahi", "Failed to resolve service '%s': %s\n", name, avahi_strerror(avahi_client_errno(c)));
164 break;
166 case AVAHI_BROWSER_REMOVE:
167 TRACE("avahi", "%s, (Browser) REMOVE: service '%s' of type '%s' in domain '%s'\n", __func__, name, type, domain);
168 break;
170 case AVAHI_BROWSER_ALL_FOR_NOW:
171 case AVAHI_BROWSER_CACHE_EXHAUSTED:
172 TRACE("avahi", "(Browser) %s\n", event == AVAHI_BROWSER_CACHE_EXHAUSTED ? "CACHE_EXHAUSTED" : "ALL_FOR_NOW");
173 break;
177 char * create_tender(AvahiClient *client, AvahiThreadedPoll *threaded_poll, const char *name, unsigned long memory) {
178 char txt[255];
179 tender_t best_tender;
181 snprintf(txt, 253, "memory=%lu", memory);
182 txt[254] = '\0';
184 best_tender.name = name;
185 best_tender.cost = FLT_MAX;
186 best_tender.dom = NULL;
188 avahi_threaded_poll_lock(threaded_poll);
189 AvahiServiceBrowser *sb = avahi_service_browser_new(client, AVAHI_IF_UNSPEC,
190 AVAHI_PROTO_UNSPEC, "_tender._tcp",
191 NULL, 0, tender_browse_callback, &best_tender);
193 if (sb == NULL) {
194 TRACE("avahi", "For whatever reason the sb is NULL\n");
195 } else {
196 AvahiEntryGroup *group = avahi_entry_group_new(client, entry_group_callback, NULL);
198 if (group == NULL) {
199 TRACE("avahi", "For whatever reason the group is NULL\n");
200 } else {
201 avahi_entry_group_add_service(group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0,
202 best_tender.name, "_offer._tcp", NULL, NULL, 651, txt, NULL, NULL);
203 avahi_entry_group_commit(group);
204 avahi_threaded_poll_unlock(threaded_poll);
206 sleep(3); /* we are for quick bidding ;) */
208 avahi_threaded_poll_lock(threaded_poll);
209 avahi_entry_group_free(group);
212 avahi_service_browser_free(sb);
214 avahi_threaded_poll_unlock(threaded_poll);
216 return best_tender.dom;