1 #include "handler_virt_tender.h"
11 #include <cherokee/cherokee.h>
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
) {
27 case AVAHI_ENTRY_GROUP_ESTABLISHED
:
28 /* The entry group has been established successfully */
31 case AVAHI_ENTRY_GROUP_COLLISION
: {
32 /* A service name collision with a remote service
37 case AVAHI_ENTRY_GROUP_FAILURE
:
38 /* Some kind of failure happened while we were registering our services */
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
,
55 const char *host_name
,
56 const AvahiAddress
*address
,
59 AvahiLookupResultFlags flags
,
62 tender_t
*tender
= userdata
;
66 /* Called whenever a service has been resolved successfully or timed out */
69 case AVAHI_RESOLVER_FAILURE
:
70 TRACE("avahi", "(Resolver) FAILURE!\n");
71 avahi_service_resolver_free(r
);
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
);
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
));
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
) {
110 avahi_string_list_get_pair (needle
, NULL
, &cost
, NULL
);
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
) {
116 tender
->cost
= amount
;
118 tender
->dom
= strdup(host_name
);
119 TRACE("tender", "We will consider %ss offer!\n", tender
->dom
);
131 static void tender_browse_callback(
132 AvahiServiceBrowser
*b
,
133 AvahiIfIndex interface
,
134 AvahiProtocol protocol
,
135 AvahiBrowserEvent event
,
139 AVAHI_GCC_UNUSED AvahiLookupResultFlags flags
,
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 */
149 case AVAHI_BROWSER_FAILURE
:
150 TRACE("avahi", "(Browser) %s\n", avahi_strerror(avahi_client_errno(c
)));
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
)));
166 case AVAHI_BROWSER_REMOVE
:
167 TRACE("avahi", "%s, (Browser) REMOVE: service '%s' of type '%s' in domain '%s'\n", __func__
, name
, type
, domain
);
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");
177 char * create_tender(AvahiClient
*client
, AvahiThreadedPoll
*threaded_poll
, const char *name
, unsigned long memory
) {
179 tender_t best_tender
;
181 snprintf(txt
, 253, "memory=%lu", memory
);
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
);
194 TRACE("avahi", "For whatever reason the sb is NULL\n");
196 AvahiEntryGroup
*group
= avahi_entry_group_new(client
, entry_group_callback
, NULL
);
199 TRACE("avahi", "For whatever reason the group is NULL\n");
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
;