[gtk-vnc-devel] RFC: api for openning a tunnelled connection



We currently have two APIs for openning connections

   vnc_display_open_fd  - takes a pre-opened file handle
   vnc_display_open_host - takes hostname & servicename (aka port)

Another pretty common way to access VNC servers is by tunnelling them over
SSH. Now obviously any client apps could implement this themselves by forking
ssh and then calling vnc_display_open_fd. I don't particularly want to have
to implement this multiple times in each app though. So what do people think
about having an explicit API for openning an SSH tunnelled connection, and
even an arbitrary 'external' tunnel script (cf CVS 'ext' method).


  vnc_display_open_ssh_tunnel(VncDisplay *d, const char *user, const char *host, const char *port)
  vnc_display_open_ext_tunnel(VncDisplay *d, const char *script);

Or just one todo both ....

   vnc_display_open_ext_tunnel(VncDisplay *d, const char **argv);

Attaching a crude impl of the SSH tunnel impl

Regards,
Dan.
-- 
|=- Red Hat, Engineering, Emerging Technologies, Boston.  +1 978 392 2496 -=|
|=-           Perl modules: http://search.cpan.org/~danberr/              -=|
|=-               Projects: http://freshmeat.net/~danielpb/               -=|
|=-  GnuPG: 7D3B9505   F3C9 553F A1DA 4AC2 5648 23C1 B3DF F742 7D3B 9505  -=| 
diff -r b1c48ddc01d9 examples/gvncviewer.c
--- a/examples/gvncviewer.c	Wed Aug 22 15:10:12 2007 -0400
+++ b/examples/gvncviewer.c	Mon Aug 27 23:20:36 2007 -0400
@@ -258,7 +258,8 @@ int main(int argc, char **argv)
 	} else
 		snprintf(port, sizeof(port), "%d", 5900);
 
-	vnc_display_open_host(VNC_DISPLAY(vnc), hostname, port);
+	//vnc_display_open_host(VNC_DISPLAY(vnc), hostname, port);
+	vnc_display_open_tunnel(VNC_DISPLAY(vnc), "root", hostname, port);
 	vnc_display_set_keyboard_grab(VNC_DISPLAY(vnc), TRUE);
 	vnc_display_set_pointer_grab(VNC_DISPLAY(vnc), TRUE);
 	//vnc_display_set_pointer_local(VNC_DISPLAY(vnc), TRUE);
diff -r b1c48ddc01d9 src/libgtk-vnc_sym.version
--- a/src/libgtk-vnc_sym.version	Wed Aug 22 15:10:12 2007 -0400
+++ b/src/libgtk-vnc_sym.version	Mon Aug 27 23:22:49 2007 -0400
@@ -6,6 +6,7 @@
     vnc_display_new;
     vnc_display_open_fd;
     vnc_display_open_host;
+    vnc_display_open_tunnel;
     vnc_display_is_open;
     vnc_display_close;
 
diff -r b1c48ddc01d9 src/vncdisplay.c
--- a/src/vncdisplay.c	Wed Aug 22 15:10:12 2007 -0400
+++ b/src/vncdisplay.c	Tue Aug 28 17:30:16 2007 -0400
@@ -24,6 +24,14 @@
 #include <unistd.h>
 #include <pwd.h>
 
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+
+#include <sys/types.h>
+#include <signal.h>
+#include <sys/wait.h>
+
 #define VNC_DISPLAY_GET_PRIVATE(obj) \
       (G_TYPE_INSTANCE_GET_PRIVATE((obj), VNC_TYPE_DISPLAY, VncDisplayPrivate))
 
@@ -32,6 +40,7 @@ struct _VncDisplayPrivate
 	int fd;
 	char *host;
 	char *port;
+	pid_t pid;
 	GdkGC *gc;
 	VncShmImage *shm_image;
 	GdkCursor *null_cursor;
@@ -632,6 +641,14 @@ static void *vnc_coroutine(void *opaque)
 
  cleanup:
 	gvnc_close(priv->gvnc);
+	if (obj->priv->pid != 0) {
+		kill(obj->priv->pid, SIGTERM);
+		if (waitpid(obj->priv->pid, NULL, WNOHANG) != obj->priv->pid) {
+			kill(obj->priv->pid, SIGKILL);
+			waitpid(obj->priv->pid, NULL, 0);
+		}
+		obj->priv->pid = 0;
+	}
 	g_signal_emit (G_OBJECT (obj),
 		       signals[VNC_DISCONNECTED],
 		       0);
@@ -689,6 +706,71 @@ gboolean vnc_display_open_host(VncDispla
 
 	g_idle_add(do_vnc_display_open, obj);
 	return TRUE;
+}
+
+gboolean vnc_display_open_tunnel(VncDisplay *obj, const char *user, const char *host, const char *port)
+{
+	int fd[2];
+	pid_t pid;
+	if (obj->priv->gvnc == NULL || gvnc_is_open(obj->priv->gvnc))
+		return FALSE;
+
+	if (socketpair(PF_UNIX, SOCK_STREAM, 0, fd) < 0)
+		return FALSE;
+
+	obj->priv->host = strdup(host);
+	if (!obj->priv->host)
+		goto fail;
+
+	obj->priv->port = strdup(port);
+	if (!obj->priv->port)
+		goto fail;
+
+	pid = fork();
+	if (pid == -1)
+		goto fail;
+	if (pid == 0) { /* child */
+		const char *cmd[6];
+		char *dst = malloc(strlen(user) + strlen(host) + 2);
+		if (!dst)
+			_exit(1);
+		strcpy(dst, user);
+		strcat(dst, "@");
+		strcat(dst, host);
+
+		cmd[0] = "ssh";
+		cmd[1] = dst;
+		cmd[2] = "nc";
+		cmd[3] = "localhost";
+		cmd[4] = port;
+		cmd[5] = NULL;
+
+		close(fd[0]);
+		close(0);
+		close(1);
+		if (dup(fd[1]) < 0)
+			_exit(1);
+		if (dup(fd[1]) < 0)
+			_exit(1);
+		close(fd[1]);
+		execvp("ssh", (char *const*)cmd);
+		_exit(1);
+	}
+	close(fd[1]);
+
+	obj->priv->fd = fd[0];
+
+	g_idle_add(do_vnc_display_open, obj);
+	return TRUE;
+
+ fail:
+	close(fd[0]);
+	close(fd[1]);
+	free(obj->priv->host);
+	obj->priv->host = NULL;
+	free(obj->priv->port);
+	obj->priv->port = NULL;
+	return FALSE;
 }
 
 gboolean vnc_display_is_open(VncDisplay *obj)


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