vino r1015 - in trunk: . capplet server server/libvncserver server/libvncserver/rfb



Author: jwendell
Date: Fri Dec 12 19:58:32 2008
New Revision: 1015
URL: http://svn.gnome.org/viewvc/vino?rev=1015&view=rev

Log:
2008-11-25  Jorge Pereira  <jorge jorgepereira com br>

	* capplet/vino-preferences.c:
	(vino_preferences_dialog_update_for_allowed),
	(vino_preferences_load_network_interfaces),
	(vino_preferences_dialog_network_interface_update_combox),
	(vino_preferences_dialog_network_interface_notify),
	(vino_preferences_dialog_network_interface_changed),
	(vino_preferences_dialog_setup_network_interface_combox),
	(vino_preferences_dialog_init):
	* capplet/vino-preferences.glade:
	* configure.in:
	* server/libvncserver/main.c: (rfbGetScreen):
	* server/libvncserver/rfb/rfb.h:
	* server/libvncserver/rfbserver.c: (rfbNewClient):
	* server/libvncserver/sockets.c: (rfbInitListenSock),
	(rfbSetAutoPort), (rfbSetPort), (rfbProcessNewConnection),
	(rfbCheckFds), (ListenOnTCPPort), (NewSocketListenTCP),
	(rfbSetNetworkInterface):
	* server/vino-prefs.c: (vino_prefs_network_interface_changed),
	(vino_prefs_create_server), (vino_prefs_init):
	* server/vino-server.c: (vino_server_new_connection_pending),
	(vino_server_init_from_screen), (vino_server_finalize),
	(vino_server_set_property), (vino_server_get_property),
	(vino_server_class_init), (vino_server_get_network_interface),
	(vino_server_set_network_interface):
	* server/vino-server.h:
	* server/vino-server.schemas.in:
	Removed the feature localOnly, added correct support for IPv4 mapped 
	IPv6, and added a new feature to able to set network interface for 
	accept connection. Closes #403183,#403192,#488354.



Modified:
   trunk/ChangeLog
   trunk/capplet/vino-preferences.c
   trunk/capplet/vino-preferences.glade
   trunk/configure.in
   trunk/server/libvncserver/main.c
   trunk/server/libvncserver/rfb/rfb.h
   trunk/server/libvncserver/rfbserver.c
   trunk/server/libvncserver/sockets.c
   trunk/server/vino-prefs.c
   trunk/server/vino-server.c
   trunk/server/vino-server.h
   trunk/server/vino-server.schemas.in

Modified: trunk/capplet/vino-preferences.c
==============================================================================
--- trunk/capplet/vino-preferences.c	(original)
+++ trunk/capplet/vino-preferences.c	Fri Dec 12 19:58:32 2008
@@ -30,6 +30,8 @@
 #include <libintl.h>
 #include <unistd.h>
 #include <netdb.h>
+#include <net/if.h>
+#include <ifaddrs.h>
 #include <gtk/gtk.h>
 #include <glade/glade.h>
 #include <gconf/gconf-client.h>
@@ -52,14 +54,14 @@
 #define VINO_PREFS_VNC_PASSWORD           VINO_PREFS_DIR "/vnc_password"
 #define VINO_PREFS_MAILTO                 VINO_PREFS_DIR "/mailto"
 #define VINO_PREFS_ICON_VISIBILITY        VINO_PREFS_DIR "/icon_visibility"
-#define VINO_PREFS_LOCAL_ONLY             VINO_PREFS_DIR "/local_only"
+#define VINO_PREFS_NETWORK_INTERFACE      VINO_PREFS_DIR "/network_interface"
 #define VINO_PREFS_ENCRYPTION             VINO_PREFS_DIR "/require_encryption"
 #define VINO_PREFS_USE_ALTERNATIVE_PORT   VINO_PREFS_DIR "/use_alternative_port"
 #define VINO_PREFS_ALTERNATIVE_PORT       VINO_PREFS_DIR "/alternative_port"
 #define VINO_PREFS_LOCK_SCREEN            VINO_PREFS_DIR "/lock_screen_on_disconnect"
 #define VINO_PREFS_DISABLE_BACKGROUND     VINO_PREFS_DIR "/disable_background"
 
-#define N_LISTENERS 13
+#define N_LISTENERS                       13
 
 #define VINO_DBUS_BUS_NAME  "org.gnome.Vino"
 #define VINO_DBUS_INTERFACE "org.gnome.VinoScreen"
@@ -82,7 +84,8 @@
   GtkWidget   *icon_always_radio;
   GtkWidget   *icon_client_radio;
   GtkWidget   *icon_never_radio;
-  GtkWidget   *local_only_toggle;
+  GtkWidget   *network_interface_combox;
+  GtkWidget   *network_interface_label;
   GtkWidget   *encryption_toggle;
   GtkWidget   *use_alternative_port_toggle;
   GtkWidget   *alternative_port_entry;
@@ -180,7 +183,8 @@
   gtk_widget_set_sensitive (dialog->icon_always_radio,     allowed);
   gtk_widget_set_sensitive (dialog->icon_client_radio,     allowed);
   gtk_widget_set_sensitive (dialog->icon_never_radio,      allowed);
-  gtk_widget_set_sensitive (dialog->local_only_toggle,     allowed);
+  gtk_widget_set_sensitive (dialog->network_interface_combox, allowed);
+  gtk_widget_set_sensitive (dialog->network_interface_label,  allowed);
   gtk_widget_set_sensitive (dialog->encryption_toggle,     allowed);
   gtk_widget_set_sensitive (dialog->use_alternative_port_toggle, allowed);
   gtk_widget_set_sensitive (dialog->alternative_port_entry,      allowed &&
@@ -189,65 +193,133 @@
   gtk_widget_set_sensitive (dialog->disable_background_toggle,   allowed);
 }
 
-static void
-vino_preferences_dialog_local_only_toggled (GtkToggleButton       *toggle,
-					    VinoPreferencesDialog *dialog)
+static GSList *
+vino_preferences_load_network_interfaces (void)
 {
-  gboolean local_only;
+  struct ifaddrs *myaddrs, *ifa;
+  GSList *list = NULL;
+
+  /* Translators: 'All' means 'All network interfaces' */
+  list = g_slist_append (list, g_strdup (_("All")));
+
+  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;
 
-  local_only = gtk_toggle_button_get_active (toggle);
+      if (ifa->ifa_addr->sa_family == AF_INET || ifa->ifa_addr->sa_family == AF_INET6)
+        {
+          if (g_slist_find_custom (list, ifa->ifa_name, (GCompareFunc)g_strcasecmp) == NULL)
+            {
+              list  = g_slist_append (list, g_strdup (ifa->ifa_name));
+            }
+        }
+    }
 
-  gconf_client_set_bool (dialog->client, VINO_PREFS_LOCAL_ONLY, local_only, NULL);
+  freeifaddrs (myaddrs);
+  return list;
 }
 
 static void
-vino_preferences_dialog_local_only_notify (GConfClient           *client,
-					   guint                  cnx_id,
-					   GConfEntry            *entry,
-					   VinoPreferencesDialog *dialog)
+vino_preferences_dialog_network_interface_update_combox (VinoPreferencesDialog *dialog,
+                                                         const gchar *selected_iface,
+                                                         gboolean first_time)
 {
-  gboolean local_only;
+  GSList *list;
+  gint    i, sel;
+  gchar  *iface_check;
 
-  if (!entry->value || entry->value->type != GCONF_VALUE_BOOL)
-    return;
+  list = vino_preferences_load_network_interfaces ();
 
-  local_only = gconf_value_get_bool (entry->value) != FALSE;
+  if (selected_iface)
+    iface_check = g_strdup (selected_iface);
+  else
+    iface_check = gconf_client_get_string (dialog->client, VINO_PREFS_NETWORK_INTERFACE, NULL);
 
-  if (local_only != gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (dialog->local_only_toggle)))
+  sel = 0;
+  for(i = 0; list; list = list->next, i++)
     {
-      gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->local_only_toggle), local_only);
+      gchar *iface = list->data;
+
+      if (!iface)
+        continue;
+
+      if (first_time)
+	gtk_combo_box_append_text (GTK_COMBO_BOX (dialog->network_interface_combox), iface);
+            
+      if (iface_check && !g_strcasecmp (iface, iface_check))
+	  sel = i;
+
+      g_free (iface);
     }
+
+  gtk_combo_box_set_active (GTK_COMBO_BOX (dialog->network_interface_combox), sel);
+  g_slist_free (list);
+  g_free (iface_check);
 }
 
-static gboolean
-vino_preferences_dialog_setup_local_only_toggle (VinoPreferencesDialog *dialog)
+static void
+vino_preferences_dialog_network_interface_notify (GConfClient           *client,
+                                                  guint                  cnx_id,
+                                                  GConfEntry            *entry,
+                                                  VinoPreferencesDialog *dialog)
 {
-  gboolean local_only;
+  gchar       *old_iface;
+  const gchar *new_iface;
 
-  dialog->local_only_toggle = glade_xml_get_widget (dialog->xml, "local_only_toggle");
-  g_assert (dialog->local_only_toggle != NULL);
+  if (!entry->value || entry->value->type != GCONF_VALUE_STRING)
+    return;
+
+  new_iface = gconf_value_get_string (entry->value);
+  old_iface = gtk_combo_box_get_active_text (GTK_COMBO_BOX (dialog->network_interface_combox));
+
+  if (old_iface && new_iface && g_strcasecmp (old_iface, new_iface) != 0)
+    vino_preferences_dialog_network_interface_update_combox (dialog, new_iface, FALSE);
+
+  g_free (old_iface);
+}
+
+static void
+vino_preferences_dialog_network_interface_changed (gpointer              unused,
+                                                   VinoPreferencesDialog *dialog)
+{
+  gchar *iface;
 
-  local_only = gconf_client_get_bool (dialog->client, VINO_PREFS_LOCAL_ONLY, NULL);
+  iface = gtk_combo_box_get_active_text (GTK_COMBO_BOX (dialog->network_interface_combox));
 
-  gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (dialog->local_only_toggle), local_only);
+  if (g_strcasecmp (iface, _("All")))
+    gconf_client_set_string (dialog->client, VINO_PREFS_NETWORK_INTERFACE, iface, NULL);
+  else
+    gconf_client_set_string (dialog->client, VINO_PREFS_NETWORK_INTERFACE, "", NULL);
+
+  g_free (iface);
+}
+
+static void
+vino_preferences_dialog_setup_network_interface_combox (VinoPreferencesDialog *dialog)
+{
+  dialog->network_interface_combox = glade_xml_get_widget (dialog->xml, "network_interface_combox");
+  dialog->network_interface_label = glade_xml_get_widget (dialog->xml, "network_interface_label");
+  g_assert (dialog->network_interface_combox != NULL);
+  vino_preferences_dialog_network_interface_update_combox (dialog, NULL, TRUE);
 
-  g_signal_connect (dialog->local_only_toggle, "toggled",
-		    G_CALLBACK (vino_preferences_dialog_local_only_toggled), dialog);
+  g_signal_connect (dialog->network_interface_combox, "changed",
+                    G_CALLBACK (vino_preferences_dialog_network_interface_changed), dialog);
 
-  if (!gconf_client_key_is_writable (dialog->client, VINO_PREFS_LOCAL_ONLY, NULL))
+  if (!gconf_client_key_is_writable (dialog->client, VINO_PREFS_NETWORK_INTERFACE, NULL))
     {
-      gtk_widget_set_sensitive (dialog->local_only_toggle, FALSE);
+      gtk_widget_set_sensitive (dialog->network_interface_combox, FALSE);
+      gtk_widget_set_sensitive (dialog->network_interface_label, FALSE);
       gtk_widget_show (dialog->writability_warning);
     }
 
-  dialog->listeners [dialog->n_listeners] = 
-    gconf_client_notify_add (dialog->client,
-			     VINO_PREFS_LOCAL_ONLY,
-			     (GConfClientNotifyFunc) vino_preferences_dialog_local_only_notify,
-			     dialog, NULL, NULL);
+  dialog->listeners [dialog->n_listeners] =
+    gconf_client_notify_add (dialog->client, 
+                VINO_PREFS_NETWORK_INTERFACE,
+                (GConfClientNotifyFunc)vino_preferences_dialog_network_interface_notify,
+                dialog, NULL, NULL);
   dialog->n_listeners++;
-
-  return local_only;
 }
 
 static void
@@ -1450,13 +1522,13 @@
 
   allowed = vino_preferences_dialog_setup_allowed_toggle (dialog);
 
-  vino_preferences_dialog_setup_prompt_enabled_toggle (dialog);
-  vino_preferences_dialog_setup_view_only_toggle      (dialog);
-  vino_preferences_dialog_setup_password_toggle       (dialog);
-  vino_preferences_dialog_setup_password_entry        (dialog);
-  vino_preferences_dialog_setup_icon_visibility       (dialog);
-  vino_preferences_dialog_setup_local_only_toggle     (dialog);
-  vino_preferences_dialog_setup_encryption_toggle     (dialog);
+  vino_preferences_dialog_setup_prompt_enabled_toggle       (dialog);
+  vino_preferences_dialog_setup_view_only_toggle            (dialog);
+  vino_preferences_dialog_setup_password_toggle             (dialog);
+  vino_preferences_dialog_setup_password_entry              (dialog);
+  vino_preferences_dialog_setup_icon_visibility             (dialog);
+  vino_preferences_dialog_setup_network_interface_combox    (dialog);
+  vino_preferences_dialog_setup_encryption_toggle           (dialog);
   vino_preferences_dialog_setup_alternative_port_entry      (dialog);
   vino_preferences_dialog_setup_use_alternative_port_toggle (dialog);
   vino_preferences_dialog_setup_lock_screen_toggle          (dialog);

Modified: trunk/capplet/vino-preferences.glade
==============================================================================
--- trunk/capplet/vino-preferences.glade	(original)
+++ trunk/capplet/vino-preferences.glade	Fri Dec 12 19:58:32 2008
@@ -444,15 +444,39 @@
                             <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
                             <property name="spacing">6</property>
                             <child>
-                              <widget class="GtkCheckButton" id="local_only_toggle">
+                              <widget class="GtkHBox" id="hbox3">
                                 <property name="visible">True</property>
-                                <property name="can_focus">True</property>
-                                <property name="has_tooltip">True</property>
-                                <property name="tooltip" translatable="yes">The server will only accept connections from localhost</property>
-                                <property name="label" translatable="yes">_Only allow local connections</property>
-                                <property name="use_underline">True</property>
-                                <property name="response_id">0</property>
-                                <property name="draw_indicator">True</property>
+                                <property name="events">GDK_POINTER_MOTION_MASK | GDK_POINTER_MOTION_HINT_MASK | GDK_BUTTON_PRESS_MASK | GDK_BUTTON_RELEASE_MASK | GDK_STRUCTURE_MASK</property>
+                                <property name="spacing">6</property>
+                                <child>
+                                  <widget class="GtkLabel" id="network_interface_label">
+                                    <property name="visible">True</property>
+                                    <property name="tooltip" translatable="yes">Which network interface we should listen to.</property>
+                                    <property name="xalign">0</property>
+                                    <property name="label" translatable="yes">_Listen this interface:</property>
+                                    <property name="use_underline">True</property>
+                                    <property name="mnemonic_widget">network_interface_combox</property>
+                                  </widget>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                  </packing>
+                                </child>
+                                <child>
+                                  <widget class="GtkComboBox" id="network_interface_combox">
+                                    <property name="visible">True</property>
+                                    <property name="can_focus">True</property>
+                                    <property name="tearoff_title">Click here to change the network interface!</property>
+                                    <property name="button_sensitivity">GTK_SENSITIVITY_ON</property>
+                                    <property name="items" translatable="yes"></property>
+                                  </widget>
+                                  <packing>
+                                    <property name="expand">False</property>
+                                    <property name="fill">False</property>
+                                    <property name="padding">1</property>
+                                    <property name="position">1</property>
+                                  </packing>
+                                </child>
                               </widget>
                               <packing>
                                 <property name="expand">False</property>
@@ -490,6 +514,7 @@
                                   </widget>
                                   <packing>
                                     <property name="expand">False</property>
+                                    <property name="padding">1</property>
                                     <property name="position">1</property>
                                   </packing>
                                 </child>

Modified: trunk/configure.in
==============================================================================
--- trunk/configure.in	(original)
+++ trunk/configure.in	Fri Dec 12 19:58:32 2008
@@ -257,7 +257,7 @@
 AC_SUBST(LIBZ)
 AC_SUBST(LIBJPEG)
 
-AC_CHECK_HEADERS([netinet/in.h sys/time.h fcntl.h unistd.h sys/socket.h signal.h])
+AC_CHECK_HEADERS([netinet/in.h sys/time.h fcntl.h unistd.h sys/socket.h signal.h ifaddrs.h net/if.h])
 AC_CHECK_FUNCS([gettimeofday])
 
 dnl

Modified: trunk/server/libvncserver/main.c
==============================================================================
--- trunk/server/libvncserver/main.c	(original)
+++ trunk/server/libvncserver/main.c	Fri Dec 12 19:58:32 2008
@@ -320,7 +320,10 @@
    rfbScreen->inetdSock=-1;
 
    rfbScreen->maxFd=0;
-   rfbScreen->rfbListenSock=-1;
+
+   rfbScreen->rfbListenSock[0] = -1;
+   rfbScreen->rfbListenSockTotal = 0;
+   rfbScreen->netIface = NULL;
 
    rfbScreen->desktopName = strdup("LibVNCServer");
    rfbScreen->rfbAlwaysShared = FALSE;

Modified: trunk/server/libvncserver/rfb/rfb.h
==============================================================================
--- trunk/server/libvncserver/rfb/rfb.h	(original)
+++ trunk/server/libvncserver/rfb/rfb.h	Fri Dec 12 19:58:32 2008
@@ -54,6 +54,8 @@
 
 /* end of stuff for autoconf */
 
+#define RFB_MAX_SOCKETLISTEN 8 /* is the max listen by network interface */
+
 struct _rfbClientRec;
 struct _rfbScreenInfo;
 struct rfbCursor;
@@ -114,7 +116,9 @@
     rfbBool autoPort;
     rfbBool localOnly;
     int rfbPort;
-    SOCKET rfbListenSock;
+    SOCKET rfbListenSock[RFB_MAX_SOCKETLISTEN];
+    int rfbListenSockTotal;
+    const char *netIface;
     int maxSock;
     int maxFd;
     fd_set allFds;
@@ -394,9 +398,11 @@
 extern int ReadExact(rfbClientPtr cl, char *buf, int len);
 extern int ReadExactTimeout(rfbClientPtr cl, char *buf, int len,int timeout);
 extern int WriteExact(rfbClientPtr cl, const char *buf, int len);
-extern void rfbProcessNewConnection(rfbScreenInfoPtr rfbScreen);
+extern void rfbProcessNewConnection(rfbScreenInfoPtr rfbScreen, int insock);
 extern void rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec);
-extern int ListenOnTCPPort(int port, rfbBool localOnly);
+extern rfbBool ListenOnTCPPort(rfbScreenInfoPtr rfbScreen, int port, const char *netIface);
+extern rfbBool rfbSetNetworkInterface(rfbScreenInfoPtr rfbScreen, const char *netIface);
+extern int NewSocketListenTCP(struct sockaddr *addr, socklen_t len);
 
 /* rfbserver.c */
 

Modified: trunk/server/libvncserver/rfbserver.c
==============================================================================
--- trunk/server/libvncserver/rfbserver.c	(original)
+++ trunk/server/libvncserver/rfbserver.c	Fri Dec 12 19:58:32 2008
@@ -151,6 +151,7 @@
     socklen_t addrlen = sizeof(addr);
     int i;
     char host[NI_MAXHOST];
+    const char *prt = "unknown";
 
     cl = (rfbClientPtr)calloc(sizeof(rfbClientRec),1);
 
@@ -173,7 +174,12 @@
 
       cl->host = strdup(host);
 
-      rfbLog("Got connection from client %s\n", cl->host);
+      if (addr.ss_family == AF_INET)
+        prt = "IPv4";
+      else if (addr.ss_family == AF_INET6)
+        prt = "IPv6";
+
+      rfbLog("[%s] Got connection from client %s\n", prt, cl->host);
 
       rfbLog("  other clients:\n");
       iterator = rfbGetClientIterator(rfbScreen);

Modified: trunk/server/libvncserver/sockets.c
==============================================================================
--- trunk/server/libvncserver/sockets.c	(original)
+++ trunk/server/libvncserver/sockets.c	Fri Dec 12 19:58:32 2008
@@ -70,6 +70,9 @@
 #endif
 #endif
 
+#include <net/if.h>  // IFF_UP
+#include <ifaddrs.h> // getifaddrs()
+
 #if defined(__linux__) && defined(NEED_TIMEVAL)
 struct timeval 
 {
@@ -135,38 +138,53 @@
 static void
 rfbInitListenSock(rfbScreenInfoPtr rfbScreen)
 {
+    char *netIface = (char*)rfbScreen->netIface;
+    int i;
+
+    if(netIface == NULL || if_nametoindex(netIface) == 0) {
+      if(netIface != NULL)
+        rfbLog("WARNING: This (%s) a invalid network interface, set to all\n", netIface);
+      netIface = NULL;
+    }
+
     if(rfbScreen->autoPort) {
-        int i;
-        rfbLog("Autoprobing TCP port \n");
+      rfbLog("Autoprobing TCP port in (%s) network interface\n",
+            netIface != NULL ? netIface : "all");
 
-        for (i = 5900; i < 6000; i++) {
-            if ((rfbScreen->rfbListenSock = ListenOnTCPPort(i, rfbScreen->localOnly)) >= 0) {
-		rfbScreen->rfbPort = i;
-		break;
-	    }
+      for (i = 5900; i < 6000; i++) {
+        if (ListenOnTCPPort(rfbScreen, i, netIface)) {
+          rfbScreen->rfbPort = i;
+          break;
         }
+      }
 
-        if (i >= 6000) {
-	    rfbLogPerror("Failure autoprobing");
-	    return;
-        }
+      if (i >= 6000) {
+        rfbLogPerror("Failure autoprobing");
+        return;
+      }
+
+      rfbLog("Autoprobing selected port %d\n", rfbScreen->rfbPort);
 
-        rfbLog("Autoprobing selected port %d\n", rfbScreen->rfbPort);
-        FD_ZERO(&(rfbScreen->allFds));
-        FD_SET(rfbScreen->rfbListenSock, &(rfbScreen->allFds));
-        rfbScreen->maxFd = rfbScreen->rfbListenSock;
+      FD_ZERO(&rfbScreen->allFds);
+      for(i=0; i < rfbScreen->rfbListenSockTotal; i++) {
+        FD_SET(rfbScreen->rfbListenSock[i], &rfbScreen->allFds);
+        rfbScreen->maxFd = rfbScreen->rfbListenSock[i];
+      }
     }
-    else if(rfbScreen->rfbPort>0) {
-      rfbLog("Listening for VNC connections on TCP port %d\n", rfbScreen->rfbPort);
+    else if(rfbScreen->rfbPort > 0) {
+      rfbLog("Listening for VNC connections on TCP port %d in (%s) network interface\n", 
+            rfbScreen->rfbPort, netIface != NULL ? netIface : "all");
 
-      if ((rfbScreen->rfbListenSock = ListenOnTCPPort(rfbScreen->rfbPort, rfbScreen->localOnly)) < 0) {
-	rfbLogPerror("ListenOnTCPPort");
-	return;
+      if (!ListenOnTCPPort(rfbScreen, rfbScreen->rfbPort, netIface)) {
+        rfbLogPerror("ListenOnTCPPort");
+        return;
       }
 
-      FD_ZERO(&(rfbScreen->allFds));
-      FD_SET(rfbScreen->rfbListenSock, &(rfbScreen->allFds));
-      rfbScreen->maxFd = rfbScreen->rfbListenSock;
+      FD_ZERO(&rfbScreen->allFds);
+      for(i=0; i < rfbScreen->rfbListenSockTotal; i++) {
+        FD_SET(rfbScreen->rfbListenSock[i], &rfbScreen->allFds);
+        rfbScreen->maxFd = rfbScreen->rfbListenSock[i];
+      }
     }
 }
 
@@ -181,10 +199,15 @@
     if (!rfbScreen->socketInitDone)
 	return;
 
-    if (rfbScreen->rfbListenSock > 0) {
-        FD_CLR(rfbScreen->rfbListenSock, &(rfbScreen->allFds));
-        close(rfbScreen->rfbListenSock);
-        rfbScreen->rfbListenSock = -1;
+    if (rfbScreen->rfbListenSockTotal > 0) {
+        int i;
+
+        for(i=0; i < rfbScreen->rfbListenSockTotal; i++) {
+           FD_CLR(rfbScreen->rfbListenSock[i], &rfbScreen->allFds);
+           close(rfbScreen->rfbListenSock[i]);
+           rfbScreen->rfbListenSock[i] = -1;
+        }
+        rfbScreen->rfbListenSockTotal = 0;
     }
 
     rfbInitListenSock(rfbScreen);
@@ -201,53 +224,35 @@
     if (!rfbScreen->socketInitDone || rfbScreen->autoPort)
 	return;
 
-    if (rfbScreen->rfbListenSock > 0) {
-        FD_CLR(rfbScreen->rfbListenSock, &(rfbScreen->allFds));
-        close(rfbScreen->rfbListenSock);
-        rfbScreen->rfbListenSock = -1;
-    }
-
-    rfbInitListenSock(rfbScreen);
-}
-
-void
-rfbSetLocalOnly(rfbScreenInfoPtr rfbScreen, rfbBool localOnly)
-{
-    if (rfbScreen->localOnly == localOnly)
-        return;
-
-    rfbScreen->localOnly = localOnly;
-
-    if (!rfbScreen->socketInitDone)
-	return;
-
-    if (rfbScreen->rfbListenSock > 0) {
-        FD_CLR(rfbScreen->rfbListenSock, &(rfbScreen->allFds));
-        close(rfbScreen->rfbListenSock);
-        rfbScreen->rfbListenSock = -1;
-    }
-
-    rfbLog("Re-binding socket to listen for %s VNC connections on TCP port %d\n",
-           rfbScreen->localOnly ? "local" : "all", rfbScreen->rfbPort);
+    if (rfbScreen->rfbListenSockTotal > 0) {
+        int i;
 
-    if ((rfbScreen->rfbListenSock = ListenOnTCPPort(rfbScreen->rfbPort, rfbScreen->localOnly)) < 0) {
-	rfbLogPerror("ListenOnTCPPort");
-	return;
+        for(i=0; i < rfbScreen->rfbListenSockTotal; i++) {
+           FD_CLR(rfbScreen->rfbListenSock[i], &rfbScreen->allFds);
+           close(rfbScreen->rfbListenSock[i]);
+           rfbScreen->rfbListenSock[i] = -1;
+        }
+        rfbScreen->rfbListenSockTotal = 0;
     }
 
-    FD_SET(rfbScreen->rfbListenSock, &(rfbScreen->allFds));
-    rfbScreen->maxFd = max(rfbScreen->rfbListenSock, rfbScreen->maxFd);
+    rfbInitListenSock(rfbScreen);
 }
 
 void
-rfbProcessNewConnection(rfbScreenInfoPtr rfbScreen)
+rfbProcessNewConnection(rfbScreenInfoPtr rfbScreen, int insock)
 {
     const int one = 1;
-    int sock;
+    int sock = -1;
+    int i;
+    
+    if((sock = accept(insock, NULL, NULL)) < 0) {
+      rfbLogPerror("rfbCheckFds: accept");
+      return;
+    }
 
-    if ((sock = accept(rfbScreen->rfbListenSock, NULL, NULL)) < 0) {
-	rfbLogPerror("rfbCheckFds: accept");
-	return;
+    if(sock < 0) {
+      rfbLogPerror("rfbCheckFds: accept");
+      return;
     }
 
 #ifndef WIN32
@@ -258,8 +263,7 @@
     }
 #endif
 
-    if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY,
-		   (char *)&one, sizeof(one)) < 0) {
+    if (setsockopt(sock, IPPROTO_TCP, TCP_NODELAY, (char *)&one, sizeof(one)) < 0) {
 	rfbLogPerror("rfbCheckFds: setsockopt");
 	close(sock);
 	return;
@@ -279,6 +283,7 @@
 rfbCheckFds(rfbScreenInfoPtr rfbScreen,long usec)
 {
     int nfds;
+    int n;
     fd_set fds;
     struct timeval tv;
     rfbClientIteratorPtr i;
@@ -289,7 +294,7 @@
 	rfbScreen->inetdInitDone = TRUE;
     }
 
-    memcpy((char *)&fds, (char *)&(rfbScreen->allFds), sizeof(fd_set));
+    memcpy(&fds, &rfbScreen->allFds, sizeof(fd_set));
     tv.tv_sec = 0;
     tv.tv_usec = usec;
     nfds = select(rfbScreen->maxFd + 1, &fds, NULL, NULL /* &fds */, &tv);
@@ -304,12 +309,14 @@
 		rfbLogPerror("rfbCheckFds: select");
 	return;
     }
-
-    if (rfbScreen->rfbListenSock != -1 && FD_ISSET(rfbScreen->rfbListenSock, &fds)) {
-	rfbProcessNewConnection(rfbScreen);
-	FD_CLR(rfbScreen->rfbListenSock, &fds);
-	if (--nfds == 0)
-	    return;
+    printf("DUMP: nfds = %d\n", nfds);
+    for(n=0; n < rfbScreen->rfbListenSockTotal; n++) {
+        if (rfbScreen->rfbListenSock[n] != -1 && FD_ISSET(rfbScreen->rfbListenSock[n], &fds)) {
+          rfbProcessNewConnection(rfbScreen, rfbScreen->rfbListenSock[n]);
+          FD_CLR(rfbScreen->rfbListenSock[n], &fds);
+          if (--nfds == 0)
+            return;
+        }
     }
 
     i = rfbGetClientIterator(rfbScreen);
@@ -547,57 +554,175 @@
     return 1;
 }
 
-int
-ListenOnTCPPort(port, localOnly)
-    int port;
-    rfbBool localOnly;
+rfbBool
+ListenOnTCPPort(rfbScreenInfoPtr rfbScreen, int port, const char *netIface)
 {
-    int sock = -1;
-    int one = 1;
-    struct sockaddr_in addr_in;
-    struct sockaddr *addr;
-    socklen_t addrlen;
+  int sock   = -1;
+  int *psock = NULL;
+  int *ptot  = NULL;
+  struct ifaddrs *myaddrs = NULL; 
+  struct ifaddrs *ifa     = NULL;
+
+  if(rfbScreen == NULL)
+    return FALSE;
+  
+  psock = rfbScreen->rfbListenSock;
+  ptot  = &rfbScreen->rfbListenSockTotal;
+  *ptot = 0;
 
+  if(netIface == NULL || strlen(netIface) == 0)
+  {
 #ifdef ENABLE_IPV6
-    struct sockaddr_in6 addr_in6;
+    struct sockaddr_in6 s6;
 
-    memset(&addr_in6, 0, sizeof(addr_in6));
-    addr_in6.sin6_family = AF_INET6;
-    addr_in6.sin6_port = htons(port);
-    addr_in6.sin6_addr = localOnly ? in6addr_loopback : in6addr_any;
+    memset(&s6, 0, sizeof(s6));
+    s6.sin6_family = AF_INET6;
+    s6.sin6_port   = htons(port);
+    s6.sin6_addr   = in6addr_any;
 
-    addr = (struct sockaddr *)&addr_in6;
-    addrlen = sizeof(addr_in6);
-
-    sock = socket(AF_INET6, SOCK_STREAM, 0);
+    sock = NewSocketListenTCP ((struct sockaddr*)&s6, sizeof(s6));
+    rfbLog("Listening IPv{4,6}://*:%d\n", port);
 #endif
+    if(sock < 0) {
+      struct sockaddr_in s4;
 
-    if (sock < 0) {
-        if ((sock = socket(AF_INET, SOCK_STREAM, 0)) < 0)
-            return -1;
+      memset(&s4, 0, sizeof(s4));
+      s4.sin_family      = AF_INET;
+      s4.sin_port        = htons(port);
+      s4.sin_addr.s_addr = htonl(INADDR_ANY);
 
-        memset(&addr_in, 0, sizeof(addr_in));
-        addr_in.sin_family = AF_INET;
-        addr_in.sin_port = htons(port);
-        addr_in.sin_addr.s_addr = localOnly ? htonl(INADDR_LOOPBACK) : htonl(INADDR_ANY);
+      sock = NewSocketListenTCP ((struct sockaddr*)&s4, sizeof(s4));
+      rfbLog("Listening IPv4://0.0.0.0:%d\n", port);
+    }
 
-        addr = (struct sockaddr *)&addr_in;
-        addrlen = sizeof(addr_in);
+    if(sock > 0) {
+      psock[0] = sock;
+     *ptot     = 1;
+      return TRUE;
     }
 
-    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR,
-		   (char *)&one, sizeof(one)) < 0) {
-	close(sock);
-	return -1;
+    rfbLog("Problems in NewSocketListenTCP(), sock=%d\n", sock);
+    return FALSE;
+  }
+
+  if(getifaddrs(&myaddrs) != 0) {
+    rfbLogPerror("getifaddrs\n");
+    return FALSE;
+  }
+
+  for (ifa = myaddrs; ifa != NULL && *ptot < RFB_MAX_SOCKETLISTEN; ifa = ifa->ifa_next) {
+    char buf[64] = { 0, };
+
+    if (ifa->ifa_addr == NULL || (ifa->ifa_flags & IFF_UP) == 0) 
+      continue;
+
+    if (ifa->ifa_addr->sa_family == AF_INET) {
+      struct sockaddr_in *s4 = (struct sockaddr_in*)ifa->ifa_addr;
+      s4->sin_port           = htons(port);
+
+      if (inet_ntop(s4->sin_family, (struct sockaddr*)&s4->sin_addr, buf, sizeof(buf)) == NULL) {
+        rfbLog("%s: inet_ntop failed!\n", ifa->ifa_name);
+        continue;
+      }
+      else if(!strcmp(ifa->ifa_name, netIface)) {
+        rfbLog("Listening IPv4://%s:%d\n", buf, port);
+        sock = NewSocketListenTCP((struct sockaddr*)s4, INET_ADDRSTRLEN);
+      }
     }
-    if (bind(sock, addr, addrlen) < 0) {
-	close(sock);
-	return -1;
+#ifdef ENABLE_IPV6            
+    if (ifa->ifa_addr->sa_family == AF_INET6) {
+      struct sockaddr_in6 *s6 = (struct sockaddr_in6*)ifa->ifa_addr;
+      s6->sin6_port           = htons(port);
+
+      if (inet_ntop(ifa->ifa_addr->sa_family, (struct sockaddr*)&s6->sin6_addr, buf, sizeof(buf)) == NULL) {
+        rfbLog("%s: inet_ntop failed!\n", ifa->ifa_name);
+        continue; 
+      }
+      else if(!strcmp(ifa->ifa_name, netIface)) {
+        rfbLog("Listening IPv6://%s:%d\n", buf, port);
+        sock = NewSocketListenTCP((struct sockaddr*)s6, INET6_ADDRSTRLEN);
+      }
+    }
+#endif       
+
+    if(sock > 0) {
+       psock[*ptot] = sock;
+      *ptot        += 1;
+       sock         = -1;
     }
+  }
+
+  freeifaddrs(myaddrs);
+
+  return TRUE;
+}
+
+int
+NewSocketListenTCP(struct sockaddr *addr, socklen_t len)
+{
+    int sock = -1;
+    int one  = 1;
+
+    if ((sock = socket(addr->sa_family, SOCK_STREAM, 0)) < 0)
+      return -1;
+
+    if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof(one)) < 0) {
+      close(sock);
+      return -1;
+    }
+
+    if (bind(sock, addr, len) < 0) {
+      close(sock);
+      return -1;
+    }
+
     if (listen(sock, 5) < 0) {
-	close(sock);
-	return -1;
+      close(sock);
+      return -1;
     }
 
     return sock;
 }
+
+rfbBool
+rfbSetNetworkInterface(rfbScreenInfoPtr rfbScreen, const char *netIface)
+{
+  int i;
+
+  if (!rfbScreen->socketInitDone || !rfbScreen->socketInitDone)
+    return FALSE;
+
+  if(rfbScreen->rfbListenSockTotal > 0) {
+    for(i=0; i < rfbScreen->rfbListenSockTotal; i++) {
+       FD_CLR(rfbScreen->rfbListenSock[i], &(rfbScreen->allFds));
+       close(rfbScreen->rfbListenSock[i]);
+       rfbScreen->rfbListenSock[i] = -1;
+    }
+    rfbScreen->rfbListenSockTotal = 0;
+  }
+
+  if(netIface != NULL && strlen(netIface) > 0 && if_nametoindex(netIface) > 0) {
+     rfbScreen->netIface = netIface;
+  }
+  else {
+     rfbScreen->netIface = NULL;
+     if(netIface != NULL)
+        rfbLog("WARNING: This (%s) a invalid network interface, set to all\n", netIface);
+  }
+
+  rfbLog("Re-binding socket to listen for VNC connections on TCP port %d in (%s) interface\n",
+         rfbScreen->rfbPort, rfbScreen->netIface != NULL ? rfbScreen->netIface : "all");
+ 
+  if (!ListenOnTCPPort(rfbScreen, rfbScreen->rfbPort, rfbScreen->netIface)) {
+    rfbLogPerror("ListenOnTCPPort");
+    return FALSE;
+  }
+
+  for(i=0; i < rfbScreen->rfbListenSockTotal; i++) {
+    FD_SET(rfbScreen->rfbListenSock[i], &(rfbScreen->allFds));
+    rfbScreen->maxFd = max(rfbScreen->rfbListenSock[i], rfbScreen->maxFd);
+  }
+ 
+  return TRUE;
+}
+

Modified: trunk/server/vino-prefs.c
==============================================================================
--- trunk/server/vino-prefs.c	(original)
+++ trunk/server/vino-prefs.c	Fri Dec 12 19:58:32 2008
@@ -37,6 +37,7 @@
 #define VINO_PREFS_PROMPT_ENABLED         VINO_PREFS_DIR "/prompt_enabled"
 #define VINO_PREFS_VIEW_ONLY              VINO_PREFS_DIR "/view_only"
 #define VINO_PREFS_LOCAL_ONLY             VINO_PREFS_DIR "/local_only"
+#define VINO_PREFS_NETWORK_INTERFACE      VINO_PREFS_DIR "/network_interface"
 #define VINO_PREFS_USE_ALTERNATIVE_PORT   VINO_PREFS_DIR "/use_alternative_port"
 #define VINO_PREFS_ALTERNATIVE_PORT       VINO_PREFS_DIR "/alternative_port"
 #define VINO_PREFS_REQUIRE_ENCRYPTION     VINO_PREFS_DIR "/require_encryption"
@@ -46,7 +47,7 @@
 #define VINO_PREFS_ICON_VISIBILITY        VINO_PREFS_DIR "/icon_visibility"
 #define VINO_PREFS_DISABLE_BACKGROUND     VINO_PREFS_DIR "/disable_background"
 
-#define VINO_N_LISTENERS 12
+#define VINO_N_LISTENERS                  12
 
 static GConfClient *vino_client  = NULL;
 static GSList      *vino_servers = NULL;
@@ -55,7 +56,7 @@
 static gboolean        vino_enabled              = FALSE;
 static gboolean        vino_prompt_enabled       = FALSE;
 static gboolean        vino_view_only            = FALSE;
-static gboolean        vino_local_only           = FALSE;
+static char           *vino_network_interface    = NULL;
 static gboolean        vino_require_encryption   = FALSE;
 static VinoAuthMethod  vino_auth_methods         = VINO_AUTH_VNC;
 static char           *vino_vnc_password         = NULL;
@@ -143,27 +144,35 @@
 }
 
 static void
-vino_prefs_local_only_changed (GConfClient *client,
-			       guint	    cnxn_id,
-			       GConfEntry  *entry)
+vino_prefs_network_interface_changed (GConfClient *client,
+                                      guint        cnxn_id,
+                                      GConfEntry  *entry)
 {
-  gboolean  local_only;
-  GSList   *l;
+  const char *network_interface;
+  GSList     *l;
 
-  if (!entry->value || entry->value->type != GCONF_VALUE_BOOL)
+  if (!entry->value || entry->value->type != GCONF_VALUE_STRING)
     return;
 
-  local_only = gconf_value_get_bool (entry->value) != FALSE;
+  network_interface = gconf_value_get_string (entry->value);
 
-  if (vino_local_only == local_only)
+  if (!network_interface && !vino_network_interface)
     return;
 
-  vino_local_only = local_only;
+  if (network_interface && vino_network_interface &&
+      !g_strcasecmp (network_interface, vino_network_interface))
+    return;
+
+  if (vino_network_interface)
+    g_free (vino_network_interface);
+
+  vino_network_interface = g_strdup (network_interface);
 
-  dprintf (PREFS, "Local only changed: %s\n", vino_local_only ? "(true)" : "(false)");
+  dprintf (PREFS, "Network Interface for bind() changed: %s\n",
+       vino_network_interface ? vino_network_interface : "(null)");
 
   for (l = vino_servers; l; l = l->next)
-    vino_server_set_local_only (l->data, local_only);
+    vino_server_set_network_interface (l->data, network_interface);
 }
 
 static void
@@ -438,7 +447,7 @@
   server = g_object_new (VINO_TYPE_SERVER,
 			 "prompt-enabled",       vino_prompt_enabled,
 			 "view-only",            vino_view_only,
-			 "local-only",           vino_local_only,
+			 "network-interface",    vino_network_interface,
 			 "use-alternative-port", vino_use_alternative_port,
 			 "alternative-port",     vino_alternative_port,
 			 "auth-methods",         vino_auth_methods,
@@ -446,8 +455,8 @@
 			 "vnc-password",         vino_vnc_password,
 			 "on-hold",              !vino_enabled,
 			 "screen",               screen,
-             "lock-screen",          vino_lock_screen,
-             "disable-background",   vino_disable_background,
+			 "lock-screen",          vino_lock_screen,
+			 "disable-background",   vino_disable_background,
 			 NULL);
 
   vino_servers = g_slist_prepend (vino_servers, server);
@@ -498,15 +507,23 @@
 					      NULL);
     }
   dprintf (PREFS, "View only: %s\n", vino_view_only ? "(true)" : "(false)");
-      
-  vino_local_only = gconf_client_get_bool (vino_client,
-					   VINO_PREFS_LOCAL_ONLY,
-					   NULL);
-  dprintf (PREFS, "Local only: %s\n", vino_local_only ? "(true)" : "(false)");
+ 
+  vino_network_interface = gconf_client_get_string (vino_client,
+						    VINO_PREFS_NETWORK_INTERFACE,
+						    NULL);
+  /* Check for old key, local_only, vino <= 2.24 */
+  if (!vino_network_interface && gconf_client_get_bool (vino_client, VINO_PREFS_LOCAL_ONLY, NULL))
+    {
+      gconf_client_set_string (vino_client, VINO_PREFS_NETWORK_INTERFACE, "lo", NULL);
+      vino_network_interface = g_strdup ("lo");
+    }
+  dprintf (PREFS, "Network interface: %s\n", 
+                vino_network_interface ? vino_network_interface : "all");
 
   vino_use_alternative_port = gconf_client_get_bool (vino_client,
                                                      VINO_PREFS_USE_ALTERNATIVE_PORT,
                                                      NULL);
+    
   dprintf (PREFS, "Use alternative port: %s\n",
            vino_use_alternative_port ? "(true)" : "(false)");
 
@@ -584,8 +601,8 @@
 
   vino_listeners [i] =
     gconf_client_notify_add (vino_client,
-			     VINO_PREFS_LOCAL_ONLY,
-			     (GConfClientNotifyFunc) vino_prefs_local_only_changed,
+			     VINO_PREFS_NETWORK_INTERFACE,
+			     (GConfClientNotifyFunc) vino_prefs_network_interface_changed,
 			     NULL, NULL, NULL);
   i++;
 
@@ -666,7 +683,11 @@
   if (vino_vnc_password)
     g_free (vino_vnc_password);
   vino_vnc_password = NULL;
-      
+
+  if (vino_network_interface)
+    g_free (vino_network_interface);
+  vino_network_interface = NULL;
+
   for (i = 0; i < VINO_N_LISTENERS; i++) {
     if (vino_listeners [i])
       gconf_client_notify_remove (vino_client, vino_listeners [i]);

Modified: trunk/server/vino-server.c
==============================================================================
--- trunk/server/vino-server.c	(original)
+++ trunk/server/vino-server.c	Fri Dec 12 19:58:32 2008
@@ -61,8 +61,8 @@
   VinoStatusIcon   *icon;
   VinoDBusListener *listener;
 
-  GIOChannel       *io_channel;
-  guint             io_watch;
+  GIOChannel       *io_channel[RFB_MAX_SOCKETLISTEN];
+  guint             io_watch[RFB_MAX_SOCKETLISTEN];
 
   GSList           *clients;
 
@@ -76,7 +76,7 @@
   int               alternative_port;
 
   guint             on_hold : 1;
-  guint             local_only : 1;
+  char             *network_interface;
   guint             prompt_enabled : 1;
   guint             view_only : 1;
   guint             require_encryption : 1;
@@ -106,7 +106,7 @@
   PROP_ON_HOLD,
   PROP_PROMPT_ENABLED,
   PROP_VIEW_ONLY,
-  PROP_LOCAL_ONLY,
+  PROP_NETWORK_INTERFACE,
   PROP_USE_ALTERNATIVE_PORT,
   PROP_ALTERNATIVE_PORT,
   PROP_REQUIRE_ENCRYPTION,
@@ -250,8 +250,8 @@
 	    g_source_remove (client->update_timeout);
 	  client->update_timeout = 0;
 
-          if (client->io_watch)
-            g_source_remove (client->io_watch);
+    if (client->io_watch)
+      g_source_remove (client->io_watch);
 	  client->io_watch = 0;
 
 	  g_io_channel_unref (client->io_channel);
@@ -471,7 +471,7 @@
 {
   g_return_val_if_fail (VINO_IS_SERVER (server), FALSE);
 
-  rfbProcessNewConnection (server->priv->rfb_screen);
+  rfbProcessNewConnection (server->priv->rfb_screen, g_io_channel_unix_get_fd(source));
 
   return TRUE;
 }
@@ -843,6 +843,7 @@
   rfbScreenInfoPtr  rfb_screen;
   char             *name;
   GtkClipboard     *cb;
+  int               i;
 
   g_return_if_fail (server->priv->screen == NULL);
   g_return_if_fail (screen != NULL);
@@ -884,7 +885,7 @@
    *   5900-6000
    */
   rfb_screen->rfbDeferUpdateTime = 0;
-  rfb_screen->localOnly          = server->priv->local_only;
+  rfb_screen->netIface           = server->priv->network_interface;
   rfb_screen->autoPort           = TRUE;
   rfb_screen->rfbPort            = VINO_SERVER_DEFAULT_PORT;
   rfb_screen->rfbAlwaysShared    = TRUE;
@@ -917,15 +918,18 @@
 
   vino_server_update_security_types (server);
 
-  dprintf (RFB, "Creating watch for listening socket %d - port %d\n",
-	   rfb_screen->rfbListenSock, rfb_screen->rfbPort);
+  dprintf (RFB, "Creating watch for listening socket [ ");
+  for (i=0; i < rfb_screen->rfbListenSockTotal; i++)
+    {
+      dprintf (RFB, "%d ", rfb_screen->rfbListenSock[i]);
 
-  server->priv->io_channel = g_io_channel_unix_new (rfb_screen->rfbListenSock);
-  server->priv->io_watch =
-    g_io_add_watch (server->priv->io_channel,
-		    G_IO_IN|G_IO_PRI,
-		    (GIOFunc) vino_server_new_connection_pending,
-		    server);
+      server->priv->io_channel[i] = g_io_channel_unix_new (rfb_screen->rfbListenSock[i]);
+      server->priv->io_watch[i]   = g_io_add_watch (server->priv->io_channel[i],
+                                                    G_IO_IN|G_IO_PRI,
+                                                   (GIOFunc) vino_server_new_connection_pending,
+                                                    server);
+   }
+   dprintf(RFB,"]- port %d\n", rfb_screen->rfbPort);
 
 #ifdef VINO_ENABLE_HTTP_SERVER
   server->priv->http = vino_http_get (rfb_screen->rfbPort);
@@ -949,7 +953,8 @@
 vino_server_finalize (GObject *object)
 {
   VinoServer *server = VINO_SERVER (object);
-
+  int i;
+  
 #ifdef VINO_ENABLE_HTTP_SERVER
   if (server->priv->http)
     {
@@ -960,13 +965,16 @@
   server->priv->http = NULL;
 #endif /* VINO_ENABLE_HTTP_SERVER */
 
-  if (server->priv->io_watch)
-    g_source_remove (server->priv->io_watch);
-  server->priv->io_watch = 0;
-
-  if (server->priv->io_channel)
-    g_io_channel_unref (server->priv->io_channel);
-  server->priv->io_channel = NULL;
+  for(i=0; i < server->priv->rfb_screen->rfbListenSockTotal; i++)
+    {
+      if (server->priv->io_watch[i])
+        g_source_remove (server->priv->io_watch[i]);
+      server->priv->io_watch[i] = 0;
+
+      if (server->priv->io_channel[i])
+        g_io_channel_unref (server->priv->io_channel[i]);
+      server->priv->io_channel[i] = NULL;
+    }
   
   if (server->priv->rfb_screen)
     rfbScreenCleanup (server->priv->rfb_screen);
@@ -981,6 +989,10 @@
     g_free (server->priv->vnc_password);
   server->priv->vnc_password = NULL;
 
+  if(server->priv->network_interface)
+    g_free (server->priv->network_interface);
+  server->priv->network_interface = NULL;
+
   if (server->priv->prompt)
     g_object_unref (server->priv->prompt);
   server->priv->prompt = NULL;
@@ -1030,8 +1042,8 @@
     case PROP_VIEW_ONLY:
       vino_server_set_view_only (server, g_value_get_boolean (value));
       break;
-    case PROP_LOCAL_ONLY:
-      vino_server_set_local_only (server, g_value_get_boolean (value));
+    case PROP_NETWORK_INTERFACE:
+      vino_server_set_network_interface (server, g_value_get_string (value));
       break;
     case PROP_REQUIRE_ENCRYPTION:
       vino_server_set_require_encryption (server, g_value_get_boolean (value));
@@ -1082,8 +1094,8 @@
     case PROP_VIEW_ONLY:
       g_value_set_boolean (value, server->priv->view_only);
       break;
-    case PROP_LOCAL_ONLY:
-      g_value_set_boolean (value, server->priv->local_only);
+    case PROP_NETWORK_INTERFACE:
+      g_value_set_string (value, server->priv->network_interface);
       break;
     case PROP_REQUIRE_ENCRYPTION:
       g_value_set_boolean (value, server->priv->require_encryption);
@@ -1181,11 +1193,11 @@
                                                          G_PARAM_STATIC_BLURB));
 
   g_object_class_install_property (gobject_class,
-				   PROP_LOCAL_ONLY,
-				   g_param_spec_boolean ("local-only",
-							 "Local Only",
-							 "Only allow local connections",
-							 FALSE,
+				   PROP_NETWORK_INTERFACE,
+				   g_param_spec_string ("network-interface",
+							 "Network Interface",
+							 "Network interface for accept connections",
+							 NULL,
                                                          G_PARAM_READWRITE   |
                                                          G_PARAM_CONSTRUCT   |
                                                          G_PARAM_STATIC_NAME |
@@ -1368,32 +1380,32 @@
     }
 }
 
-gboolean
-vino_server_get_local_only (VinoServer *server)
+G_CONST_RETURN char *
+vino_server_get_network_interface (VinoServer *server)
 {
-  g_return_val_if_fail (VINO_IS_SERVER (server), FALSE);
-
-  return server->priv->local_only;
+  g_return_val_if_fail (VINO_IS_SERVER (server), NULL);
+  
+  return server->priv->network_interface;
 }
 
 void
-vino_server_set_local_only (VinoServer *server,
-                            gboolean    local_only)
+vino_server_set_network_interface (VinoServer *server,
+                                   const char *network_interface)
 {
   g_return_if_fail (VINO_IS_SERVER (server));
 
-  local_only = local_only != FALSE;
+  if (server->priv->network_interface)
+    g_free (server->priv->network_interface);
 
-  if (server->priv->local_only != local_only)
-    {
-      server->priv->local_only = local_only;
+  if(network_interface != NULL && strlen (network_interface) > 0)
+    server->priv->network_interface = g_strdup (network_interface);
+  else
+    server->priv->network_interface = NULL;
 
-      if (server->priv->rfb_screen != NULL)
-        rfbSetLocalOnly (server->priv->rfb_screen,
-                         server->priv->local_only);
+  if (server->priv->rfb_screen != NULL)
+    rfbSetNetworkInterface (server->priv->rfb_screen, server->priv->network_interface);
 
-      g_object_notify (G_OBJECT (server), "local-only");
-    }
+  g_object_notify (G_OBJECT (server), "network-interface");
 }
 
 gboolean

Modified: trunk/server/vino-server.h
==============================================================================
--- trunk/server/vino-server.h	(original)
+++ trunk/server/vino-server.h	Fri Dec 12 19:58:32 2008
@@ -85,9 +85,10 @@
 void                 vino_server_set_alternative_port     (VinoServer     *server,
 							   int             alternative_port);
 int                  vino_server_get_port                 (VinoServer     *server);
-void                 vino_server_set_local_only           (VinoServer     *server,
-							   gboolean        local_only);
-gboolean             vino_server_get_local_only           (VinoServer     *server);
+
+void                 vino_server_set_network_interface    (VinoServer     *server,
+                                                           const char     *network_interface);
+G_CONST_RETURN char *vino_server_get_network_interface    (VinoServer     *server);
 void                 vino_server_set_require_encryption   (VinoServer     *server,
 							   gboolean        require_encryption);
 gboolean             vino_server_get_require_encryption   (VinoServer     *server);

Modified: trunk/server/vino-server.schemas.in
==============================================================================
--- trunk/server/vino-server.schemas.in	(original)
+++ trunk/server/vino-server.schemas.in	Fri Dec 12 19:58:32 2008
@@ -51,19 +51,18 @@
     </schema>
 
     <schema>
-      <key>/schemas/desktop/gnome/remote_access/local_only</key>
-      <applyto>/desktop/gnome/remote_access/local_only</applyto>
+      <key>/schemas/desktop/gnome/remote_access/network_interface</key>
+      <applyto>/desktop/gnome/remote_access/network_interface</applyto>
       <owner>gnome</owner>
-      <type>bool</type>
-      <default>false</default>
+      <type>string</type>
+      <default></default>
       <locale name="C">
-         <short>Only allow local connections</short>
+         <short>Settings of network interface using for accept connections</short>
          <long>
-           If true, the server will only accept connections from
-           localhost and network connections will be rejected.
+           If set all, the server will listener in all network interfaces.
 
-           Set this option to true if you wish to exclusively use
-           a tunneling mechanism to access the server, such as ssh.
+           Set this if you want that accept connections only from specific
+           network interface. eg: eth0, wifi0, lo, ...
          </long>
       </locale>
     </schema>



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