6 #include <avahi-client/client.h>
7 #include <avahi-client/publish.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 <libvirt/libvirt.h>
20 unsigned int domainid
;
21 AvahiEntryGroup
*group
;
25 typedef struct list_el domu
;
27 domu
* domus
= NULL
; /* list of domains */
28 unsigned int domu_count
= 0;
29 static AvahiSimplePoll
*simple_poll
= NULL
;
31 static AvahiStringList
* domainProperties(virDomainPtr thisDomain
) {
32 AvahiStringList
*new = avahi_string_list_new(NULL
);
34 virDomainGetInfo(thisDomain
, &info
);
35 new = avahi_string_list_add_printf(new, "maxMem=%lu", info
.maxMem
);
36 new = avahi_string_list_add_printf(new, "memory=%lu", info
.memory
);
37 new = avahi_string_list_add_printf(new, "cpuTime=%llu", info
.cpuTime
);
39 /* todo network, block device */
44 static void entry_group_callback(AvahiEntryGroup
*g
, AvahiEntryGroupState state
, AVAHI_GCC_UNUSED
void *userdata
) {
45 /* Called whenever the entry group state changes */
48 case AVAHI_ENTRY_GROUP_ESTABLISHED
:
49 /* The entry group has been established successfully */
50 //fprintf(stderr, "Service '%s' successfully established.\n", name);
53 case AVAHI_ENTRY_GROUP_COLLISION
: {
56 /* A service name collision with a remote service
57 * happened. Let's pick a new name */
58 //n = avahi_alternative_service_name(name);
62 // fprintf(stderr, "Service name collision, renaming service to '%s'\n", name);
64 /* And recreate the services */
65 //create_services(avahi_entry_group_get_client(g));
69 case AVAHI_ENTRY_GROUP_FAILURE
:
71 fprintf(stderr
, "Entry group failure: %s\n", avahi_strerror(avahi_client_errno(avahi_entry_group_get_client(g
))));
73 /* Some kind of failure happened while we were registering our services */
74 avahi_simple_poll_quit(simple_poll
);
77 case AVAHI_ENTRY_GROUP_UNCOMMITED
:
78 case AVAHI_ENTRY_GROUP_REGISTERING
:
83 void create_services(AvahiClient
*c
) {
84 virConnectPtr conn
= virConnectOpenReadOnly(NULL
);
87 int maxid
= virConnectNumOfDomains(conn
);
88 if (maxid
> 1) { /* ignore dom0 */
89 int *ids
= (int *) malloc(sizeof(int) * maxid
);
90 if ((maxid
= virConnectListDomains(conn
, &ids
[0], maxid
)) < 0) {
94 unsigned int domu_count_new
= (maxid
- 1);
95 domu
* domus_old
= domus
;
96 domus
= (domu
*) malloc(sizeof(domu
) * domu_count_new
);
97 const char *type
= "_domu._tcp";
98 for (i
= 0; i
< domu_count_new
; i
++) {
100 domus
[i
].group
= NULL
;
101 domus
[i
].domainid
= ids
[i
+1];
104 for (j
= 0; j
< domu_count
; j
++) {
105 if (ids
[i
+1] == domus_old
[j
].domainid
) {
106 virDomainPtr thisDomain
= virDomainLookupByID(conn
, domus
[i
].domainid
);
107 AvahiStringList
*domainProps
;
108 domus
[i
].group
= domus_old
[j
].group
;
109 domus_old
[j
].keep
= 1;
110 domainProps
= domainProperties(thisDomain
);
111 avahi_entry_group_update_service_txt_strlst(domus
[i
].group
, AVAHI_IF_UNSPEC
, AVAHI_PROTO_UNSPEC
, 0, virDomainGetName(thisDomain
), type
, NULL
, domainProps
);
112 avahi_string_list_free(domainProps
);
113 virDomainFree(thisDomain
);
116 if (i
> domu_count
|| domus
[i
].group
== NULL
) {
117 AvahiStringList
*domainProps
;
118 virDomainPtr thisDomain
= virDomainLookupByID(conn
, ids
[i
+1]);
119 domus
[i
].group
= avahi_entry_group_new(c
, entry_group_callback
, NULL
);
120 domainProps
= domainProperties(thisDomain
);
121 avahi_entry_group_add_service_strlst(domus
[i
].group
, AVAHI_IF_UNSPEC
, AVAHI_PROTO_UNSPEC
, 0, virDomainGetName(thisDomain
), type
, NULL
, NULL
, 651, domainProps
);
122 avahi_string_list_free(domainProps
);
123 virDomainFree(thisDomain
);
124 avahi_entry_group_commit(domus
[i
].group
);
129 for (i
= 0; i
< domu_count
; i
++) {
130 if (domus_old
[i
].keep
== 0 && domus_old
[i
].group
!= NULL
) {
131 avahi_entry_group_free(domus_old
[i
].group
);
136 domu_count
= domu_count_new
;
140 virConnectClose(conn
);
144 static void client_callback(AvahiClient
*c
, AvahiClientState state
, AVAHI_GCC_UNUSED
void * userdata
) {
147 /* Called whenever the client or server state changes */
150 case AVAHI_CLIENT_S_RUNNING
:
152 /* The server has startup successfully and registered its host
153 * name on the network, so it's time to create our services */
157 case AVAHI_CLIENT_FAILURE
:
159 fprintf(stderr
, "Client failure: %s\n", avahi_strerror(avahi_client_errno(c
)));
160 avahi_simple_poll_quit(simple_poll
);
164 case AVAHI_CLIENT_S_COLLISION
:
166 /* Let's drop our registered services. When the server is back
167 * in AVAHI_SERVER_RUNNING state we will register them
168 * again with the new host name. */
170 case AVAHI_CLIENT_S_REGISTERING
:
172 /* The server records are now being established. This
173 * might be caused by a host name change. We need to wait
174 * for our own records to register until the host name is
175 * properly esatblished. */
178 avahi_entry_group_reset(group);*/
182 case AVAHI_CLIENT_CONNECTING
:
189 static void modify_callback(AvahiTimeout
*e
, void *userdata
) {
191 AvahiClient
*client
= userdata
;
193 // fprintf(stderr, "Doing some weird modification\n");
195 /* If the server is currently running, we need to remove our
196 * service and create it anew */
197 if (avahi_client_get_state(client
) == AVAHI_CLIENT_S_RUNNING
) {
198 /* And create them again with the new name */
199 create_services(client
);
201 avahi_simple_poll_get(simple_poll
)->timeout_update(e
, avahi_elapse_time(&tv
, 1000*POLL
, 0));
204 int main(AVAHI_GCC_UNUSED
int argc
, AVAHI_GCC_UNUSED
char*argv
[]) {
205 AvahiClient
*client
= NULL
;
209 /* Allocate main loop object */
210 if (!(simple_poll
= avahi_simple_poll_new())) {
211 fprintf(stderr
, "Failed to create simple poll object.\n");
215 /* Allocate a new client */
216 client
= avahi_client_new(avahi_simple_poll_get(simple_poll
), 0, client_callback
, NULL
, &error
);
218 /* Check wether creating the client object succeeded */
220 fprintf(stderr
, "Failed to create client: %s\n", avahi_strerror(error
));
224 /* After 10s do some weird modification to the service */
225 avahi_simple_poll_get(simple_poll
)->timeout_new(
226 avahi_simple_poll_get(simple_poll
),
227 avahi_elapse_time(&tv
, 1000*POLL
, 0),
231 /* Run the main loop */
232 avahi_simple_poll_loop(simple_poll
);
241 avahi_client_free(client
);
244 avahi_simple_poll_free(simple_poll
);