diff options
author | kraxel <kraxel> | 2007-02-06 16:07:24 +0000 |
---|---|---|
committer | kraxel <kraxel> | 2007-02-06 16:07:24 +0000 |
commit | 32f212ab9d1b4dcf4e2be5abc3776d8192bb93f4 (patch) | |
tree | 6b7fcc6e5b3a4af7220c4a3070f76e7ebbd6867f /mdns-publish-vnc.c | |
parent | cbd9777e41ce186c9ef2e060aea5dab9647f1b4e (diff) | |
download | xenwatch-32f212ab9d1b4dcf4e2be5abc3776d8192bb93f4.tar.gz |
mdns vnc stuff
Diffstat (limited to 'mdns-publish-vnc.c')
-rw-r--r-- | mdns-publish-vnc.c | 238 |
1 files changed, 238 insertions, 0 deletions
diff --git a/mdns-publish-vnc.c b/mdns-publish-vnc.c new file mode 100644 index 0000000..1a88fa0 --- /dev/null +++ b/mdns-publish-vnc.c @@ -0,0 +1,238 @@ +#include <stdio.h> +#include <stdlib.h> +#include <stdarg.h> +#include <string.h> +#include <unistd.h> +#include <signal.h> +#include <fcntl.h> +#include <time.h> +#include <sys/syslog.h> +#include <sys/utsname.h> + +#include <xs.h> + +#include "list.h" +#include "xenstore.h" +#include "mdns-publish.h" + +/* ------------------------------------------------------------- */ + +struct dom { + int domid; + char name[128]; + int destroyed; + + char label[256]; + int vnc_port; + int published; + struct mdns_pub_entry *entry; + + struct list_head next; +}; + +static LIST_HEAD(doms); +static struct utsname uts; + +/* ------------------------------------------------------------- */ + +static struct dom *find_dom(int domid) +{ + struct dom *dom; + struct list_head *item; + + list_for_each(item, &doms) { + dom = list_entry(item, struct dom, next); + if (dom->domid == domid) + return dom; + } + return NULL; +} + +static struct dom *get_dom(int domid) +{ + struct dom *dom; + + dom = find_dom(domid); + if (!dom) { + dom = malloc(sizeof(*dom)); + memset(dom,0,sizeof(*dom)); + dom->domid = domid; + list_add_tail(&dom->next, &doms); + } + return dom; +} + +static void try_attach_domain(struct mdns_pub *mdns, struct dom *dom, int boot) +{ + if (dom->published) + return; + if (!strlen(dom->name)) + return; + if (!dom->vnc_port) + return; + + snprintf(dom->label, sizeof(dom->label), "host %s, guest %s", + uts.nodename, dom->name); + mdns_log_printf(mdns, LOG_INFO, "pub: %s (%d)\n", dom->name, dom->domid); + dom->entry = mdns_pub_add(mdns, dom->label, "_rfb._tcp", dom->vnc_port); + + dom->published = 1; +} + +static void try_release_domain(struct mdns_pub *mdns, struct dom *dom) +{ + if (!dom->destroyed) + return; + if (dom->published) { + mdns_log_printf(mdns, LOG_INFO, "del: %s (%d)\n", dom->name, dom->domid); + mdns_pub_del(dom->entry); + } + list_del(&dom->next); + free(dom); +} + +/* ------------------------------------------------------------- */ + +static void usage(FILE *fp) +{ + fprintf(fp, "usage: [fixme]\n"); +} + +int main(int argc, char *argv[]) +{ + struct mdns_pub *mdns = NULL; + struct xs_handle *xenstore = NULL; + xs_transaction_t xst; + char **vec = NULL; + int domid, c; + int debug = 0; + char path[128], value[128]; + unsigned int count, i, rc; + struct dom *dom; + fd_set set; + + for (;;) { + if (-1 == (c = getopt(argc, argv, "hd"))) + break; + switch (c) { + + case 'd': + debug++; + break; + + case 'h': + usage(stdout); + exit(0); + default: + usage(stderr); + exit(1); + } + } + + mdns_pub_appname = "mdns-publish-vnc"; + uname(&uts); + if (!debug) + mdns_daemonize(); + + /* connect to xenstore */ + xenstore = xenstore_open(1,1,1,1); + if (NULL == xenstore) { + mdns_log_printf(mdns, LOG_ERR, "can't access xenstore, exiting\n"); + exit(1); + } + xs_watch(xenstore, "/local/domain", "token"); + + mdns = mdns_pub_init(debug); + if (NULL == mdns) + exit(1); + mdns_sigsetup(mdns); + mdns_pub_start(mdns); + + /* look for running domains */ + if (!(xst = xs_transaction_start(xenstore))) { + mdns_log_printf(mdns, LOG_ERR, "Oops, can't start xenstore transaction\n"); + exit(1); + } + vec = xs_directory(xenstore, xst, "/local/domain", &count); + xs_transaction_end(xenstore, xst, 0); + + fprintf(stderr,"looking for existing domains\n"); + for (i = 0; i < count; i++) { + domid = atoi(vec[i]); + dom = get_dom(domid); + snprintf(path, sizeof(path), "/local/domain/%d/name", domid); + xenstore_read(xenstore, path, dom->name, sizeof(dom->name)); + snprintf(path, sizeof(path), "/local/domain/%d/console/vnc-port", domid); + if (0 == xenstore_read(xenstore, path, value, sizeof(value))) + dom->vnc_port = atoi(value); + try_attach_domain(mdns, dom, 1); + } + + /* main loop */ + fprintf(stderr,"ok, watching out for changes now\n"); + for (;;) { + if (mdns_pub_appquit) + break; + + FD_ZERO(&set); + FD_SET(xs_fileno(xenstore), &set); + switch (select(xs_fileno(xenstore)+1, &set, NULL, NULL, NULL)) { + case -1: + if (EINTR == errno) + continue; /* termsig check */ + perror("select"); + break; + case 0: + fprintf(stderr,"Huh, select() timeout?\n"); + mdns_pub_appquit++; + break; + default: + break; + } + + if (vec) + free(vec); + vec = xs_read_watch(xenstore, &count); + if (NULL == vec) { + fprintf(stderr,"xs_read_watch() failed\n"); + exit(1); + } + if (2 != sscanf(vec[XS_WATCH_PATH], "/local/domain/%d/%64s", &domid, path)) { + if (1 != sscanf(vec[XS_WATCH_PATH], "/local/domain/%d", &domid)) + continue; + strcpy(path, ""); + } + dom = get_dom(domid); + + if (0 == strcmp(path,"")) { + rc = xenstore_read(xenstore, vec[XS_WATCH_PATH], value, sizeof(value)); + if (0 != rc) + dom->destroyed = 1; + + } else if (0 == strcmp(path, "name")) { + rc = xenstore_read(xenstore, vec[XS_WATCH_PATH], value, sizeof(value)); + if (0 != rc) + continue; + strcpy(dom->name, value); + mdns_log_printf(mdns, LOG_INFO, "new: %s (%d)\n", dom->name, dom->domid); + + } else if (0 == strcmp(path, "console/vnc-port")) { + rc = xenstore_read(xenstore, vec[XS_WATCH_PATH], value, sizeof(value)); + if (0 != rc) + continue; + dom->vnc_port = atoi(value); + + } else { + continue; + + } + + try_attach_domain(mdns, dom, 0); + try_release_domain(mdns, dom); + } + + mdns_pub_del_all(mdns); + mdns_pub_stop(mdns); + mdns_pub_fini(mdns); + return 0; +} |