[vino/3] okay. preferences are done now.



commit 58ba9d1331246eaff96838abfb55815c923a91ba
Author: Ryan Lortie <desrt desrt ca>
Date:   Wed Jul 7 21:28:24 2010 -0400

    okay.  preferences are done now.

 capplet/vino-message-box.h  |    2 +-
 capplet/vino-preferences.c  |  196 ++++++++++++++++++++++-------------
 capplet/vino-preferences.ui |    5 +-
 server/vino-dbus-listener.c |  213 ++++++++++---------------------------
 server/vino-main.c          |  243 ++++++++++++++++++++++++++++++++++---------
 server/vino-prefs.c         |   89 ----------------
 server/vino-util.c          |  105 ++++++++++++++++++-
 server/vino-util.h          |    4 +-
 8 files changed, 483 insertions(+), 374 deletions(-)
---
diff --git a/capplet/vino-message-box.h b/capplet/vino-message-box.h
index 0c0714f..409bbe9 100644
--- a/capplet/vino-message-box.h
+++ b/capplet/vino-message-box.h
@@ -46,7 +46,7 @@ struct _VinoMessageBox
   VinoMessageBoxPrivate *priv;
 };
 
-GType vino_message_box_get_type (void) G_GNUC_CONST;
+GType vino_message_box_get_type (void);
 
 GtkWidget	*vino_message_box_new (void);
 
diff --git a/capplet/vino-preferences.c b/capplet/vino-preferences.c
index d62e788..4a440eb 100644
--- a/capplet/vino-preferences.c
+++ b/capplet/vino-preferences.c
@@ -39,7 +39,6 @@ typedef struct
   GtkApplication        parent_instance;
 
   VinoConnectivityInfo *info;
-  VinoMessageBox       *message_box;
 } VinoPreferences;
 
 typedef GtkApplicationClass VinoPreferencesClass;
@@ -48,7 +47,7 @@ static GType vino_preferences_get_type (void);
 G_DEFINE_TYPE (VinoPreferences, vino_preferences, GTK_TYPE_APPLICATION)
 
 
-/* We define two GSettings mappings here:
+/* We define three GSettings mappings here:
  *
  * First, a relatively boring boolean inversion mapping.
  */
@@ -69,8 +68,45 @@ set_inverted (const GValue       *value,
   return g_variant_new_boolean (!g_value_get_boolean (value));
 }
 
+/* Next, one that maps between the array-of-strings list of
+ * authentication mechanisms and a boolean that is FALSE if the 'none'
+ * and TRUE otherwise (ie: for 'vnc' in the list).
+ */
+static gboolean
+get_authtype (GValue   *value,
+              GVariant *variant,
+              gpointer  user_data)
+{
+  GVariantIter iter;
+  const gchar *type;
+
+  g_variant_iter_init (&iter, variant);
+  g_value_set_boolean (value, TRUE);
+
+  while (g_variant_iter_next (&iter, "s", &type))
+    if (strcmp (type, "none") == 0)
+      g_value_set_boolean (value, FALSE);
+
+  return TRUE;
+}
+
+static GVariant *
+set_authtype (const GValue       *value,
+              const GVariantType *type,
+              gpointer            user_data)
+{
+  const gchar *authtype;
+
+  if (g_value_get_boolean (value))
+    authtype = "vnc";
+  else
+    authtype = "none";
 
-/* Next, a somewhat evil mapping for the password setting:
+  return g_variant_new_strv (&authtype, 1);
+}
+
+
+/* Finally, a somewhat evil mapping for the password setting:
  *
  * If the setting is 'keyring' then we load the password from the
  * keyring.  Else, it is assumed to be a base64-encoded string which is
@@ -177,19 +213,21 @@ vino_preferences_dialog_response (GtkWidget *widget,
 }
 
 static void
-vino_preferences_update_message (VinoPreferences *app)
+vino_preferences_info_changed (VinoConnectivityInfo *info,
+                               gpointer              user_data)
 {
+  VinoMessageBox *message_box = VINO_MESSAGE_BOX (user_data);
   gchar *internal_host, *external_host, *avahi_host;
   guint16 internal_port, external_port;
 
-  if (!vino_connectivity_info_get (app->info,
+  if (!vino_connectivity_info_get (info,
                                    &internal_host, &internal_port,
                                    &external_host, &external_port,
                                    &avahi_host))
     {
-      vino_message_box_set_label (app->message_box,
+      vino_message_box_set_label (message_box,
                                   _("Checking the connectivity of this machine..."));
-      vino_message_box_show_image (app->message_box);
+      vino_message_box_show_image (message_box);
 
       return;
     }
@@ -224,49 +262,95 @@ vino_preferences_update_message (VinoPreferences *app)
           g_string_append (url, _(" or "));
           g_string_append_printf (url, "<a href=\"vnc://%s::%d\">%s</a>",
                                   avahi_host, internal_port, avahi_host);
-        }
-
+        } 
       g_string_append_printf (message, _("Others can access your computer "
                                          "using the address %s."), url->str);
 
-      vino_message_box_set_label (app->message_box, message->str);
+      vino_message_box_set_label (message_box, message->str);
       g_string_free (message, TRUE);
       g_string_free (url, TRUE);
     }
   else
-    vino_message_box_set_label (app->message_box,
+    vino_message_box_set_label (message_box,
                                 _("Nobody can access your desktop."));
 
-  vino_message_box_hide_image (app->message_box);
+  vino_message_box_hide_image (message_box);
 
   g_free (internal_host);
   g_free (external_host);
   g_free (avahi_host);
 }
 
-static void
-vino_preferences_finalize (GObject *object)
+static GtkWindow *
+vino_preferences_connect_ui (VinoPreferences *app,
+                             GtkBuilder      *builder)
 {
-  VinoPreferences *app = (VinoPreferences *) object;
+  struct {
+    const gchar             *setting;
+    const gchar             *name;
+    const gchar             *property;
+    GSettingsBindFlags       flags;
+    GSettingsBindGetMapping  get_mapping;
+    GSettingsBindSetMapping  set_mapping;
+  } bindings[] = {
+    { "enabled",                "allowed_toggle",        "active"                                                           },
+
+    { "enabled",                "control_settings",      "sensitive",       G_SETTINGS_BIND_GET                             },
+    { "view-only",              "view_only_toggle",      "active",          0,                   get_inverted, set_inverted },
+
+    { "enabled",                "security_settings",     "sensitive",       G_SETTINGS_BIND_GET                             },
+    { "prompt-enabled",         "prompt_enabled_toggle", "active",                                                          },
+    { "authentication-methods", "password_toggle",       "active",          0,                   get_authtype, set_authtype },
+    { "authentication-methods", "password_box",          "sensitive",       G_SETTINGS_BIND_GET, get_authtype               },
+    { "vnc-password",           "password_entry",        "text",            0,                   get_password, set_password },
+    { "use-upnp",               "use_upnp_toggle",       "active",                                                          },
+
+    { "enabled",                "notification_settings", "sensitive",       G_SETTINGS_BIND_GET                             },
+    { "icon-visibility",        "icon_always_radio",     "settings-active",                                                 }
+  };
+  GSettings *settings;
+  gpointer window;
+  gint i;
 
-  g_object_unref (app->info);
+  settings = g_settings_new ("org.gnome.Vino");
 
-  G_OBJECT_CLASS (vino_preferences_parent_class)
-    ->finalize (object);
-}
+  for (i = 0; i < G_N_ELEMENTS (bindings); i++)
+    g_settings_bind_with_mapping (settings, bindings[i].setting,
+                                  gtk_builder_get_object (builder,
+                                                          bindings[i].name),
+                                  bindings[i].property,
+                                  bindings[i].flags,
+                                  bindings[i].get_mapping,
+                                  bindings[i].set_mapping,
+                                  NULL, NULL);
 
+  window = gtk_builder_get_object (builder, "vino_dialog");
+  g_signal_connect (window, "response",
+                    G_CALLBACK (vino_preferences_dialog_response), NULL);
+
+  app->info = vino_connectivity_info_new (gdk_screen_get_number (gtk_window_get_screen (window)));
+  g_signal_connect (app->info, "changed",
+                    G_CALLBACK (vino_preferences_info_changed),
+                    gtk_builder_get_object (builder, "message"));
+  vino_preferences_info_changed (app->info,
+                                 gtk_builder_get_object (builder, "message"));
+
+  g_object_unref (settings);
+  g_object_unref (builder);
+
+  return window;
+}
 
 static GtkWindow *
 vino_preferences_create_window (GtkApplication *gtk_app)
 {
   VinoPreferences *app = (VinoPreferences *) gtk_app;
   GError     *error = NULL;
-  GSettings  *settings;
   GtkBuilder *builder;
   const char *ui_file;
-  gpointer    window;
 
   vino_radio_button_get_type ();
+  vino_message_box_get_type ();
 
 #define VINO_UI_FILE "vino-preferences.ui"
   if (g_file_test (VINO_UI_FILE, G_FILE_TEST_EXISTS))
@@ -278,63 +362,23 @@ vino_preferences_create_window (GtkApplication *gtk_app)
   builder = gtk_builder_new ();
   if (!gtk_builder_add_from_file (builder, ui_file, &error))
     {
-      g_warning ("Unable to locate ui file '%s'", ui_file);
+      g_warning ("Unable to load ui file '%s': %s", ui_file, error->message);
       g_error_free (error);
-      return FALSE;
+      return NULL;
     }
 
-  settings = g_settings_new ("org.gnome.Vino");
-
-  g_settings_bind (settings, "enabled",
-                   gtk_builder_get_object (builder, "control_settings"),
-                   "sensitive", G_SETTINGS_BIND_GET);
-
-  g_settings_bind (settings, "enabled",
-                   gtk_builder_get_object (builder, "security_settings"),
-                   "sensitive", G_SETTINGS_BIND_GET);
-
-  g_settings_bind (settings, "enabled",
-                   gtk_builder_get_object (builder, "notification_settings"),
-                   "sensitive", G_SETTINGS_BIND_GET);
-
-  g_settings_bind (settings, "enabled",
-                   gtk_builder_get_object (builder, "allowed_toggle"),
-                   "active", 0);
-
-  g_settings_bind_with_mapping (settings, "view-only",
-                                gtk_builder_get_object (builder,
-                                                        "view_only_toggle"),
-                                "active", 0,
-                                get_inverted, set_inverted, NULL, NULL);
-
-  g_settings_bind_with_mapping (settings, "vnc-password",
-                                gtk_builder_get_object (builder,
-                                                        "password_entry"),
-                                "text", 0,
-                                get_password, set_password, NULL, NULL);
-
-  g_settings_bind (settings, "icon-visibility",
-                   gtk_builder_get_object (builder, "icon_always_radio"),
-                   "settings-active", 0);
-
-
-  window = gtk_builder_get_object (builder, "vino_dialog");
-  g_signal_connect (window, "response",
-                    G_CALLBACK (vino_preferences_dialog_response), NULL);
-
+  return vino_preferences_connect_ui (app, builder);
+}
 
-  app->info = vino_connectivity_info_new (gdk_screen_get_number (gtk_window_get_screen (window)));
-  g_signal_connect_swapped (app->info, "changed",
-                            G_CALLBACK (vino_preferences_update_message), app);
-  app->message_box = VINO_MESSAGE_BOX (vino_message_box_new ());
-  gtk_widget_show (GTK_WIDGET (app->message_box));
-  gtk_container_add (GTK_CONTAINER (gtk_builder_get_object (builder, "event_box")),
-                     GTK_WIDGET (app->message_box));
-  vino_preferences_update_message (app);
+static void
+vino_preferences_finalize (GObject *object)
+{
+  VinoPreferences *app = (VinoPreferences *) object;
 
-  g_object_unref (builder);
+  g_object_unref (app->info);
 
-  return window;
+  G_OBJECT_CLASS (vino_preferences_parent_class)
+    ->finalize (object);
 }
 
 static void
@@ -352,13 +396,17 @@ vino_preferences_class_init (GtkApplicationClass *class)
 }
 
 static GtkApplication *
-vino_preferences_new (void)
+vino_preferences_new (gint argc, char **argv)
 {
   GError *error = NULL;
   GtkApplication *app;
+  const gchar **args;
+
+  args = (const gchar **) argv;
 
   app = g_initable_new (vino_preferences_get_type (), NULL, &error,
                         "application-id", "org.gnome.Vino.Preferences",
+                        "argv", g_variant_new_bytestring_array (args, argc),
                         NULL);
 
   if G_UNLIKELY (app == NULL)
@@ -377,7 +425,7 @@ main (int argc, char **argv)
   textdomain (GETTEXT_PACKAGE);
 
   gtk_init (&argc, &argv);
-  app = vino_preferences_new ();
+  app = vino_preferences_new (argc, argv);
   gtk_application_get_window (app);
   gtk_application_run (app);
   g_object_unref (app);
diff --git a/capplet/vino-preferences.ui b/capplet/vino-preferences.ui
index a01f697..fa1f582 100644
--- a/capplet/vino-preferences.ui
+++ b/capplet/vino-preferences.ui
@@ -165,11 +165,8 @@
                       </packing>
                     </child>
                     <child>
-                      <object class="GtkEventBox" id="event_box">
+                      <object class="VinoMessageBox" id="message">
                         <property name="visible">True</property>
-                        <child>
-                          <placeholder/>
-                        </child>
                       </object>
                       <packing>
                         <property name="position">1</property>
diff --git a/server/vino-dbus-listener.c b/server/vino-dbus-listener.c
index d4d4f11..9c8df97 100644
--- a/server/vino-dbus-listener.c
+++ b/server/vino-dbus-listener.c
@@ -1,7 +1,5 @@
 /*
- * Copyright (C) 2004-2006 William Jon McCann <mccann jhu edu>
- * Copyright (C) 2006 Jonh Wendell <wendell bani com br>
- * Copyright (C) 2007 Mark McLoughlin <markmc skynet ie>
+ * Copyright © 2010 Codethink Limited
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -18,12 +16,7 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
  * 02111-1307, USA.
  *
- * Authors:
- *      William Jon McCann <mccann jhu edu>
- *      Jonh Wendell <wendell bani com br>
- *      Mark McLoughlin <mark skynet ie>
- *
- * Code taken from gnome-screensaver/src/gs-listener-dbus.c
+ * Author: Ryan Lortie <desrt desrt ca>
  */
 
 #include "config.h"
@@ -31,43 +24,15 @@
 #include "vino-dbus-listener.h"
 #include "vino-dbus.h"
 
-#include <stdlib.h>
-#include <stdio.h>
-#include <string.h>
-#include <unistd.h>
-#include <netdb.h>
-#include <sys/socket.h>
-#include <net/if.h>
-#include <arpa/inet.h>
-#include <netinet/in.h>
-
-#include "vino-dbus-error.h"
-
 #ifdef HAVE_TELEPATHY_GLIB
 #include "vino-tube-servers-manager.h"
 #endif
 
 #include "vino-util.h"
-#include "vino-mdns.h"
 #ifdef VINO_ENABLE_HTTP_SERVER
 #include "vino-http.h"
 #endif
 
-#ifdef HAVE_IFADDRS_H
-#include <ifaddrs.h>
-#else
-#include "libvncserver/ifaddr/ifaddrs.h"
-#endif
-
-#ifdef RFC2553
-#define ADDR_FAMILY_MEMBER ss_family
-#else
-#define ADDR_FAMILY_MEMBER sa_family
-#endif
-
-#define VINO_DBUS_BUS_NAME  "org.gnome.Vino"
-
-
 struct _VinoDBusListener
 {
   GObject  parent_instance;
@@ -82,124 +47,44 @@ struct _VinoDBusListener
 typedef GObjectClass VinoDBusListenerClass;
 
 static GType vino_dbus_listener_get_type (void);
+
 G_DEFINE_TYPE (VinoDBusListener, vino_dbus_listener, G_TYPE_OBJECT)
 
-static char *
-get_local_hostname (VinoDBusListener *listener)
+static void
+vino_dbus_listener_finalize (GObject *object)
 {
-  char                *retval, buf[INET6_ADDRSTRLEN];
-  struct ifaddrs      *myaddrs, *ifa; 
-  void                *sin;
-  const char          *server_iface;
-  GHashTable          *ipv4, *ipv6;
-  GHashTableIter      iter;
-  gpointer            key, value;
-
-  retval = NULL;
-  server_iface = vino_server_get_network_interface (listener->server);
-  ipv4 = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
-  ipv6 = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
-
-  getifaddrs (&myaddrs);
-  for (ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
-    {
-      if (ifa->ifa_addr == NULL || ifa->ifa_name == NULL || (ifa->ifa_flags & IFF_UP) == 0)
-	continue;
-
-      switch (ifa->ifa_addr->ADDR_FAMILY_MEMBER)
-	{
-	  case AF_INET:
-	    sin = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
-	    inet_ntop (AF_INET, sin, buf, INET6_ADDRSTRLEN);
-	    g_hash_table_insert (ipv4,
-				 ifa->ifa_name,
-				 g_strdup (buf));
-	    break;
-
-	  case AF_INET6:
-	    sin = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
-	    inet_ntop (AF_INET6, sin, buf, INET6_ADDRSTRLEN);
-	    g_hash_table_insert (ipv6,
-				 ifa->ifa_name,
-				 g_strdup (buf));
-	    break;
-	  default: continue;
-	}
-    }
+  VinoDBusListener *listener = (VinoDBusListener *) object;
 
-  if (server_iface && server_iface[0] != '\0')
-    {
-      if ((retval = g_strdup (g_hash_table_lookup (ipv4, server_iface))))
-	goto the_end;
-      if ((retval = g_strdup (g_hash_table_lookup (ipv6, server_iface))))
-	goto the_end;
-    }
-
-  g_hash_table_iter_init (&iter, ipv4);
-  while (g_hash_table_iter_next (&iter, &key, &value))
-    {
-      if (strncmp (key, "lo", 2) == 0)
-	continue;
-      retval = g_strdup (value);
-      goto the_end;
-    }
-
-  g_hash_table_iter_init (&iter, ipv6);
-  while (g_hash_table_iter_next (&iter, &key, &value))
-    {
-      if (strncmp (key, "lo", 2) == 0)
-	continue;
-      retval = g_strdup (value);
-      goto the_end;
-    }
+  g_object_unref (listener->connection);
+  g_free (listener->path);
+  if (listener->server)
+    g_object_unref (listener->server);
 
-  if ((retval = g_strdup (g_hash_table_lookup (ipv4, "lo"))))
-    goto the_end;
-  if ((retval = g_strdup (g_hash_table_lookup (ipv6, "lo"))))
-    goto the_end;
-
-  the_end:
-  freeifaddrs (myaddrs); 
-  g_hash_table_destroy (ipv4);
-  g_hash_table_destroy (ipv6);
-
-  return retval;
-}
 
 #ifdef HAVE_TELEPATHY_GLIB
-
-static void
-vino_dbus_listener_dispose (GObject *object)
-{
-  VinoDBusListener *listener = VINO_DBUS_LISTENER (object);
-
-  if (listener->priv->manager != NULL)
+  if (listener->manager != NULL)
     {
       g_object_unref (listener->priv->manager);
       listener->priv->manager = NULL;
     }
+#endif
 
-  if (G_OBJECT_CLASS (vino_dbus_listener_parent_class)->dispose)
-    G_OBJECT_CLASS (vino_dbus_listener_parent_class)->dispose (object);
+  G_OBJECT_CLASS (vino_dbus_listener_parent_class)
+    ->finalize (object);
 }
-#endif
 
 static void
 vino_dbus_listener_init (VinoDBusListener *listener)
 {
 #ifdef HAVE_TELEPATHY_GLIB
-  listener->priv->manager = vino_tube_servers_manager_new ();
+  listener->manager = vino_tube_servers_manager_new ();
 #endif
 }
 
 static void
-vino_dbus_listener_class_init (VinoDBusListenerClass *klass)
+vino_dbus_listener_class_init (GObjectClass *class)
 {
-#ifdef HAVE_TELEPATHY_GLIB
-  GObjectClass *object_class = G_OBJECT_CLASS (klass);
-
-  object_class->dispose = vino_dbus_listener_dispose;
-#endif
+  class->finalize = vino_dbus_listener_finalize;
 }
 
 static guint16
@@ -223,12 +108,36 @@ vino_dbus_listener_get_property (GDBusConnection  *connection,
 {
   VinoDBusListener *listener = user_data;
 
+  if (listener->server == NULL)
+    /* We (reasonably) assume that nobody will be doing Vino property
+     * queries during the extremely short period of time between
+     * connecting to the bus and acquiring our well-known name.
+     *
+     * As soon as the well-known name is acquired, GDBus invokes our
+     * name_acquired function (in vino-main.c) and that blocks until all
+     * of the servers have been setup.  That completes before any more
+     * messages (ie: to the well-known name) can be dispatched.
+     *
+     * That means that the only possibility that we see property queries
+     * here without listener->server being set is in the case that the
+     * property is being queried against our unique name (which we
+     * assume won't happen).
+     */
+    {
+      g_warning ("Somebody queried vino server properties "
+                 "(%s, property %s) before unique name was acquired.",
+                 object_path, property_name);
+      return NULL;
+    }
+
   if (strcmp (property_name, "Host") == 0)
     {
       gchar *local_hostname;
+      const gchar *iface;
       GVariant *result;
 
-      local_hostname = get_local_hostname (listener);
+      iface = vino_server_get_network_interface (listener->server);
+      local_hostname = vino_util_get_local_hostname (iface);
       if (local_hostname)
         result = g_variant_new_string (local_hostname);
       else
@@ -266,6 +175,22 @@ vino_dbus_listener_get_property (GDBusConnection  *connection,
     g_assert_not_reached ();
 }
 
+void
+vino_dbus_listener_set_server (VinoDBusListener *listener,
+                               VinoServer       *server)
+{
+  g_return_if_fail (listener->server == NULL);
+  g_return_if_fail (VINO_IS_SERVER (server));
+  g_return_if_fail (listener->screen ==
+                    gdk_screen_get_number (vino_server_get_screen (server)));
+
+  listener->server = g_object_ref (server);
+
+  /* We need not notify for property changes here since we assume that
+   * nobody will have checked properties before now (see large comment
+   * above in get_property()).
+   */
+}
 
 VinoDBusListener *
 vino_dbus_listener_new (gint screen)
@@ -288,25 +213,3 @@ vino_dbus_listener_new (gint screen)
 
   return listener;
 }
-
-
-void
-vino_dbus_listener_set_server (VinoDBusListener *listener,
-                               VinoServer       *server)
-{
-  g_assert (listener->server == NULL);
-  g_assert_cmpint (listener->screen, ==,
-                   gdk_screen_get_number (vino_server_get_screen (server)));
-
-  listener->server = server;
-
-  /* XXX: emit property change signal, watch for more changes
-   */
-}
-
-gboolean
-vino_dbus_request_name (void)
-{
-  g_application_new ("org.gnome.Vino", 0, NULL);
-  return TRUE;
-}
diff --git a/server/vino-main.c b/server/vino-main.c
index cbf5337..16dc1b2 100644
--- a/server/vino-main.c
+++ b/server/vino-main.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2003 Sun Microsystems, Inc.
+ * Copyright © 2010 Codethink Limited
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -19,11 +20,11 @@
  * Authors:
  *      Mark McLoughlin <mark skynet ie>
  *      Jonh Wendell <wendell bani com br>
+ *      Ryan Lortie <desrt desrt ca>
  */
 
-#include <config.h>
+#include "config.h"
 
-#include <glib.h>
 #include <glib/gi18n.h>
 #include <gtk/gtk.h>
 #include <locale.h>
@@ -31,7 +32,6 @@
 #include "vino-input.h"
 #include "vino-mdns.h"
 #include "vino-server.h"
-#include "vino-prefs.h"
 #include "vino-util.h"
 #include "vino-dbus-listener.h"
 #include "eggsmclient.h"
@@ -39,88 +39,235 @@
 #ifdef HAVE_GNUTLS
 #include <gnutls/gnutls.h>
 
-#ifdef GNOME_ENABLE_DEBUG
+# ifdef GNOME_ENABLE_DEBUG
 static void
 vino_debug_gnutls (int         level,
-		   const char *str)
+                   const char *str)
 {
   fputs (str, stderr);
 }
-#endif
+# endif
 #endif /* HAVE_GNUTLS */
 
+typedef struct
+{
+  GSettings         *settings;
+  GdkDisplay        *display;
+  VinoDBusListener **listeners;
+  gint               n_screens;
+  EggSMClient       *sm_client;
+  GMainLoop         *main_loop;
+} VinoApplication;
+
+static void
+enabled_changed (VinoApplication *vino)
+{
+  if (!g_settings_get_boolean (vino->settings, "enabled"))
+    {
+      g_message ("The remote desktop service has been disabled.  Exiting.");
+      g_main_loop_quit (vino->main_loop);
+    }
+}
+
+static void
+bus_acquired (GDBusConnection *connection,
+              const gchar     *name,
+              gpointer         user_data)
+{
+  VinoApplication *vino = user_data;
+  gint i;
+
+  /* Get the listeners on their object paths before we acquire the name.
+   *
+   * This prevents incoming calls to the well-known name from finding
+   * the listeners missing.
+   *
+   * Later (after we acquire the name) we will create the server objects
+   * and register them with the listeners.
+   */
+  vino->display = gdk_display_get_default ();
+  vino->n_screens = gdk_display_get_n_screens (vino->display);
+  vino->listeners = g_new (VinoDBusListener *, vino->n_screens);
+  for (i = 0; i < vino->n_screens; i++)
+    vino->listeners[i] = vino_dbus_listener_new (i);
+}
+
+static void
+name_acquired (GDBusConnection *connection,
+               const gchar     *name,
+               gpointer         user_data)
+{
+  VinoApplication *vino = user_data;
+  gboolean view_only;
+  gint i;
+
+  /* Name is acquired.  Start up the servers and register them with the
+   * listeners.
+   */
+  if ((view_only = !vino_input_init (vino->display)))
+    g_warning (_("Your XServer does not support the XTest extension - "
+                 "remote desktop access will be view-only\n"));
+
+  for (i = 0; i < vino->n_screens; i++)
+    {
+      VinoServer *server;
+
+      /* The server is initially "on-hold" while we set everything up. */
+      server = vino_server_new (gdk_display_get_screen (vino->display,
+                                                        i),
+                                view_only);
+
+      g_settings_bind (vino->settings, "prompt-enabled",
+                       server, "prompt-enabled", G_SETTINGS_BIND_GET);
+
+      /* Only bind to the user's view-only preference if we're not
+       * forced to be view-only by an incapable X server.
+       */
+      if (!view_only)
+        g_settings_bind (vino->settings, "view-only",
+                         server, "view-only", G_SETTINGS_BIND_GET);
+
+      g_settings_bind (vino->settings, "network-interface",
+                       server, "network-interface", G_SETTINGS_BIND_GET);
+      g_settings_bind (vino->settings, "use-alternative-port",
+                       server, "use-alternative-port", G_SETTINGS_BIND_GET);
+      g_settings_bind (vino->settings, "alternative-port",
+                       server, "alternative-port", G_SETTINGS_BIND_GET);
+      g_settings_bind (vino->settings, "authentication-methods",
+                       server, "auth-methods", G_SETTINGS_BIND_GET);
+      g_settings_bind (vino->settings, "require-encryption",
+                       server, "require-encryption", G_SETTINGS_BIND_GET);
+      g_settings_bind (vino->settings, "require-encryption",
+                       server, "require-encryption", G_SETTINGS_BIND_GET);
+      g_settings_bind (vino->settings, "vnc-password",
+                       server, "vnc-password", G_SETTINGS_BIND_GET);
+      g_settings_bind (vino->settings, "lock-screen-on-disconnect",
+                       server, "lock-screen", G_SETTINGS_BIND_GET);
+      g_settings_bind (vino->settings, "disable-background",
+                       server, "disable-background", G_SETTINGS_BIND_GET);
+      g_settings_bind (vino->settings, "use-upnp",
+                       server, "use-upnp", G_SETTINGS_BIND_GET);
+      g_settings_bind (vino->settings, "disable-xdamage",
+                       server, "disable-xdamage", G_SETTINGS_BIND_GET);
+      g_settings_bind (vino->settings, "icon-visibility",
+                       vino_server_get_status_icon (server),
+                       "visibility", G_SETTINGS_BIND_GET);
+
+      vino_dbus_listener_set_server (vino->listeners[i], server);
+      vino_server_set_on_hold (server, FALSE);
+
+      g_object_unref (server);
+    }
+}
+
+static void
+name_lost (GDBusConnection *connection,
+           const gchar     *name,
+           gpointer         user_data)
+{
+  VinoApplication *vino = user_data;
+
+  g_message ("The remote desktop service is already running.  Exiting.");
+  g_main_loop_quit (vino->main_loop);
+}
+
+static void
+sm_quit (VinoApplication *vino)
+{
+  g_main_loop_quit (vino->main_loop);
+}
+
 int
 main (int argc, char **argv)
 {
-  GOptionContext *context;
-  GdkDisplay     *display;
-  gboolean        view_only;
-  int             i, n_screens;
-  GError         *error = NULL;
-  EggSMClient    *client;
+  VinoApplication vino = { 0, };
 
   setlocale (LC_ALL, "");
   bindtextdomain (GETTEXT_PACKAGE, VINO_LOCALEDIR);
   bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
   textdomain (GETTEXT_PACKAGE);
 
-  context = g_option_context_new (_("- VNC Server for GNOME"));
-  g_option_context_add_group (context, gtk_get_option_group (TRUE));
-  g_option_context_add_group (context, egg_sm_client_get_option_group ());
-  g_option_context_parse (context, &argc, &argv, &error);
-  if (error)
+  /* Parse commandline arguments */
+  {
+    GOptionContext *context;
+    GError *error = NULL;
+
+    context = g_option_context_new (_("- VNC Server for GNOME"));
+    g_option_context_add_group (context, gtk_get_option_group (TRUE));
+    g_option_context_add_group (context, egg_sm_client_get_option_group ());
+    if (!g_option_context_parse (context, &argc, &argv, &error))
+      {
+        g_print ("%s\n%s\n", error->message,
+                 _("Run 'vino-server --help' to see a full list of "
+                   "available command line options"));
+        g_error_free (error);
+        return 1;
+      }
+    g_option_context_free (context);
+  }
+
+  /* GSettings */
+  vino.settings = g_settings_new ("org.gnome.Vino");
+  g_signal_connect_swapped (vino.settings, "changed::enabled",
+                            G_CALLBACK (enabled_changed), &vino);
+  if (!g_settings_get_boolean (vino.settings, "enabled"))
     {
-      g_print ("%s\n%s\n",
-	       error->message,
-	       _("Run 'vino-server --help' to see a full list of available command line options"));
-      g_error_free (error);
+      g_warning ("The remote desktop service is not "
+                 "enabled, so it should not be run.");
       return 1;
     }
 
-  client = egg_sm_client_get ();
-  egg_sm_client_set_mode (EGG_SM_CLIENT_MODE_NO_RESTART);
-  g_signal_connect (client, "quit",
-		    G_CALLBACK (gtk_main_quit), NULL);
-
-  vino_setup_debug_flags ();
+  gtk_window_set_default_icon_name ("preferences-desktop-remote-desktop");
+  g_set_application_name (_("GNOME Remote Desktop"));
+  vino.main_loop = g_main_loop_new (NULL, FALSE);
 
-#ifdef HAVE_GNUTLS
 #ifdef GNOME_ENABLE_DEBUG
+  vino_setup_debug_flags ();
+# ifdef HAVE_GNUTLS
   if (_vino_debug_flags & VINO_DEBUG_TLS)
     {
       gnutls_global_set_log_level (10);
       gnutls_global_set_log_function (vino_debug_gnutls);
     }
+# endif /* HAVE_GNUTLS */
 #endif
-#endif /* HAVE_GNUTLS */
 
-  gtk_window_set_default_icon_name ("preferences-desktop-remote-desktop");
-  g_set_application_name (_("GNOME Remote Desktop"));
+  /* Session management */
+  vino.sm_client = egg_sm_client_get ();
+  egg_sm_client_set_mode (EGG_SM_CLIENT_MODE_NO_RESTART);
+  g_signal_connect_swapped (vino.sm_client, "quit",
+                            G_CALLBACK (sm_quit), &vino);
 
-  if (!vino_dbus_request_name ())
-    return 1;
 
-  display = gdk_display_get_default ();
+  /* Start attempting to acquire the bus name.
+   * This starts everything...
+   */
+  g_bus_own_name (G_BUS_TYPE_SESSION, "org.gnome.Vino",
+                  G_BUS_NAME_OWNER_FLAGS_NONE,
+                  bus_acquired, name_acquired, name_lost,
+                  &vino, NULL);
 
-  view_only = FALSE;
-  if (!vino_input_init (display))
-    {
-      g_warning (_("Your XServer does not support the XTest extension - "
-		   "remote desktop access will be view-only\n"));
-      view_only = TRUE;
-    }
 
-  vino_prefs_init (view_only);
+  g_main_loop_run (vino.main_loop);
 
-  n_screens = gdk_display_get_n_screens (display);
-  for (i = 0; i < n_screens; i++)
-    vino_dbus_listener_set_server (vino_dbus_listener_new (i), vino_prefs_create_server (gdk_display_get_screen (display, i)));
 
-  gtk_main ();
+  /* Shutdown */
+  if (vino.listeners)
+    {
+      gint i;
+
+      /* We need to finalize these to ensure
+       * that mdns gets shutdown properly.
+       */
+      for (i = 0; i < vino.n_screens; i++)
+        g_object_unref (vino.listeners[i]);
 
-  vino_mdns_shutdown ();
+      g_free (vino.listeners);
+    }
 
-  vino_prefs_shutdown ();
+  g_main_loop_unref (vino.main_loop);
+  g_object_unref (vino.sm_client);
+  g_object_unref (vino.settings);
 
   return 0;
 }
diff --git a/server/vino-prefs.c b/server/vino-prefs.c
index f6a54df..87d8df0 100644
--- a/server/vino-prefs.c
+++ b/server/vino-prefs.c
@@ -36,9 +36,6 @@
 #include "vino-mdns.h"
 #include "vino-status-icon.h"
 
-#define VINO_PREFS_LOCKFILE               "vino-server.lock"
-
-static GSettings *background_settings = NULL;
 static GSettings *settings       = NULL;
 static gboolean   force_view_only;
 
@@ -51,15 +48,6 @@ vino_prefs_restart_mdns (VinoServer *server,
   vino_mdns_start (vino_server_get_network_interface (server));
 }
 
-static gboolean
-get_inverted_boolean (GValue   *value,
-                      GVariant *variant,
-                      gpointer  user_data)
-{
-  g_value_set_boolean (value, !g_variant_get_boolean (variant));
-  return TRUE;
-}
-
 VinoServer *
 vino_prefs_create_server (GdkScreen *screen)
 {
@@ -116,82 +104,9 @@ vino_prefs_create_server (GdkScreen *screen)
 }
 
 static void
-vino_prefs_restore_background (void)
-{
-  if (g_settings_get_boolean (settings, "disable-background"))
-    g_settings_set_boolean (background_settings, "draw-background", TRUE);
-}
-
-static gchar *
-vino_prefs_lock_filename (void)
-{
-  gchar *dir;
-
-  dir = g_build_filename (g_get_user_data_dir (),
-			 "vino",
-			  NULL);
-  if (!g_file_test (dir, G_FILE_TEST_EXISTS))
-    g_mkdir_with_parents (dir, 0755);
-
-  g_free (dir);
-
-  return g_build_filename (g_get_user_data_dir (),
-			   "vino",
-			    VINO_PREFS_LOCKFILE,
-			    NULL);
-}
-
-static gboolean
-vino_prefs_lock (void)
-{
-  gchar    *lockfile;
-  gboolean  res;
-
-  res = FALSE;
-  lockfile = vino_prefs_lock_filename ();
-
-  if (g_file_test (lockfile, G_FILE_TEST_EXISTS))
-    {
-      dprintf (PREFS, "WARNING: The lock file (%s) already exists\n", lockfile);
-    }
-  else
-    {
-      g_creat (lockfile, 0644);
-      res = TRUE;
-    }
-
-  g_free (lockfile);
-  return res;
-}
-
-static gboolean
-vino_prefs_unlock (void)
-{
-  gchar    *lockfile;
-  gboolean  res;
-
-  res = FALSE;
-  lockfile = vino_prefs_lock_filename ();
-
-  if (!g_file_test (lockfile, G_FILE_TEST_EXISTS))
-    {
-      dprintf (PREFS, "WARNING: Lock file (%s) not found!\n", lockfile);
-    }
-  else
-    {
-      g_unlink (lockfile);
-      res = TRUE;
-    }
-
-  g_free (lockfile);
-  return res;
-}
-
-static void
 vino_prefs_sighandler (int sig)
 {
   g_message (_("Received signal %d, exiting...\n"), sig);
-  vino_prefs_restore_background ();
   vino_mdns_shutdown ();
   vino_prefs_shutdown ();
   exit (0);
@@ -227,10 +142,6 @@ vino_prefs_init (gboolean view_only)
 void
 vino_prefs_shutdown (void)
 {
-  g_object_unref (background_settings);
   g_object_unref (settings);
-  background_settings = NULL;
   settings = NULL;
-
-  vino_prefs_unlock ();
 }
diff --git a/server/vino-util.c b/server/vino-util.c
index d7e39d8..c41f6cb 100644
--- a/server/vino-util.c
+++ b/server/vino-util.c
@@ -1,5 +1,6 @@
 /*
  * Copyright (C) 2003 Sun Microsystems, Inc.
+ * Copyright (C) 2006-2010 Jonh Wendell <wendell bani com br>
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License as
@@ -17,14 +18,37 @@
  * 02111-1307, USA.
  *
  * Authors:
+ *      Jonh Wendell <wendell bani com br>
  *      Mark McLoughlin <mark skynet ie>
  */
 
-#include <config.h>
+#include "config.h"
 
 #include "vino-util.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <netdb.h>
+#include <sys/socket.h>
+#include <net/if.h>
+#include <arpa/inet.h>
+#include <netinet/in.h>
 #include <gtk/gtk.h>
 
+#ifdef HAVE_IFADDRS_H
+#include <ifaddrs.h>
+#else
+#include "libvncserver/ifaddr/ifaddrs.h"
+#endif
+
+#ifdef RFC2553
+#define ADDR_FAMILY_MEMBER ss_family
+#else
+#define ADDR_FAMILY_MEMBER sa_family
+#endif
+
 #ifdef GNOME_ENABLE_DEBUG
 VinoDebugFlags _vino_debug_flags = VINO_DEBUG_NONE;
 
@@ -135,3 +159,82 @@ vino_util_show_error (const gchar *title, const gchar *message, GtkWindow *paren
   gtk_widget_show_all (GTK_WIDGET(d));
 }
 
+gchar *
+vino_util_get_local_hostname (const gchar *server_iface)
+{
+  char                *retval, buf[INET6_ADDRSTRLEN];
+  struct ifaddrs      *myaddrs, *ifa;
+  void                *sin;
+  GHashTable          *ipv4, *ipv6;
+  GHashTableIter      iter;
+  gpointer            key, value;
+
+  retval = NULL;
+  ipv4 = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
+  ipv6 = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
+
+  getifaddrs (&myaddrs);
+  for (ifa = myaddrs; ifa != NULL; ifa = ifa->ifa_next)
+    {
+      if (ifa->ifa_addr == NULL || ifa->ifa_name == NULL || (ifa->ifa_flags & IFF_UP) == 0)
+        continue;
+
+      switch (ifa->ifa_addr->ADDR_FAMILY_MEMBER)
+        {
+          case AF_INET:
+            sin = &((struct sockaddr_in *)ifa->ifa_addr)->sin_addr;
+            inet_ntop (AF_INET, sin, buf, INET6_ADDRSTRLEN);
+            g_hash_table_insert (ipv4,
+                                 ifa->ifa_name,
+                                 g_strdup (buf));
+            break;
+
+          case AF_INET6:
+            sin = &((struct sockaddr_in6 *)ifa->ifa_addr)->sin6_addr;
+            inet_ntop (AF_INET6, sin, buf, INET6_ADDRSTRLEN);
+            g_hash_table_insert (ipv6,
+                                 ifa->ifa_name,
+                                 g_strdup (buf));
+            break;
+          default: continue;
+        }
+    }
+
+  if (server_iface && server_iface[0] != '\0')
+    {
+      if ((retval = g_strdup (g_hash_table_lookup (ipv4, server_iface))))
+        goto the_end;
+      if ((retval = g_strdup (g_hash_table_lookup (ipv6, server_iface))))
+        goto the_end;
+    }
+
+  g_hash_table_iter_init (&iter, ipv4);
+  while (g_hash_table_iter_next (&iter, &key, &value))
+    {
+      if (strncmp (key, "lo", 2) == 0)
+        continue;
+      retval = g_strdup (value);
+      goto the_end;
+    }
+
+  g_hash_table_iter_init (&iter, ipv6);
+  while (g_hash_table_iter_next (&iter, &key, &value))
+    {
+      if (strncmp (key, "lo", 2) == 0)
+        continue;
+      retval = g_strdup (value);
+      goto the_end;
+    }
+
+  if ((retval = g_strdup (g_hash_table_lookup (ipv4, "lo"))))
+    goto the_end;
+  if ((retval = g_strdup (g_hash_table_lookup (ipv6, "lo"))))
+    goto the_end;
+
+  the_end:
+  freeifaddrs (myaddrs);
+  g_hash_table_destroy (ipv4);
+  g_hash_table_destroy (ipv6);
+
+  return retval;
+}
diff --git a/server/vino-util.h b/server/vino-util.h
index 97b0ae3..a93437f 100644
--- a/server/vino-util.h
+++ b/server/vino-util.h
@@ -78,8 +78,6 @@ void vino_setup_debug_flags (void);
 #  define dprintf(args...)
 #endif
 
-#define vino_setup_debug_flags()
-
 #endif /* GNOME_ENABLE_DEBUG */
 
 void  vino_init_stock_items	(void);
@@ -88,6 +86,8 @@ void  vino_util_show_error	(const gchar *title,
 				 const gchar *message,
 				 GtkWindow *parent);
 
+gchar *vino_util_get_local_hostname (const gchar *server_iface);
+
 
 G_END_DECLS
 



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]