summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2007-09-07 23:46:14 +0200
committerLennart Poettering <lennart@poettering.net>2007-09-07 23:46:14 +0200
commit7e2e7661c325718982387c3355d4f929e4025ec7 (patch)
tree79f13b7028a2762889870f9a365c8cdfaacd4c1b
parent3d0b8b888855df89ac535ed1b74a6b2834204865 (diff)
add avahi browsing support
-rw-r--r--Makefile6
-rw-r--r--lassi-avahi.c229
-rw-r--r--lassi-avahi.h29
-rw-r--r--lassi-osd.c3
-rw-r--r--lassi-osd.h3
-rw-r--r--lassi-server.c43
-rw-r--r--lassi-server.h5
7 files changed, 289 insertions, 29 deletions
diff --git a/Makefile b/Makefile
index c21ca57..d4f9749 100644
--- a/Makefile
+++ b/Makefile
@@ -1,7 +1,7 @@
-CFLAGS=-Wall -Wextra -W -O0 -g -pipe -Wno-unused-parameter `pkg-config --cflags dbus-glib-1 glib-2.0 gtk+-2.0 xtst`
-LIBS=`pkg-config --libs dbus-glib-1 glib-2.0 gtk+-2.0 xtst`
+CFLAGS=-Wall -Wextra -W -O0 -g -pipe -Wno-unused-parameter `pkg-config --cflags dbus-glib-1 glib-2.0 gtk+-2.0 xtst avahi-glib avahi-client avahi-ui`
+LIBS=`pkg-config --libs dbus-glib-1 glib-2.0 gtk+-2.0 xtst avahi-glib avahi-client avahi-ui`
-mango-lassi: lassi-server.o lassi-grab.o lassi-osd.o lassi-order.o lassi-clipboard.o *.h
+mango-lassi: lassi-server.o lassi-grab.o lassi-osd.o lassi-order.o lassi-clipboard.o lassi-avahi.o *.h
$(CC) $^ -o $@ $(LIBS) $(CFLAGS)
clean:
diff --git a/lassi-avahi.c b/lassi-avahi.c
new file mode 100644
index 0000000..9fb81c9
--- /dev/null
+++ b/lassi-avahi.c
@@ -0,0 +1,229 @@
+#include <string.h>
+
+#include <avahi-common/error.h>
+#include <avahi-common/alternative.h>
+#include <avahi-glib/glib-malloc.h>
+
+#include "lassi-avahi.h"
+
+#define SERVICE_TYPE "_mango-lassi._tcp"
+
+/* FIXME: Error and collision handling is suboptimal */
+
+static void resolve_cb(
+ AvahiServiceResolver *r,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiResolverEvent event,
+ const char *name,
+ const char *type,
+ const char *domain,
+ const char *host_name,
+ const AvahiAddress *address,
+ uint16_t port,
+ AvahiStringList *txt,
+ AvahiLookupResultFlags flags,
+ void* userdata) {
+
+ LassiAvahiInfo *i = userdata;
+
+ g_assert(r);
+ g_assert(i);
+
+ /* Called whenever a service has been resolved successfully or timed out */
+
+ switch (event) {
+ case AVAHI_RESOLVER_FOUND: {
+ char a[AVAHI_ADDRESS_STR_MAX], *t;
+
+ avahi_address_snprint(a, sizeof(a), address);
+ t = g_strdup_printf("tcp:port=%u,host=%s", port, a);
+ lassi_server_connect(i->server, t);
+ g_free(t);
+ break;
+ }
+
+ case AVAHI_RESOLVER_FAILURE:
+ g_message("Failed to resolve service '%s' of type '%s' in domain '%s': %s", name, type, domain, avahi_strerror(avahi_client_errno(i->client)));
+ break;
+
+ }
+
+ avahi_service_resolver_free(r);
+ }
+
+static void browse_cb(
+ AvahiServiceBrowser *b,
+ AvahiIfIndex interface,
+ AvahiProtocol protocol,
+ AvahiBrowserEvent event,
+ const char *name,
+ const char *type,
+ const char *domain,
+ AvahiLookupResultFlags flags,
+ void* userdata) {
+
+ LassiAvahiInfo *i = userdata;
+
+ g_assert(b);
+ g_assert(i);
+
+ switch (event) {
+ case AVAHI_BROWSER_NEW:
+
+ if (!(flags & AVAHI_LOOKUP_RESULT_OUR_OWN))
+ if (!(avahi_service_resolver_new(i->client, interface, protocol, name, type, domain, AVAHI_PROTO_UNSPEC, 0, resolve_cb, i)))
+ g_message("Failed to resolve service '%s': %s", name, avahi_strerror(avahi_client_errno(i->client)));
+ break;
+
+ case AVAHI_BROWSER_REMOVE:
+ case AVAHI_BROWSER_ALL_FOR_NOW:
+ case AVAHI_BROWSER_CACHE_EXHAUSTED:
+ break;
+
+ case AVAHI_BROWSER_FAILURE:
+ g_message("Browsing failed: %s", avahi_strerror(avahi_client_errno(i->client)));
+ break;
+ }
+}
+
+
+static void create_service(LassiAvahiInfo *i);
+
+static void entry_group_callback(AvahiEntryGroup *g, AvahiEntryGroupState state, void *userdata) {
+ LassiAvahiInfo *i = userdata;
+
+ g_assert(g);
+ g_assert(i);
+
+ i->group = g;
+
+ switch (state) {
+ case AVAHI_ENTRY_GROUP_ESTABLISHED :
+ g_message("Service '%s' successfully established.", i->service_name);
+ break;
+
+ case AVAHI_ENTRY_GROUP_COLLISION : {
+ char *n;
+
+ n = avahi_alternative_service_name(i->service_name);
+ avahi_free(i->service_name);
+ i->service_name = n;
+
+ g_message("Service name collision, renaming service to '%s'", n);
+
+ /* And recreate the services */
+ create_service(i);
+ break;
+ }
+
+ case AVAHI_ENTRY_GROUP_FAILURE :
+ g_message("Entry group failure: %s", avahi_strerror(avahi_client_errno(i->client)));
+ break;
+
+ case AVAHI_ENTRY_GROUP_UNCOMMITED:
+ case AVAHI_ENTRY_GROUP_REGISTERING:
+ ;
+ }
+}
+
+static void create_service(LassiAvahiInfo *i) {
+ g_assert(i);
+
+ if (!i->group)
+ if (!(i->group = avahi_entry_group_new(i->client, entry_group_callback, i))) {
+ g_message("avahi_entry_group_new() failed: %s", avahi_strerror(avahi_client_errno(i->client)));
+ return;
+ }
+
+ if (avahi_entry_group_is_empty(i->group)) {
+ int ret;
+
+ if (!i->service_name)
+ i->service_name = g_strdup(i->server->id);
+
+ if ((ret = avahi_entry_group_add_service(i->group, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, 0, i->service_name, SERVICE_TYPE, NULL, NULL, i->server->port, NULL)) < 0) {
+ g_message("Failed to add service: %s", avahi_strerror(ret));
+ return;
+ }
+
+ if ((ret = avahi_entry_group_commit(i->group)) < 0) {
+ g_message("Failed to commit entry group: %s", avahi_strerror(ret));
+ return;
+ }
+ }
+}
+
+static void client_cb(AvahiClient *client, AvahiClientState state, void *userdata) {
+ LassiAvahiInfo *i = userdata;
+
+ i->client = client;
+
+ switch (state) {
+ case AVAHI_CLIENT_S_RUNNING:
+ if (!i->group)
+ create_service(i);
+ break;
+
+ case AVAHI_CLIENT_FAILURE:
+ g_message("Client failure: %s", avahi_strerror(avahi_client_errno(client)));
+ break;
+
+ case AVAHI_CLIENT_S_COLLISION:
+ case AVAHI_CLIENT_S_REGISTERING:
+ if (i->group)
+ avahi_entry_group_reset(i->group);
+
+ break;
+
+ case AVAHI_CLIENT_CONNECTING:
+ ;
+ }
+}
+
+int lassi_avahi_init(LassiAvahiInfo *i, LassiServer *server) {
+ int error;
+
+ g_assert(i);
+ g_assert(server);
+
+ memset(i, 0, sizeof(*i));
+ i->server = server;
+
+ avahi_set_allocator(avahi_glib_allocator());
+
+ if (!(i->poll = avahi_glib_poll_new(NULL, G_PRIORITY_DEFAULT))) {
+ g_message("avahi_glib_poll_new() failed.");
+ goto fail;
+ }
+
+ if (!(i->client = avahi_client_new(avahi_glib_poll_get(i->poll), 0, client_cb, i, &error))) {
+ g_message("avahi_client_new() failed: %s", avahi_strerror(error));
+ goto fail;
+ }
+
+ if (!(i->browser = avahi_service_browser_new(i->client, AVAHI_IF_UNSPEC, AVAHI_PROTO_UNSPEC, SERVICE_TYPE, NULL, 0, browse_cb, i))) {
+ g_message("avahi_service_browser_new(): %s", avahi_strerror(avahi_client_errno(i->client)));
+ goto fail;
+ }
+
+ return 0;
+
+fail:
+ lassi_avahi_done(i);
+ return -1;
+}
+
+void lassi_avahi_done(LassiAvahiInfo *i) {
+ g_assert(i);
+
+ if (i->client)
+ avahi_client_free(i->client);
+
+ if (i->poll)
+ avahi_glib_poll_free(i->poll);
+
+ g_free(i->service_name);
+
+ memset(i, 0, sizeof(*i));
+}
diff --git a/lassi-avahi.h b/lassi-avahi.h
new file mode 100644
index 0000000..34484db
--- /dev/null
+++ b/lassi-avahi.h
@@ -0,0 +1,29 @@
+#ifndef foolassiavahihfoo
+#define foolassiavahihfoo
+
+#include <avahi-client/client.h>
+#include <avahi-client/publish.h>
+#include <avahi-client/lookup.h>
+#include <avahi-glib/glib-watch.h>
+
+typedef struct LassiAvahiInfo LassiAvahiInfo;
+struct LassiServer;
+
+struct LassiAvahiInfo {
+ struct LassiServer *server;
+
+ AvahiGLibPoll *poll;
+ AvahiClient *client;
+
+ AvahiEntryGroup *group;
+ char *service_name;
+
+ AvahiServiceBrowser *browser;
+};
+
+#include "lassi-server.h"
+
+int lassi_avahi_init(LassiAvahiInfo *i, LassiServer *server);
+void lassi_avahi_done(LassiAvahiInfo *i);
+
+#endif
diff --git a/lassi-osd.c b/lassi-osd.c
index f5824a6..ae9a21c 100644
--- a/lassi-osd.c
+++ b/lassi-osd.c
@@ -7,7 +7,7 @@
#include "lassi-osd.h"
-void lassi_osd_init(LassiOsdInfo *osd) {
+int lassi_osd_init(LassiOsdInfo *osd) {
GtkWidget *hbox;
GdkColor color;
guint32 cardinal;
@@ -66,6 +66,7 @@ void lassi_osd_init(LassiOsdInfo *osd) {
g_debug("WINDOW=%p", osd->window);
+ return 0;
}
void lassi_osd_done(LassiOsdInfo *osd) {
diff --git a/lassi-osd.h b/lassi-osd.h
index 4f3fc1b..2a792eb 100644
--- a/lassi-osd.h
+++ b/lassi-osd.h
@@ -9,11 +9,10 @@ struct LassiOsdInfo {
GtkWidget *window, *label, *left_icon, *right_icon;
};
-void lassi_osd_init(LassiOsdInfo *osd);
+int lassi_osd_init(LassiOsdInfo *osd);
void lassi_osd_done(LassiOsdInfo *osd);
void lassi_osd_set_text(LassiOsdInfo *osd, const char *text, const char *icon_name_left, const char *icon_name_right);
void lassi_osd_hide(LassiOsdInfo *osd);
-
#endif
diff --git a/lassi-server.c b/lassi-server.c
index 7a6f56c..7584d95 100644
--- a/lassi-server.c
+++ b/lassi-server.c
@@ -16,16 +16,16 @@
#include "lassi-grab.h"
#include "lassi-order.h"
#include "lassi-clipboard.h"
+#include "lassi-avahi.h"
#define LASSI_INTERFACE "org.gnome.MangoLassi"
-#define PORT_MIN 4000
-#define PORT_MAX 4050
+#define PORT_MIN 7421
+#define PORT_MAX (PORT_MIN + 50)
#define CONNECTIONS_MAX 16
static void server_disconnect_all(LassiServer *ls);
-static LassiConnection* server_connect(LassiServer *ls, const char *a);
static void server_send_update_grab(LassiServer *ls, int y);
static void server_broadcast(LassiServer *ls, DBusMessage *m, LassiConnection *except) {
@@ -720,7 +720,7 @@ static int signal_node_added(LassiConnection *lc, DBusMessage *m) {
if (g_hash_table_lookup(lc->server->connections_by_id, id))
return 0;
- if (!(server_connect(lc->server, address))) {
+ if (!(lassi_server_connect(lc->server, address))) {
DBusMessage *n;
dbus_bool_t b;
@@ -1308,8 +1308,10 @@ static int server_init(LassiServer *ls) {
ls->dbus_server = dbus_server_listen(t, &e);
g_free(t);
- if (ls->dbus_server)
+ if (ls->dbus_server) {
+ ls->port = port;
break;
+ }
if (!dbus_error_has_name(&e, DBUS_ERROR_ADDRESS_IN_USE)) {
g_warning("Failed to create D-Bus server: %s %s", e.message, e.name);
@@ -1331,13 +1333,21 @@ static int server_init(LassiServer *ls) {
ls->connections_by_id = g_hash_table_new(g_str_hash, g_str_equal);
- ls->id = g_strdup_printf("%u", getpid());
+ ls->id = g_strdup_printf("%s's desktop on %s", g_get_user_name(), g_get_host_name());
ls->address = dbus_server_get_address(ls->dbus_server);
ls->order = g_list_prepend(NULL, g_strdup(ls->id));
- lassi_grab_init(&ls->grab_info, ls);
- lassi_osd_init(&ls->osd_info);
- lassi_clipboard_init(&ls->clipboard_info, ls);
+ if (lassi_grab_init(&ls->grab_info, ls) < 0)
+ goto finish;
+
+ if (lassi_osd_init(&ls->osd_info) < 0)
+ goto finish;
+
+ if (lassi_clipboard_init(&ls->clipboard_info, ls) < 0)
+ goto finish;
+
+ if (lassi_avahi_init(&ls->avahi_info, ls) < 0)
+ goto finish;
r = 0;
@@ -1378,7 +1388,7 @@ static void server_done(LassiServer *ls) {
memset(ls, 0, sizeof(*ls));
}
-static LassiConnection* server_connect(LassiServer *ls, const char *a) {
+LassiConnection* lassi_server_connect(LassiServer *ls, const char *a) {
DBusError e;
DBusConnection *c;
LassiConnection *lc = NULL;
@@ -1414,19 +1424,6 @@ int main(int argc, char *argv[]) {
if (server_init(&ls) < 0)
goto fail;
- server_connect(&ls, "tcp:port=4000,host=lambda.local");
- server_connect(&ls, "tcp:port=4001,host=lambda.local");
- server_connect(&ls, "tcp:port=4002,host=lambda.local");
- server_connect(&ls, "tcp:port=4003,host=lambda.local");
- server_connect(&ls, "tcp:port=4000,host=ecstasy.local");
- server_connect(&ls, "tcp:port=4001,host=ecstasy.local");
- server_connect(&ls, "tcp:port=4002,host=ecstasy.local");
- server_connect(&ls, "tcp:port=4003,host=ecstasy.local");
- server_connect(&ls, "tcp:port=4000,host=127.0.0.1");
- server_connect(&ls, "tcp:port=4001,host=127.0.0.1");
- server_connect(&ls, "tcp:port=4002,host=127.0.0.1");
- server_connect(&ls, "tcp:port=4003,host=127.0.0.1");
-
gtk_main();
fail:
diff --git a/lassi-server.h b/lassi-server.h
index b8f7dc4..b6117ae 100644
--- a/lassi-server.h
+++ b/lassi-server.h
@@ -10,11 +10,13 @@ typedef struct LassiConnection LassiConnection;
#include "lassi-grab.h"
#include "lassi-osd.h"
#include "lassi-clipboard.h"
+#include "lassi-avahi.h"
struct LassiServer {
DBusServer *dbus_server;
char *id, *address;
+ uint16_t port;
/* All connections */
GList *connections;
@@ -45,6 +47,7 @@ struct LassiServer {
LassiGrabInfo grab_info;
LassiOsdInfo osd_info;
LassiClipboardInfo clipboard_info;
+ LassiAvahiInfo avahi_info;
};
struct LassiConnection {
@@ -67,4 +70,6 @@ int lassi_server_acquire_clipboard(LassiServer *ls, gboolean primary, char**targ
int lassi_server_return_clipboard(LassiServer *ls, gboolean primary);
int lassi_server_get_clipboard(LassiServer *ls, gboolean primary, const char *t, int *f, gpointer *p, int *l);
+LassiConnection* lassi_server_connect(LassiServer *ls, const char *a);
+
#endif