diff options
author | kraxel <kraxel> | 2006-04-07 15:38:39 +0000 |
---|---|---|
committer | kraxel <kraxel> | 2006-04-07 15:38:39 +0000 |
commit | 87fcf49941e76d58934b143a1b1441f263323c12 (patch) | |
tree | d67644a0f4ffda122cec12d02af6f31e2b06437a /mdns.c | |
parent | b6b64172f31759d9aa2a9f40438c8ab09f0f9a98 (diff) | |
download | xenwatch-87fcf49941e76d58934b143a1b1441f263323c12.tar.gz |
mdns hacking
Diffstat (limited to 'mdns.c')
-rw-r--r-- | mdns.c | 193 |
1 files changed, 160 insertions, 33 deletions
@@ -21,6 +21,7 @@ #endif #include "list.h" +#include "apps.h" #include "mdns.h" #ifdef HAVE_AVAHI @@ -28,6 +29,52 @@ static int debug = 0; /* ---------------------------------------------------------------------- */ +/* build URLs */ + +struct protocols { + char *type; + char *proto; + int defport; +}; + +static const struct protocols protocols[] = { + { "_ftp._tcp", "ftp", 21 }, + { "_ssh._tcp", "ssh", 22 }, + { "_http._tcp", "http", 80 }, + { "_rfb._tcp", "vnc", -1 }, +}; + +/* ---------------------------------------------------------------------- */ +/* start apps */ + +struct actions { + enum desktop_type desktop; + char *type; + char *tryapp; + char *cmdline; + int needurl:1; +}; + +static const struct actions default_actions[] = { + { + /* let KDE decide how to handle it ... */ + .desktop = DESKTOP_KDE, + .needurl = 1, + .tryapp = "kfmclient", + .cmdline = "kfmclient exec %u", + },{ + .desktop = DESKTOP_ANY, + .type = "_ssh._tcp", + .cmdline = "xterm -title \"%n\" -e ssh -p %p \"%h\"", + },{ + .desktop = DESKTOP_ANY, + .type = "_rfb._tcp", + .tryapp = "vncviewer", + .cmdline = "vncviewer %h::%p", + } +}; + +/* ---------------------------------------------------------------------- */ enum { /* browse */ @@ -60,6 +107,13 @@ static int str_sort[] = { ST_COL_HOSTNAME, }; +struct mdns_browser { + char *service; + char *domain; + AvahiServiceBrowser *sb; + struct list_head next; +}; + struct mdns_window { GtkListStore *store; GtkWidget *toplevel, *view, *status; @@ -69,7 +123,7 @@ struct mdns_window { const AvahiPoll *poll_api; AvahiGLibPoll *glib_poll; AvahiClient *client; - AvahiServiceBrowser *sb; + struct list_head browser; }; /* ---------------------------------------------------------------------- */ @@ -202,14 +256,6 @@ static void resolve_callback(AvahiServiceResolver *r, AvahiLookupResultFlags flags, void* userdata) { - static const struct { - char *type; - char *proto; - int defport; - } protos[] = { - { "_http._tcp", "http", 80 }, - { "_ftp._tcp", "ftp", 21 }, - }; struct mdns_window *mdns = userdata; char a[AVAHI_ADDRESS_STR_MAX], p[32], url[256]; unsigned char *txtstr, *path = NULL; @@ -266,15 +312,17 @@ static void resolve_callback(AvahiServiceResolver *r, } /* url */ - for (i = 0; i < sizeof(protos)/sizeof(protos[0]); i++) { - if (0 != strcmp(protos[i].type, type)) + for (i = 0; i < array_size(protocols); i++) { + if (0 != strcmp(protocols[i].type, type)) continue; - proto = protos[i].proto; - defport = protos[i].defport; + proto = protocols[i].proto; + defport = protocols[i].defport; break; } - if (!proto || !path) + if (!proto) break; + if (!path) + path = (unsigned char*)""; if (defport != port) snprintf(url, sizeof(url), "%s://%s:%d%s", proto, host_name, port, path); @@ -463,6 +511,7 @@ static int mdns_init(struct mdns_window *mdns) &error); if (mdns->client == NULL) goto fail; + INIT_LIST_HEAD(&mdns->browser); if (0) dump_stuff(mdns); @@ -473,32 +522,55 @@ fail: return -1; } -int mdns_browse(struct mdns_window *mdns, +int mdns_browse(struct mdns_window *mdns, int replace, const char *service, const char *domain) { + struct list_head *item, *tmp; + struct mdns_browser *br; char label[256]; - - if (mdns->sb) { - avahi_service_browser_free(mdns->sb); - mdns->sb = NULL; + int pos; + + if (NULL == domain) + domain = avahi_client_get_domain_name(mdns->client); + + if (replace) { + /* zap old browsers and entries */ + list_for_each_safe(item, tmp, &mdns->browser) { + br = list_entry(item, struct mdns_browser, next); + avahi_service_browser_free(br->sb); + list_del(&br->next); + free(br->domain); + free(br->service); + free(br); + } del_entries(mdns); gtk_label_set_text(GTK_LABEL(mdns->status), "idle"); } - if (NULL == domain) - domain = avahi_client_get_domain_name(mdns->client); - mdns->sb = avahi_service_browser_new(mdns->client, - AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, - service, domain, 0, - browse_callback, mdns); - if (NULL == mdns->sb) { + /* allocate new one */ + br = malloc(sizeof(*br)); + memset(br,0,sizeof(*br)); + br->sb = avahi_service_browser_new(mdns->client, + AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, + service, domain, 0, + browse_callback, mdns); + if (NULL == br->sb) { fprintf(stderr, "%s: failed to create service browser: %s\n", __FUNCTION__, avahi_strerror(avahi_client_errno(mdns->client))); + free(br); return -1; } - snprintf(label, sizeof(label), - "service \"%s\" in domain \"%s\"", - service, domain); + br->service = strdup(service); + br->domain = strdup(domain); + list_add_tail(&br->next,&mdns->browser); + + /* update status line */ + pos = 0; + list_for_each_safe(item, tmp, &mdns->browser) { + br = list_entry(item, struct mdns_browser, next); + pos += snprintf(label+pos, sizeof(label)-pos, + "%s%s", pos ? ", " : "", br->service); + } gtk_label_set_text(GTK_LABEL(mdns->status), label); return 0; } @@ -610,6 +682,63 @@ static void destroy(GtkWidget *widget, /* ---------------------------------------------------------------------- */ +static int run_actions(const struct actions *actions, int nactions, + char *name, char *type, char *host, char *port, + char *url) +{ + int i; + + for (i = 0; i < nactions; i++) { + if (actions[i].desktop != DESKTOP_ANY && + actions[i].desktop != desktop_type) + continue; + if (actions[i].type && 0 != strcmp(actions[i].type, type)) + continue; + if (actions[i].tryapp && !have_application(actions[i].tryapp)) + continue; + if (actions[i].needurl && NULL == url) + continue; + run_cmdline_replace(0, actions[i].cmdline, + "%n", name, + "%t", type, + "%h", host, + "%p", port, + "%u", url, + NULL); + return 0; + } + return -1; +} + +static void row_activate(GtkTreeView* treeview, + GtkTreePath *path, + GtkTreeViewColumn* col, + gpointer data) +{ +// struct mdns_window *mdns = data; + GtkTreeModel* model; + GtkTreeIter iter; + char *name, *type, *host, *port, *url; + int rc; + + model = gtk_tree_view_get_model(treeview); + if (!gtk_tree_model_get_iter(model, &iter, path)) + return; + gtk_tree_model_get(model, &iter, + ST_COL_NAME, &name, + ST_COL_TYPE, &type, + ST_COL_HOSTNAME, &host, + ST_COL_PORT, &port, + ST_COL_URL, &url, + -1); + + rc = run_actions(default_actions, array_size(default_actions), + name, type, host, port, url); + /* FIXME: error message if failed */ +} + +/* ---------------------------------------------------------------------- */ + static const GtkActionEntry entries[] = { { .name = "FileMenu", @@ -952,9 +1081,7 @@ struct mdns_window *mdns_create_window(int standalone, enum mdns_view view) G_TYPE_STRING, // ST_COL_XEN_VM_UUID NULL); mdns->view = mdns_create_view(mdns); -#if 0 - g_signal_connect(mdns->view, "row-activated", G_CALLBACK(activate), mdns); -#endif + g_signal_connect(mdns->view, "row-activated", G_CALLBACK(row_activate), mdns); scroll = gtk_scrolled_window_new(NULL, NULL); gtk_scrolled_window_set_policy(GTK_SCROLLED_WINDOW(scroll), GTK_POLICY_NEVER, @@ -1011,7 +1138,7 @@ struct mdns_window *mdns_create_window(int standalone, enum mdns_view view) void mdns_show_window(struct mdns_window *mdns) {} void mdns_destroy_window(struct mdns_window *mdns) {} -int mdns_browse(struct mdns_window *mdns, +int mdns_browse(struct mdns_window *mdns, int replace, const char *service, const char *domain) { return -1; |