summaryrefslogtreecommitdiffstats
path: root/lassi-server.c
diff options
context:
space:
mode:
authorLennart Poettering <lennart@poettering.net>2007-10-21 17:54:45 +0200
committerLennart Poettering <lennart@poettering.net>2007-10-21 17:54:45 +0200
commit31f26c2915caa6320af74ba73ebf71491ab80fa3 (patch)
tree08ad71473267f9a7d3cf24de044c92d2fef0992c /lassi-server.c
parent02ff678b9ec7f36c9c18fa2c0e6b1f388d0c106e (diff)
Basic autoconfization
Diffstat (limited to 'lassi-server.c')
-rw-r--r--lassi-server.c1554
1 files changed, 0 insertions, 1554 deletions
diff --git a/lassi-server.c b/lassi-server.c
deleted file mode 100644
index f160279..0000000
--- a/lassi-server.c
+++ /dev/null
@@ -1,1554 +0,0 @@
-#include <unistd.h>
-#include <string.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <netinet/tcp.h>
-
-#include <dbus/dbus-glib.h>
-#include <dbus/dbus-glib-lowlevel.h>
-#include <dbus/dbus.h>
-
-#include <gtk/gtk.h>
-
-#include "lassi-server.h"
-#include "lassi-grab.h"
-#include "lassi-order.h"
-#include "lassi-clipboard.h"
-#include "lassi-avahi.h"
-#include "lassi-tray.h"
-
-#define LASSI_INTERFACE "org.gnome.MangoLassi"
-
-#define PORT_MIN 7421
-#define PORT_MAX (PORT_MIN + 50)
-
-#define CONNECTIONS_MAX 16
-
-static void server_disconnect_all(LassiServer *ls, gboolean clear_order);
-static void server_send_update_grab(LassiServer *ls, int y);
-
-static void server_broadcast(LassiServer *ls, DBusMessage *m, LassiConnection *except) {
- GList *i;
-
- g_assert(ls);
- g_assert(m);
-
- for (i = ls->connections; i; i = i->next) {
- dbus_bool_t b;
- LassiConnection *lc = i->data;
- DBusMessage *n;
-
- if (lc == except || !lc->id)
- continue;
-
- n = dbus_message_copy(m);
- g_assert(n);
- b = dbus_connection_send(lc->dbus_connection, n, NULL);
- g_assert(b);
- dbus_message_unref(n);
- }
-}
-
-static void server_layout_changed(LassiServer *ls, int y) {
- g_assert(ls);
-
- g_debug("updating layout");
-
- lassi_grab_enable_triggers(&ls->grab_info, !!ls->connections_left, !!ls->connections_right);
-
- if (ls->active_connection) {
- char *t;
- gboolean to_left = !!g_list_find(ls->connections_left, ls->active_connection);
-
- t = g_strdup_printf("Mouse and keyboard are being redirected to <b>%s</b>, which is located to the <b>%s</b> of this screen.\n"
- "To redirect input back to this screen, press and release both shift keys simultaneously.",
- ls->active_connection->id, to_left ? "left" : "right");
-
- if (to_left)
- lassi_osd_set_text(&ls->osd_info, t, "go-previous", NULL);
- else
- lassi_osd_set_text(&ls->osd_info, t, NULL, "go-next");
-
- lassi_grab_start(&ls->grab_info, to_left);
-
- } else {
- lassi_grab_stop(&ls->grab_info, y);
- lassi_osd_hide(&ls->osd_info);
- }
-}
-
-static void server_set_order(LassiServer *ls, GList *order) {
- GList *l;
- gboolean on_left = TRUE;
- g_assert(ls);
-
- lassi_list_free(ls->order);
- ls->order = order;
-
- g_list_free(ls->connections_left);
- g_list_free(ls->connections_right);
-
- ls->connections_left = ls->connections_right = NULL;
-
- for (l = ls->order; l; l = l->next) {
- LassiConnection *lc;
-
- if (!(lc = g_hash_table_lookup(ls->connections_by_id, l->data))) {
-
- if (strcmp(ls->id, l->data))
- continue;
- }
-
- g_assert(lc || on_left);
-
- if (!lc)
- on_left = FALSE;
- else if (on_left)
- ls->connections_left = g_list_prepend(ls->connections_left, lc);
- else
- ls->connections_right = g_list_prepend(ls->connections_right, lc);
- }
-
- for (l = ls->connections; l; l = l->next) {
- LassiConnection *lc = l->data;
-
- if (!lc->id)
- continue;
-
- if (g_list_find(ls->connections_left, lc))
- continue;
-
- if (g_list_find(ls->connections_right, lc))
- continue;
-
- ls->order = g_list_append(ls->order, lc->id);
- ls->connections_right = g_list_prepend(ls->connections_right, lc);
- }
-
- ls->connections_right = g_list_reverse(ls->connections_right);
- server_layout_changed(ls, -1);
-
- lassi_prefs_update(&ls->prefs_info);
-}
-
-static void server_dump(LassiServer *ls) {
- GList *l;
- int n = 0;
-
- g_assert(ls);
-
- g_debug("BEGIN Current connections:");
-
- g_debug("Displays left of us:");
- for (l = ls->connections_left; l; l = l->next) {
- LassiConnection *lc = l->data;
- if (!lc->id)
- continue;
- g_debug("%2i) %s %s %s", n++, ls->active_connection == lc ? "ACTIVE" : " ", lc->id, lc->address);
- }
-
- g_debug("Displays right of us:");
- for (l = ls->connections_right; l; l = l->next) {
- LassiConnection *lc = l->data;
- if (!lc->id)
- continue;
- g_debug("%2i) %s %s %s", n++, ls->active_connection == lc ? "ACTIVE" : " ", lc->id, lc->address);
- }
-
- if (!ls->active_connection)
- g_debug("We're the active connection");
-
- g_debug("END");
-}
-
-static void connection_destroy(LassiConnection *lc) {
- g_assert(lc);
-
- dbus_connection_flush(lc->dbus_connection);
- dbus_connection_close(lc->dbus_connection);
- dbus_connection_unref(lc->dbus_connection);
- g_free(lc->id);
- g_free(lc->address);
- g_free(lc);
-}
-
-static void server_pick_active_connection(LassiServer *ls) {
- LassiConnection *pick;
- GList *l;
- char *id;
-
- pick = NULL;
- id = ls->id;
-
- for (l = ls->connections; l; l = l->next) {
- LassiConnection *lc = l->data;
-
- if (!lc->id)
- continue;
-
- if (strcmp(lc->id, id) > 0) {
- id = lc->id;
- pick = lc;
- }
- }
-
- ls->active_connection = pick;
-
- server_send_update_grab(ls, -1);
- server_layout_changed(ls, -1);
-}
-
-static void server_send_update_grab(LassiServer *ls, int y) {
- char *active;
- DBusMessage *n;
- dbus_bool_t b;
- gint32 g;
-
- g_assert(ls);
-
- active = ls->active_connection ? ls->active_connection->id : ls->id;
-
- n = dbus_message_new_signal("/", LASSI_INTERFACE, "UpdateGrab");
- g_assert(n);
-
- g = ++ ls->active_generation;
- b = dbus_message_append_args(
- n,
- DBUS_TYPE_INT32, &g,
- DBUS_TYPE_STRING, &active,
- DBUS_TYPE_INT32, &y,
- DBUS_TYPE_INVALID);
- g_assert(b);
-
- server_broadcast(ls, n, NULL);
- dbus_message_unref(n);
-}
-
-static void server_send_update_order(LassiServer *ls, LassiConnection *except) {
- DBusMessage *n;
- dbus_bool_t b;
- gint32 g;
- DBusMessageIter iter, sub;
- GList *l;
-
- g_assert(ls);
-
- n = dbus_message_new_signal("/", LASSI_INTERFACE, "UpdateOrder");
- g_assert(n);
-
- g = ++ ls->order_generation;
- b = dbus_message_append_args(
- n,
- DBUS_TYPE_INT32, &g,
- DBUS_TYPE_INVALID);
- g_assert(b);
-
- dbus_message_iter_init_append(n, &iter);
-
- b = dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING, &sub);
- g_assert(b);
-
- for (l = ls->order; l; l = l->next) {
- b = dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, &l->data);
- g_assert(b);
- }
-
- b = dbus_message_iter_close_container(&iter, &sub);
- g_assert(b);
-
- server_broadcast(ls, n, except);
- dbus_message_unref(n);
-}
-
-int lassi_server_change_grab(LassiServer *ls, gboolean to_left, int y) {
- LassiConnection *lc;
- GList *l;
-
- g_assert(ls);
-
- l = to_left ? ls->connections_left : ls->connections_right;
- lc = l ? l->data : NULL;
-
- if (!lc)
- return -1;
-
- ls->active_connection = lc;
-
- server_send_update_grab(ls, y);
- server_layout_changed(ls, y);
- return 0;
-}
-
-int lassi_server_acquire_grab(LassiServer *ls) {
- g_assert(ls);
-
- ls->active_connection = NULL;
-
- server_send_update_grab(ls, -1);
- server_layout_changed(ls, -1);
- return 0;
-}
-
-int lassi_server_motion_event(LassiServer *ls, int dx, int dy) {
- DBusMessage *n;
- dbus_bool_t b;
-
- g_assert(ls);
-
- if (!ls->active_connection)
- return -1;
-
- n = dbus_message_new_signal("/", LASSI_INTERFACE, "MotionEvent");
- g_assert(n);
-
- b = dbus_message_append_args(n, DBUS_TYPE_INT32, &dx, DBUS_TYPE_INT32, &dy, DBUS_TYPE_INVALID);
- g_assert(b);
-
- b = dbus_connection_send(ls->active_connection->dbus_connection, n, NULL);
- g_assert(b);
-
- dbus_message_unref(n);
-
- dbus_connection_flush(ls->active_connection->dbus_connection);
-
- return 0;
-}
-
-int lassi_server_button_event(LassiServer *ls, unsigned button, gboolean is_press) {
- DBusMessage *n;
- dbus_bool_t b;
-
- if (!ls->active_connection)
- return -1;
-
- n = dbus_message_new_signal("/", LASSI_INTERFACE, "ButtonEvent");
- g_assert(n);
-
- b = dbus_message_append_args(n, DBUS_TYPE_UINT32, &button, DBUS_TYPE_BOOLEAN, &is_press, DBUS_TYPE_INVALID);
- g_assert(b);
-
- b = dbus_connection_send(ls->active_connection->dbus_connection, n, NULL);
- g_assert(b);
-
- dbus_message_unref(n);
-
- dbus_connection_flush(ls->active_connection->dbus_connection);
-
- return 0;
-}
-
-int lassi_server_key_event(LassiServer *ls, unsigned key, gboolean is_press) {
- DBusMessage *n;
- dbus_bool_t b;
-
- if (!ls->active_connection)
- return -1;
-
- n = dbus_message_new_signal("/", LASSI_INTERFACE, "KeyEvent");
- g_assert(n);
-
- b = dbus_message_append_args(n, DBUS_TYPE_UINT32, &key, DBUS_TYPE_BOOLEAN, &is_press, DBUS_TYPE_INVALID);
- g_assert(b);
-
- b = dbus_connection_send(ls->active_connection->dbus_connection, n, NULL);
- g_assert(b);
-
- dbus_message_unref(n);
-
- dbus_connection_flush(ls->active_connection->dbus_connection);
-
- return 0;
-}
-
-static void show_welcome(LassiConnection *lc, gboolean connect) {
- gboolean to_left;
- LassiServer *ls;
- char *summary, *body;
-
- g_assert(lc);
-
- ls = lc->server;
- to_left = !!g_list_find(ls->connections_left, lc);
-
- if (connect) {
- summary = g_strdup_printf("%s now shares input with this desktop", lc->id);
- body = g_strdup_printf("You're now sharing keyboard and mouse with <b>%s</b> which is located to the <b>%s</b>.", lc->id, to_left ? "left" : "right");
- } else {
- summary = g_strdup_printf("%s no longer shares input with this desktop", lc->id);
- body = g_strdup_printf("You're no longer sharing keyboard and mouse with <b>%s</b> which was located to the <b>%s</b>.", lc->id, to_left ? "left" : "right");
- }
-
- lassi_tray_show_notification(&ls->tray_info, summary, body, to_left ? LASSI_TRAY_NOTIFICATION_LEFT : LASSI_TRAY_NOTIFICATION_RIGHT);
-
- g_free(summary);
- g_free(body);
-}
-
-static void connection_unlink(LassiConnection *lc, gboolean remove_from_order) {
- LassiServer *ls;
- g_assert(lc);
-
- g_debug("Unlinking %s (%s)", lc->id, lc->address);
-
- ls = lc->server;
-
- if (lc->id) {
- DBusMessage *n;
- dbus_bool_t b;
-
- /* Tell everyone */
- n = dbus_message_new_signal("/", LASSI_INTERFACE, "NodeRemoved");
- g_assert(n);
-
- b = dbus_message_append_args(n,
- DBUS_TYPE_STRING, &lc->id,
- DBUS_TYPE_STRING, &lc->address,
- DBUS_TYPE_BOOLEAN, &remove_from_order,
- DBUS_TYPE_INVALID);
- g_assert(b);
-
- server_broadcast(ls, n, NULL);
- dbus_message_unref(n);
- }
-
- ls->connections = g_list_remove(ls->connections, lc);
- ls->n_connections --;
-
- if (lc->id) {
- show_welcome(lc, FALSE);
-
- g_hash_table_remove(ls->connections_by_id, lc->id);
- ls->connections_left = g_list_remove(ls->connections_left, lc);
- ls->connections_right = g_list_remove(ls->connections_right, lc);
-
- if (ls->active_connection == lc)
- server_pick_active_connection(ls);
-
- if (ls->clipboard_connection == lc) {
- ls->clipboard_connection = NULL;
- ls->clipboard_empty = TRUE;
- lassi_clipboard_clear(&lc->server->clipboard_info, FALSE);
- }
-
- if (ls->primary_connection == lc) {
- ls->primary_connection = NULL;
- ls->primary_empty = TRUE;
- lassi_clipboard_clear(&lc->server->clipboard_info, TRUE);
- }
-
- if (remove_from_order) {
- GList *i = g_list_find_custom(ls->order, lc->id, (GCompareFunc) strcmp);
-
- if (i)
- ls->order = g_list_delete_link(ls->order, i);
- }
-
- server_layout_changed(ls, -1);
- lassi_prefs_update(&ls->prefs_info);
- server_dump(ls);
- }
-
- lassi_tray_update(&ls->tray_info, ls->n_connections);
-
- connection_destroy(lc);
-}
-
-static void server_position_connection(LassiServer *ls, LassiConnection *lc) {
- GList *l;
- LassiConnection *last = NULL;
-
- g_assert(ls);
- g_assert(lc);
-
- g_assert(!g_list_find(ls->connections_left, lc));
- g_assert(!g_list_find(ls->connections_right, lc));
-
- for (l = ls->order; l; l = l->next) {
- LassiConnection *k;
-
- if (strcmp(l->data, lc->id) == 0)
- break;
-
- if ((k = g_hash_table_lookup(ls->connections_by_id, l->data)))
- last = k;
- }
-
- if (l) {
- /* OK, We found a spot to add this */
-
- if (last) {
- GList *j;
-
- /*Ok, this one belongs to the right of 'last' */
-
- if ((j = g_list_find(ls->connections_left, last)))
- /* This one belongs in the left list */
- ls->connections_left = g_list_insert_before(ls->connections_left, j, lc);
- else {
- /* This one belongs in the rightlist */
- ls->connections_right = g_list_reverse(ls->connections_right);
- j = g_list_find(ls->connections_right, last);
- g_assert(j);
- ls->connections_right = g_list_insert_before(ls->connections_right, j, lc);
- ls->connections_right = g_list_reverse(ls->connections_right);
- }
- } else
- /* Hmm, this is before the left end */
- ls->connections_left = g_list_append(ls->connections_left, lc);
- } else {
- ls->order = g_list_append(ls->order, g_strdup(lc->id));
- /* No spot found, let's add it to the right end */
- ls->connections_right = g_list_append(ls->connections_right, lc);
- }
-}
-
-int lassi_server_acquire_clipboard(LassiServer *ls, gboolean primary, char**targets) {
- DBusMessageIter iter, sub;
- DBusMessage *n;
- gint32 g;
- gboolean b;
-
- g_assert(ls);
- g_assert(targets);
-
- if (primary) {
- ls->primary_empty = FALSE;
- ls->primary_connection = NULL;
- } else {
- ls->clipboard_empty = FALSE;
- ls->clipboard_connection = NULL;
- }
-
- n = dbus_message_new_signal("/", LASSI_INTERFACE, "AcquireClipboard");
- g_assert(n);
-
- if (primary)
- g = ++ ls->primary_generation;
- else
- g = ++ ls->clipboard_generation;
-
- b = dbus_message_append_args(n, DBUS_TYPE_INT32, &g, DBUS_TYPE_BOOLEAN, &primary, DBUS_TYPE_INVALID);
- g_assert(b);
-
- dbus_message_iter_init_append(n, &iter);
-
- b = dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_STRING_AS_STRING, &sub);
- g_assert(b);
-
- for (; *targets; targets++) {
- g_debug("Exporting target %s", *targets);
- b = dbus_message_iter_append_basic(&sub, DBUS_TYPE_STRING, targets);
- g_assert(b);
- }
-
- b = dbus_message_iter_close_container(&iter, &sub);
- g_assert(b);
-
- server_broadcast(ls, n, NULL);
- g_assert(b);
-
- dbus_message_unref(n);
- return 0;
-}
-
-int lassi_server_return_clipboard(LassiServer *ls, gboolean primary) {
- DBusMessage *n;
- guint32 g;
- gboolean b;
-
- g_assert(ls);
-
- if (primary) {
-
- if (ls->primary_empty || ls->primary_connection != NULL)
- return -1;
-
- ls->primary_empty = TRUE;
- ls->primary_connection = NULL;
-
- } else {
-
- if (ls->clipboard_empty || ls->clipboard_connection != NULL)
- return -1;
-
- ls->clipboard_empty = TRUE;
- ls->clipboard_connection = NULL;
- }
-
- n = dbus_message_new_signal("/", LASSI_INTERFACE, "ReturnClipboard");
- g_assert(n);
-
- if (primary)
- g = ++ ls->primary_generation;
- else
- g = ++ ls->clipboard_generation;
-
- b = dbus_message_append_args(n, DBUS_TYPE_UINT32, &g, DBUS_TYPE_BOOLEAN, &primary, DBUS_TYPE_INVALID);
- g_assert(b);
-
- server_broadcast(ls, n, NULL);
-
- dbus_message_unref(n);
- return 0;
-}
-
-int lassi_server_get_clipboard(LassiServer *ls, gboolean primary, const char *t, int *f, gpointer *p, int *l) {
- DBusMessage *n, *reply;
- DBusConnection *c;
- DBusError e;
- int ret = -1;
- DBusMessageIter iter, sub;
- gboolean b;
-
- g_assert(ls);
-
- dbus_error_init(&e);
-
- if (primary) {
-
- if (ls->primary_empty || !ls->primary_connection)
- return -1;
-
- c = ls->primary_connection->dbus_connection;
-
- } else {
-
- if (ls->clipboard_empty || !ls->clipboard_connection)
- return -1;
-
- c = ls->clipboard_connection->dbus_connection;
- }
-
- n = dbus_message_new_method_call(NULL, "/", LASSI_INTERFACE, "GetClipboard");
- g_assert(n);
-
- b = dbus_message_append_args(n, DBUS_TYPE_BOOLEAN, &primary, DBUS_TYPE_STRING, &t, DBUS_TYPE_INVALID);
- g_assert(b);
-
- if (!(reply = dbus_connection_send_with_reply_and_block(c, n, -1, &e))) {
- g_debug("Getting clipboard failed: %s", e.message);
- goto finish;
- }
-
- dbus_message_iter_init(reply, &iter);
- dbus_message_iter_get_basic(&iter, f);
- dbus_message_iter_next(&iter);
-
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY || dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_BYTE) {
- g_debug("Invalid clipboard data");
- goto finish;
- }
-
- dbus_message_iter_recurse(&iter, &sub);
- dbus_message_iter_get_fixed_array(&sub, p, l);
-
- *p = g_memdup(*p, *l);
-
- ret = 0;
-
-finish:
-
- dbus_message_unref(n);
-
- if (reply)
- dbus_message_unref(reply);
-
- dbus_error_free(&e);
-
- return ret;
-}
-
-static int signal_hello(LassiConnection *lc, DBusMessage *m) {
- const char *id, *address;
- DBusError e;
- GList *i;
- dbus_bool_t b;
- DBusMessage *n;
- gint32 active_generation, order_generation, clipboard_generation;
-
- dbus_error_init(&e);
-
- if (lc->id) {
- g_debug("Received duplicate HelloNode.");
- return -1;
- }
-
- if (!(dbus_message_get_args(
- m, &e,
- DBUS_TYPE_STRING, &id,
- DBUS_TYPE_STRING, &address,
- DBUS_TYPE_INT32, &active_generation,
- DBUS_TYPE_INT32, &order_generation,
- DBUS_TYPE_INT32, &clipboard_generation,
- DBUS_TYPE_INVALID))) {
- g_debug("Received invalid message: %s", e.message);
- dbus_error_free(&e);
- return -1;
- }
-
- if (strcmp(id, lc->server->id) == 0) {
- g_debug("Dropping looped back connection.");
- return -1;
- }
-
- if (g_hash_table_lookup(lc->server->connections_by_id, id)) {
- g_debug("Dropping duplicate connection.");
- return -1;
- }
-
- lc->server->active_generation = MAX(lc->server->active_generation, active_generation);
- lc->server->order_generation = MAX(lc->server->order_generation, order_generation);
- lc->server->clipboard_generation = MAX(lc->server->clipboard_generation, clipboard_generation);
-
- g_debug("Got welcome from %s (%s)", id, address);
-
- lc->id = g_strdup(id);
- lc->address = g_strdup(address);
- g_hash_table_insert(lc->server->connections_by_id, lc->id, lc);
- server_position_connection(lc->server, lc);
-
- /* Notify all old nodes of the new one */
- n = dbus_message_new_signal("/", LASSI_INTERFACE, "NodeAdded");
- g_assert(n);
-
- b = dbus_message_append_args(n, DBUS_TYPE_STRING, &id, DBUS_TYPE_STRING, &address, DBUS_TYPE_INVALID);
- g_assert(b);
-
- server_broadcast(lc->server, n, lc);
- dbus_message_unref(n);
-
- /* Notify new node about old nodes */
- for (i = lc->server->connections; i; i = i->next) {
- LassiConnection *k = i->data;
- dbus_bool_t b;
-
- if (k == lc || !k->id)
- continue;
-
- n = dbus_message_new_signal("/", LASSI_INTERFACE, "NodeAdded");
- g_assert(n);
-
- b = dbus_message_append_args(n, DBUS_TYPE_STRING, &id, DBUS_TYPE_STRING, &address, DBUS_TYPE_INVALID);
- g_assert(b);
-
- b = dbus_connection_send(lc->dbus_connection, n, NULL);
- g_assert(b);
-
- dbus_message_unref(n);
- }
-
- if (lc->we_are_client) {
- server_send_update_grab(lc->server, -1);
- server_send_update_order(lc->server, NULL);
-
- lc->delayed_welcome = FALSE;
- show_welcome(lc, TRUE);
- } else
- lc->delayed_welcome = TRUE;
-
- server_layout_changed(lc->server, -1);
- lassi_prefs_update(&lc->server->prefs_info);
-
- server_dump(lc->server);
-
- return 0;
-}
-
-static int signal_node_added(LassiConnection *lc, DBusMessage *m) {
- const char *id, *address;
- DBusError e;
-
- dbus_error_init(&e);
-
- if (!(dbus_message_get_args(m, &e, DBUS_TYPE_STRING, &id, DBUS_TYPE_STRING, &address, DBUS_TYPE_INVALID))) {
- g_debug("Received invalid message: %s", e.message);
- dbus_error_free(&e);
- return -1;
- }
-
- if (strcmp(id, lc->server->id) == 0)
- return 0;
-
- if (g_hash_table_lookup(lc->server->connections_by_id, id))
- return 0;
-
- if (!(lassi_server_connect(lc->server, address))) {
- DBusMessage *n;
- dbus_bool_t b;
-
- /* Failed to connnect to this client, tell everyone */
- n = dbus_message_new_signal("/", LASSI_INTERFACE, "NodeRemoved");
- g_assert(n);
-
- b = dbus_message_append_args(n, DBUS_TYPE_STRING, &id, DBUS_TYPE_STRING, &address, DBUS_TYPE_INVALID);
- g_assert(b);
-
- server_broadcast(lc->server, n, NULL);
- dbus_message_unref(n);
- }
-
- return 0;
-}
-
-static int signal_node_removed(LassiConnection *lc, DBusMessage *m) {
- const char *id, *address;
- DBusError e;
- LassiConnection *k;
- gboolean remove_from_order;
- LassiServer *ls;
-
- dbus_error_init(&e);
-
- if (!(dbus_message_get_args(m, &e,
- DBUS_TYPE_STRING, &id,
- DBUS_TYPE_STRING, &address,
- DBUS_TYPE_BOOLEAN, &remove_from_order,
- DBUS_TYPE_INVALID))) {
- g_debug("Received invalid message: %s", e.message);
- dbus_error_free(&e);
- return -1;
- }
-
- if (strcmp(id, lc->server->id) == 0) {
- g_debug("We've been kicked ourselves.");
-
- server_disconnect_all(lc->server, TRUE);
- return 0;
- }
-
- if (remove_from_order) {
- GList *i = g_list_find_custom(ls->order, id, (GCompareFunc) strcmp);
-
- if (i)
- ls->order = g_list_delete_link(ls->order, i);
- }
-
- ls = lc->server;
-
- if ((k = g_hash_table_lookup(lc->server->connections_by_id, id)))
- connection_unlink(k, remove_from_order);
-
- server_broadcast(ls, m, lc == k ? NULL : lc);
-
- return 0;
-}
-
-static int signal_update_grab(LassiConnection *lc, DBusMessage *m) {
- const char*id, *current_id;
- gint32 generation;
- LassiConnection *k = NULL;
- DBusError e;
- int y;
-
- dbus_error_init(&e);
-
- if (!(dbus_message_get_args(
- m, &e,
- DBUS_TYPE_INT32, &generation,
- DBUS_TYPE_STRING, &id,
- DBUS_TYPE_INT32, &y,
- DBUS_TYPE_INVALID))) {
- g_debug("Received invalid message: %s", e.message);
- dbus_error_free(&e);
- return -1;
- }
-
- g_debug("received grab request for %s (%i vs %i)", id, lc->server->active_generation, generation);
-
- if (strcmp(id, lc->server->id) && !(k = g_hash_table_lookup(lc->server->connections_by_id, id))) {
- g_debug("Unknown connection");
- return -1;
- }
-
- if (k == lc->server->active_connection) {
- g_debug("Connection already active");
- return 0;
- }
-
- current_id = lc->server->active_connection ? lc->server->active_connection->id : lc->server->id;
-
- if ((lc->server->active_generation > generation || (lc->server->active_generation == generation && strcmp(current_id, id) > 0))) {
- g_debug("Ignoring request for active connection");
- return 0;
- }
-
- lc->server->active_connection = k;
- lc->server->active_generation = generation;
-
- if (!k)
- g_debug("We're now the active server.");
- else
- g_debug("Connection '%s' activated.", k->id);
-
- server_broadcast(lc->server, m, lc);
- server_layout_changed(lc->server, y);
-
- return 0;
-}
-
-static int signal_update_order(LassiConnection *lc, DBusMessage *m) {
- gint32 generation;
- DBusError e;
- DBusMessageIter iter, sub;
- GList *new_order = NULL, *merged_order = NULL;
- int r = 0;
- int c = 0;
-
- dbus_error_init(&e);
-
- if (!(dbus_message_get_args(
- m, &e,
- DBUS_TYPE_INT32, &generation,
- DBUS_TYPE_INVALID))) {
- g_debug("Received invalid message: %s", e.message);
- dbus_error_free(&e);
- return -1;
- }
-
- dbus_message_iter_init(m, &iter);
- dbus_message_iter_next(&iter);
-
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY || dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRING) {
- g_debug("Bad connection list fo the left");
- return -1;
- }
-
- if (lc->server->order_generation > generation) {
- g_debug("Ignoring request for layout");
- return 0;
- }
-
- dbus_message_iter_recurse(&iter, &sub);
-
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- const char *id;
- dbus_message_iter_get_basic(&sub, &id);
- new_order = g_list_prepend(new_order, g_strdup(id));
- dbus_message_iter_next(&sub);
- }
-
- new_order = g_list_reverse(new_order);
-
- if (!lassi_list_nodups(new_order)) {
- g_debug("Received invalid list.");
- r = -1;
- goto finish;
- }
-
- c = lassi_list_compare(lc->server->order, new_order);
-
- if (c == 0) {
- g_debug("Requested order identical to ours.");
- goto finish;
- }
-
- if (lc->server->order_generation == generation && c > 0) {
- g_debug("Ignoring request for layout 2");
- goto finish;
- }
-
- merged_order = lassi_list_merge(lassi_list_copy(new_order), lc->server->order);
-
- if (lassi_list_compare(lc->server->order, merged_order)) {
- server_set_order(lc->server, merged_order);
- merged_order = NULL;
- }
-
- server_send_update_order(lc->server, lassi_list_compare(lc->server->order, new_order) ? NULL : lc);
-
- lc->server->order_generation = generation;
-
-finish:
-
- lassi_list_free(new_order);
- lassi_list_free(merged_order);
-
- if (lc->delayed_welcome) {
- lc->delayed_welcome = FALSE;
- show_welcome(lc, TRUE);
- }
-
- return r;
-}
-
-static int signal_key_event(LassiConnection *lc, DBusMessage *m) {
- DBusError e;
- guint32 key;
- gboolean is_press;
-
- dbus_error_init(&e);
-
- if (!(dbus_message_get_args(m, &e, DBUS_TYPE_UINT32, &key, DBUS_TYPE_BOOLEAN, &is_press, DBUS_TYPE_INVALID))) {
- g_debug("Received invalid message: %s", e.message);
- dbus_error_free(&e);
- return -1;
- }
-
-/* g_debug("got dbus key %i %i", key, !!is_press); */
- lassi_grab_press_key(&lc->server->grab_info, key, is_press);
-
- return 0;
-}
-
-static int signal_motion_event(LassiConnection *lc, DBusMessage *m) {
- DBusError e;
- int dx, dy;
-
- dbus_error_init(&e);
-
- if (!(dbus_message_get_args(m, &e, DBUS_TYPE_INT32, &dx, DBUS_TYPE_INT32, &dy, DBUS_TYPE_INVALID))) {
- g_debug("Received invalid message: %s", e.message);
- dbus_error_free(&e);
- return -1;
- }
-
-/* g_debug("got dbus motion %i %i", dx, dy); */
- lassi_grab_move_pointer_relative(&lc->server->grab_info, dx, dy);
-
- return 0;
-}
-
-static int signal_button_event(LassiConnection *lc, DBusMessage *m) {
- DBusError e;
- guint32 button;
- gboolean is_press;
-
- dbus_error_init(&e);
-
- if (!(dbus_message_get_args(m, &e, DBUS_TYPE_UINT32, &button, DBUS_TYPE_BOOLEAN, &is_press, DBUS_TYPE_INVALID))) {
- g_debug("Received invalid message: %s", e.message);
- dbus_error_free(&e);
- return -1;
- }
-
-/* g_debug("got dbus button %i %i", button, !!is_press); */
- lassi_grab_press_button(&lc->server->grab_info, button, is_press);
-
- return 0;
-}
-
-static int signal_acquire_clipboard(LassiConnection *lc, DBusMessage *m) {
- DBusError e;
- gint32 g;
- gboolean primary;
- DBusMessageIter iter, sub;
- char **targets;
- unsigned alloc_targets, j;
-
- dbus_error_init(&e);
-
- if (!(dbus_message_get_args(m, &e, DBUS_TYPE_INT32, &g, DBUS_TYPE_BOOLEAN, &primary, DBUS_TYPE_INVALID))) {
- g_debug("Received invalid message: %s", e.message);
- dbus_error_free(&e);
- return -1;
- }
-
- if ((primary ? lc->server->primary_generation : lc->server->clipboard_generation) > g) {
- g_debug("Ignoring request for clipboard.");
- return 0;
- }
-
- /* FIXME, tie break missing */
-
- dbus_message_iter_init(m, &iter);
- dbus_message_iter_next(&iter);
- dbus_message_iter_next(&iter);
-
- if (dbus_message_iter_get_arg_type(&iter) != DBUS_TYPE_ARRAY || dbus_message_iter_get_element_type(&iter) != DBUS_TYPE_STRING) {
- g_debug("Bad target list");
- return -1;
- }
-
- dbus_message_iter_recurse(&iter, &sub);
-
- targets = g_new(char*, alloc_targets = 20);
- j = 0;
-
- while (dbus_message_iter_get_arg_type(&sub) != DBUS_TYPE_INVALID) {
- const char *t;
- dbus_message_iter_get_basic(&sub, &t);
-
- if (j >= alloc_targets) {
- alloc_targets *= 2;
- targets = g_realloc(targets, sizeof(char*) * (alloc_targets+1));
- }
-
- g_assert(j < alloc_targets);
-
- targets[j++] = (char*) t;
- dbus_message_iter_next(&sub);
-
- g_debug("Received target %s on %s", t, lc->id);
- }
-
- targets[j] = NULL;
-
- lassi_clipboard_set(&lc->server->clipboard_info, primary, targets);
-
- g_free(targets);
-
- if (primary) {
- lc->server->primary_connection = lc;
- lc->server->primary_empty = FALSE;
- lc->server->primary_generation = g;
- } else {
- lc->server->clipboard_connection = lc;
- lc->server->clipboard_empty = FALSE;
- lc->server->clipboard_generation = g;
- }
-
- return 0;
-}
-
-static int signal_return_clipboard(LassiConnection *lc, DBusMessage *m) {
- DBusError e;
- gint32 g;
- gboolean primary;
-
- dbus_error_init(&e);
-
- if (!(dbus_message_get_args(m, &e, DBUS_TYPE_INT32, &g, DBUS_TYPE_BOOLEAN, &primary, DBUS_TYPE_INVALID))) {
- g_debug("Received invalid message: %s", e.message);
- dbus_error_free(&e);
- return -1;
- }
-
- if ((primary ? lc->server->primary_generation : lc->server->clipboard_generation) > g) {
- g_debug("Ignoring request for clipboard empty.");
- return 0;
- }
-
- /* FIXME, tie break missing */
-
- lassi_clipboard_clear(&lc->server->clipboard_info, primary);
-
- if (primary) {
- lc->server->primary_connection = NULL;
- lc->server->primary_empty = TRUE;
- lc->server->primary_generation = g;
- } else {
- lc->server->clipboard_connection = NULL;
- lc->server->clipboard_empty = TRUE;
- lc->server->clipboard_generation = g;
- }
-
- return 0;
-}
-
-static int method_get_clipboard(LassiConnection *lc, DBusMessage *m) {
- DBusError e;
- char *type;
- gboolean primary;
- DBusMessage *n = NULL;
- gint32 f;
- gpointer p = NULL;
- int l = 0;
- DBusMessageIter iter, sub;
- gboolean b;
-
- dbus_error_init(&e);
-
- if (!(dbus_message_get_args(m, &e, DBUS_TYPE_BOOLEAN, &primary, DBUS_TYPE_STRING, &type, DBUS_TYPE_INVALID))) {
- g_debug("Received invalid message: %s", e.message);
- dbus_error_free(&e);
- return -1;
- }
-
- if ((primary && (lc->server->primary_connection || lc->server->primary_empty)) ||
- (!primary && (lc->server->clipboard_connection || lc->server->clipboard_empty))) {
- n = dbus_message_new_error(m, LASSI_INTERFACE ".NotOwner", "We're not the clipboard owner");
- goto finish;
- }
-
- if (lassi_clipboard_get(&lc->server->clipboard_info, primary, type, &f, &p, &l) < 0) {
- n = dbus_message_new_error(m, LASSI_INTERFACE ".ClipboardFailure", "Failed to read clipboard data");
- goto finish;
- }
-
- if (l > dbus_connection_get_max_message_size(lc->dbus_connection)*9/10) {
- n = dbus_message_new_error(m, LASSI_INTERFACE ".TooLarge", "Clipboard data too large");
- goto finish;
- }
-
- n = dbus_message_new_method_return(m);
- g_assert(n);
-
- dbus_message_iter_init_append(n, &iter);
- b = dbus_message_iter_append_basic(&iter, DBUS_TYPE_INT32, &f);
- g_assert(b);
-
- b = dbus_message_iter_open_container(&iter, DBUS_TYPE_ARRAY, DBUS_TYPE_BYTE_AS_STRING, &sub);
- g_assert(b);
-
- b = dbus_message_iter_append_fixed_array(&sub, DBUS_TYPE_BYTE, &p, l);
- g_assert(b);
-
- b = dbus_message_iter_close_container(&iter, &sub);
- g_assert(b);
-
-finish:
- g_assert(n);
-
- dbus_connection_send(lc->dbus_connection, n, NULL);
- dbus_message_unref(n);
-
- g_free(p);
-
- return 0;
-}
-
-DBusHandlerResult message_function(DBusConnection *c, DBusMessage *m, void *userdata) {
- DBusError e;
- LassiConnection *lc = userdata;
-
- g_assert(c);
- g_assert(m);
- g_assert(lc);
-
- dbus_error_init(&e);
-
-/* g_debug("[%s] interface=%s, path=%s, member=%s serial=%u", */
-/* lc->id, */
-/* dbus_message_get_interface(m), */
-/* dbus_message_get_path(m), */
-/* dbus_message_get_member(m), */
-/* dbus_message_get_serial(m)); */
-
- if (dbus_message_is_signal(m, DBUS_INTERFACE_LOCAL, "Disconnected"))
- goto fail;
-
- else if (dbus_message_is_signal(m, LASSI_INTERFACE, "Hello")) {
- if (signal_hello(lc, m) < 0)
- goto fail;
-
- } else if (lc->id) {
-
- if (dbus_message_is_signal(m, LASSI_INTERFACE, "NodeAdded")) {
-
- if (signal_node_added(lc, m) < 0)
- goto fail;
-
- } else if (dbus_message_is_signal(m, LASSI_INTERFACE, "NodeRemoved")) {
-
- if (signal_node_removed(lc, m) < 0)
- goto fail;
-
- } else if (dbus_message_is_signal(m, LASSI_INTERFACE, "UpdateGrab")) {
-
- if (signal_update_grab(lc, m) < 0)
- goto fail;
-
- } else if (dbus_message_is_signal(m, LASSI_INTERFACE, "UpdateOrder")) {
-
- if (signal_update_order(lc, m) < 0)
- goto fail;
-
- } else if (dbus_message_is_signal(m, LASSI_INTERFACE, "KeyEvent")) {
-
- if (signal_key_event(lc, m) < 0)
- goto fail;
-
- } else if (dbus_message_is_signal(m, LASSI_INTERFACE, "MotionEvent")) {
-
- if (signal_motion_event(lc, m) < 0)
- goto fail;
-
- } else if (dbus_message_is_signal(m, LASSI_INTERFACE, "ButtonEvent")) {
-
- if (signal_button_event(lc, m) < 0)
- goto fail;
-
- } else if (dbus_message_is_signal(m, LASSI_INTERFACE, "AcquireClipboard")) {
-
- if (signal_acquire_clipboard(lc, m) < 0)
- goto fail;
-
- } else if (dbus_message_is_signal(m, LASSI_INTERFACE, "ReturnClipboard")) {
-
- if (signal_return_clipboard(lc, m) < 0)
- goto fail;
-
- } else if (dbus_message_is_method_call(m, LASSI_INTERFACE, "GetClipboard")) {
-
- if (method_get_clipboard(lc, m) < 0)
- goto fail;
-
- } else
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
- } else
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-
- return DBUS_HANDLER_RESULT_HANDLED;
-
-fail:
-
- dbus_error_free(&e);
-
- connection_unlink(lc, TRUE);
-
- return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
-}
-
-static LassiConnection* connection_add(LassiServer *ls, DBusConnection *c, gboolean we_are_client) {
- LassiConnection *lc;
- dbus_bool_t b;
- DBusMessage *m;
- gint32 ag, og, cg;
- int fd, one = 1;
-
- g_assert(ls);
- g_assert(c);
-
- lc = g_new(LassiConnection, 1);
- lc->dbus_connection = dbus_connection_ref(c);
- lc->server = ls;
- lc->id = lc->address = NULL;
- lc->we_are_client = we_are_client;
- lc->delayed_welcome = FALSE;
- ls->connections = g_list_prepend(ls->connections, lc);
- ls->n_connections++;
-
- dbus_connection_setup_with_g_main(c, NULL);
-
- b = dbus_connection_add_filter(c, message_function, lc, NULL);
- g_assert(b);
-
- m = dbus_message_new_signal("/", LASSI_INTERFACE, "Hello");
- g_assert(m);
-
- ag = ls->active_generation;
- og = ls->order_generation;
- cg = ls->clipboard_generation;
-
- b = dbus_message_append_args(
- m,
- DBUS_TYPE_STRING, &ls->id,
- DBUS_TYPE_STRING, &ls->address,
- DBUS_TYPE_INT32, &ag,
- DBUS_TYPE_INT32, &og,
- DBUS_TYPE_INT32, &cg,
- DBUS_TYPE_INVALID);
- g_assert(b);
-
- fd = -1;
- dbus_connection_get_socket(c, &fd);
- g_assert(fd >= 0);
-
- if (setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &one, sizeof(one)) < 0)
- g_warning("Failed to enable TCP_NODELAY");
-
- b = dbus_connection_send(c, m, NULL);
- g_assert(b);
-
- dbus_message_unref(m);
-
- lassi_tray_update(&ls->tray_info, ls->n_connections);
- return lc;
-}
-
-static void new_connection(DBusServer *s, DBusConnection *c, void *userdata) {
- LassiServer *ls = userdata;
-
- g_assert(s);
- g_assert(c);
-
- if (ls->n_connections >= CONNECTIONS_MAX)
- return;
-
- dbus_connection_set_allow_anonymous(c, TRUE);
- connection_add(ls, c, FALSE);
-}
-
-static int server_init(LassiServer *ls) {
- DBusError e;
- int r = -1;
- guint16 port;
-
- g_assert(ls);
-
- memset(ls, 0, sizeof(*ls));
-
- dbus_error_init(&e);
-
- for (port = PORT_MIN; port < PORT_MAX; port++) {
- char *t;
-
- t = g_strdup_printf("tcp:port=%u,host=0.0.0.0", port);
- ls->dbus_server = dbus_server_listen(t, &e);
- g_free(t);
-
- 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);
- goto finish;
- }
-
- dbus_error_free(&e);
- }
-
- if (!ls->dbus_server) {
- g_warning("All ports blocked.");
- goto finish;
- }
-
- g_debug("Listening on port %u", port);
-
- dbus_server_setup_with_g_main(ls->dbus_server, NULL);
- dbus_server_set_new_connection_function(ls->dbus_server, new_connection, ls, NULL);
-
- ls->connections_by_id = g_hash_table_new(g_str_hash, g_str_equal);
-
- ls->id = g_strdup_printf("%s's desktop on %s", g_get_user_name(), g_get_host_name());
-
- if (lassi_avahi_init(&ls->avahi_info, ls) < 0)
- goto finish;
-
- /* The initialization of Avahi might have changed ls->id! */
-
- ls->address = dbus_server_get_address(ls->dbus_server);
- ls->order = g_list_prepend(NULL, g_strdup(ls->id));
-
- 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_tray_init(&ls->tray_info, ls) < 0)
- goto finish;
-
- if (lassi_prefs_init(&ls->prefs_info, ls) < 0)
- goto finish;
-
- r = 0;
-
-finish:
- dbus_error_free(&e);
- return r;
-}
-
-void lassi_server_disconnect(LassiServer *ls, const char *id, gboolean remove_from_order) {
- LassiConnection *lc;
-
- g_assert(ls);
- g_assert(id);
-
- if ((lc = g_hash_table_lookup(ls->connections_by_id, id)))
- connection_unlink(lc, remove_from_order);
- else if (remove_from_order) {
- GList *i = g_list_find_custom(ls->order, id, (GCompareFunc) strcmp);
-
- if (i)
- ls->order = g_list_delete_link(ls->order, i);
- }
-}
-
-static void server_disconnect_all(LassiServer *ls, gboolean clear_order) {
-
- while (ls->connections)
- connection_unlink(ls->connections->data, clear_order);
-
- if (clear_order) {
- lassi_list_free(ls->order);
- ls->order = NULL;
- }
-}
-
-static void server_done(LassiServer *ls) {
-
- g_assert(ls);
-
- if (ls->dbus_server) {
- dbus_server_disconnect(ls->dbus_server);
- dbus_server_unref(ls->dbus_server);
- }
-
- server_disconnect_all(ls, FALSE);
-
- if (ls->connections_by_id)
- g_hash_table_destroy(ls->connections_by_id);
-
- g_free(ls->id);
- g_free(ls->address);
-
- lassi_list_free(ls->order);
-
- lassi_grab_done(&ls->grab_info);
- lassi_osd_done(&ls->osd_info);
- lassi_clipboard_done(&ls->clipboard_info);
- lassi_avahi_done(&ls->avahi_info);
- lassi_tray_done(&ls->tray_info);
- lassi_prefs_done(&ls->prefs_info);
-
- memset(ls, 0, sizeof(*ls));
-}
-
-gboolean lassi_server_is_connected(LassiServer *ls, const char *id) {
- g_assert(ls);
- g_assert(id);
-
- return strcmp(id, ls->id) == 0 || g_hash_table_lookup(ls->connections_by_id, id);
-}
-
-gboolean lassi_server_is_known(LassiServer *ls, const char *id) {
- g_assert(ls);
- g_assert(id);
-
- return !!g_list_find_custom(ls->order, id, (GCompareFunc) strcmp);
-}
-
-LassiConnection* lassi_server_connect(LassiServer *ls, const char *a) {
- DBusError e;
- DBusConnection *c;
- LassiConnection *lc = NULL;
-
- dbus_error_init(&e);
-
- if (ls->n_connections >= CONNECTIONS_MAX)
- goto finish;
-
- if (!(c = dbus_connection_open_private(a, &e))) {
- g_warning("Failed to connect to client: %s", e.message);
- goto finish;
- }
-
- lc = connection_add(ls, c, TRUE);
-
-finish:
-
- if (c)
- dbus_connection_unref(c);
-
- dbus_error_free(&e);
- return lc;
-}
-
-int main(int argc, char *argv[]) {
- LassiServer ls;
-
- gtk_init(&argc, &argv);
-
- memset(&ls, 0, sizeof(ls));
-
- if (server_init(&ls) < 0)
- goto fail;
-
- gtk_main();
-
-fail:
-
- server_done(&ls);
-
- return 0;
-}