[gnome-network][PATCH] connection timeout in gnome-remote-shell



Hi all, 

the patch I have attached adds a 15 sec timeout for connection in
gnome-remote-shell. 
Without the timeout, when you try to connect to a server with a firewall
that drops the packets received in the ssh or telnet port,  the syscall
connection is kept blocked forever

-- 
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
 Carlos Garcia Campos a.k.a. KaL
   elkalmail yahoo es
   carlosgc gnome org
 Grupo Linups
   Usuarios de SL/Linux de la UPSAM
 http://www.linups.org
=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=		  
PGP key: http://pgp.rediris.es:11371/pks/lookup?op=get&search=0x523E6462
Index: ChangeLog
===================================================================
RCS file: /cvs/gnome/gnome-network/network-utilities/ChangeLog,v
retrieving revision 1.28
diff -u -u -r1.28 ChangeLog
--- ChangeLog	17 Dec 2003 23:00:12 -0000	1.28
+++ ChangeLog	27 Dec 2003 16:06:49 -0000
@@ -1,3 +1,8 @@
+2003-12-27  Carlos Garcia Campos <carlosgc gnome org>
+
+	* gnome-remote-shell.c (check_network_status): added connection
+	timeout
+
 2003-12-17  Mason Kidd <mason_kidd mrkidd com>
 
 	* Makefile.am:
Index: gnome-remote-shell.c
===================================================================
RCS file: /cvs/gnome/gnome-network/network-utilities/gnome-remote-shell.c,v
retrieving revision 1.22
diff -u -u -r1.22 gnome-remote-shell.c
--- gnome-remote-shell.c	9 Dec 2003 23:24:32 -0000	1.22
+++ gnome-remote-shell.c	27 Dec 2003 16:06:49 -0000
@@ -27,6 +27,7 @@
 #include <sys/types.h>
 #include <sys/socket.h>
 #include <netinet/in.h>
+#include <fcntl.h>
 #include <gconf/gconf-client.h>
 #include <gtk/gtkdialog.h>
 #include <gtk/gtkentry.h>
@@ -180,69 +181,131 @@
 {
 	struct sockaddr_in *addr;
 	struct sockaddr_in6 *addr6;
+	struct sockaddr *addr_ptr;
 	struct hostent *hostname;
-	gint sd;
+	gint sd, err, ip_version, pf, size;
+	gint flags, len;
+	fd_set fd;
+	struct timeval *timeout;
 	gchar *msgerror;
 
-	switch (get_ip_version (host))
+	switch (ip_version = get_ip_version (host))
 	{
 	case IPV4:
-		hostname = gethostbyname2 (host, AF_INET);
+		pf = PF_INET;
+		break;
+	case IPV6:
+		pf = PF_INET6;
+		break;
+	case -1:
+	default:
+		g_print ("Error: Host unkown\n");
+		return FALSE;
+	}
+	hostname = gethostbyname2 (host, pf);
 
-		addr = (struct sockaddr_in *) g_malloc (sizeof (struct sockaddr_in));
-		
-		sd = socket (AF_INET, SOCK_STREAM, 0);
-		addr->sin_family = AF_INET;
-		addr->sin_port = g_htons (port);
-		addr->sin_addr = *(struct in_addr *) hostname->h_addr;
-		
-		errno = 0;
-		if (connect (sd, (struct sockaddr *) addr, sizeof (struct sockaddr_in)) != 0) {
-			msgerror = (gchar *) strerror (errno);
-			msgerror = g_locale_to_utf8 (msgerror, strlen (msgerror), NULL, NULL, NULL);
-			
-			create_error (_("There is a connection error"), msgerror);
-									
-			g_free (msgerror);
-			g_free (addr);
-			
-			return FALSE;
-		}
-		shutdown (sd, 2);
+	if ((sd = socket (pf, SOCK_STREAM, 0)) < 0) {
+		perror ("socket:");
+		return FALSE;
+	}
 
-		g_free (addr);
+	flags = fcntl (sd, F_GETFL, 0);
 
-		break;
-	case IPV6:
-		hostname = gethostbyname2 (host, PF_INET6);
+	if (fcntl (sd, F_SETFL, flags | O_NONBLOCK) < 0) {
+		perror ("fcntl:");
+		return FALSE;
+	}
+	
+	if (ip_version == IPV4) {
+		addr = (struct sockaddr_in *) g_malloc (sizeof (struct sockaddr_in));
 
+		addr->sin_family = PF_INET;
+		addr->sin_port = g_htons (port);
+		addr->sin_addr = *(struct in_addr *) hostname->h_addr;
+		addr_ptr = (struct sockaddr *) addr;
+		size = sizeof (struct sockaddr_in);
+	} else {
 		addr6 = (struct sockaddr_in6 *) g_malloc (sizeof (struct sockaddr_in6));
 
-		sd = socket (PF_INET6, SOCK_STREAM, 0);
 		addr6->sin6_family = PF_INET6;
 		addr6->sin6_port = g_htons (port);
 		addr6->sin6_addr = *(struct in6_addr *) hostname->h_addr;
+		addr_ptr = (struct sockaddr *) addr6;
+		size = sizeof (struct sockaddr_in6);
+	}
 
-		errno = 0;
-		if (connect (sd, (struct sockaddr *) addr6, sizeof (struct sockaddr_in6)) != 0) {
-			msgerror = (gchar *) strerror (errno);
-			msgerror = g_locale_to_utf8 (msgerror, strlen (msgerror), NULL, NULL, NULL);
+	errno = 0;
+	err = connect (sd, addr_ptr, size);
+
+	if (err < 0) {
+		if (errno != EINPROGRESS) {
+			msgerror = (gchar *) g_strerror (errno);
 			
 			create_error (_("There is a connection error"), msgerror);
-
+			
 			g_free (msgerror);
-			g_free (addr6);
-
+			g_free (addr_ptr);
+		
 			return FALSE;
 		}
-		shutdown (sd, 2);
+	}
 
-		g_free (addr6);
+	if (fcntl (sd, F_SETFL, flags) < 0) {
+		perror ("fcntl:");
+		return FALSE;
+	}
+	
+	FD_ZERO (&fd);
+	FD_SET (sd, &fd);
+	
+	timeout = (struct timeval *) g_malloc (sizeof (struct timeval));
+	timeout->tv_sec = 15;
+	timeout->tv_usec = 0;
+
+	errno = 0;
+	err = select (FD_SETSIZE, NULL, &fd, NULL, timeout);
+
+	if (err == 0) {
+		msgerror = g_strdup (_("Connection Timeout"));
+		msgerror = g_locale_to_utf8 (msgerror, strlen (msgerror), NULL, NULL, NULL);
 
-		break;
-	case -1:
+		create_error (_("There is a connection error"), msgerror);
+		
+		g_free (msgerror);
+		g_free (addr_ptr);
+		g_free (timeout);
+		
 		return FALSE;
 	}
+
+	len = sizeof (err);
+	if (getsockopt (sd, SOL_SOCKET, SO_ERROR, &err, &len) < 0) {
+		msgerror = g_strdup (_("Connection Timeout"));
+		msgerror = g_locale_to_utf8 (msgerror, strlen (msgerror), NULL, NULL, NULL);
+
+		create_error (_("There is a connection error"), msgerror);
+
+		g_free (msgerror);
+		g_free (addr_ptr);
+		g_free (timeout);
+
+		return FALSE;
+	} else if (err != 0) {
+		msgerror = (gchar *) g_strerror (err);
+
+		create_error (_("There is a connection error"), msgerror);
+
+		g_free (msgerror);
+		g_free (addr_ptr);
+		g_free (timeout);
+
+		return FALSE;
+	}
+		
+	shutdown (sd, 2);
+	
+	g_free (addr_ptr);
+	g_free (timeout);
 	
 	return TRUE;
 }
@@ -338,8 +401,9 @@
 	if (validate_host (host) == FALSE)
 		return;
 
-	if (check_network_status (host, port) == FALSE)
+	if (check_network_status (host, port) == FALSE) {
 		return;
+	}
 
 	/*
 	 * Get the terminal preferences from GConf.

Attachment: signature.asc
Description: Esta parte del mensaje =?ISO-8859-1?Q?est=E1?= firmada digitalmente



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