aboutsummaryrefslogtreecommitdiffstats
path: root/mdns.c
diff options
context:
space:
mode:
authorkraxel <kraxel>2006-04-07 15:38:39 +0000
committerkraxel <kraxel>2006-04-07 15:38:39 +0000
commit87fcf49941e76d58934b143a1b1441f263323c12 (patch)
treed67644a0f4ffda122cec12d02af6f31e2b06437a /mdns.c
parentb6b64172f31759d9aa2a9f40438c8ab09f0f9a98 (diff)
downloadxenwatch-87fcf49941e76d58934b143a1b1441f263323c12.tar.gz
mdns hacking
Diffstat (limited to 'mdns.c')
-rw-r--r--mdns.c193
1 files changed, 160 insertions, 33 deletions
diff --git a/mdns.c b/mdns.c
index d50fc10..2044590 100644
--- a/mdns.c
+++ b/mdns.c
@@ -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;