[vhffs-dev] [1605] added TCP keepalive on the slave, so that the slave can reconnect on network or power outage

[ Thread Index | Date Index | More vhffs.org/vhffs-dev Archives ]


Revision: 1605
Author:   gradator
Date:     2010-05-10 01:18:54 +0200 (Mon, 10 May 2010)
Log Message:
-----------
added TCP keepalive on the slave, so that the slave can reconnect on network or power outage

Modified Paths:
--------------
    trunk/vhffs-fssync/vhffsfssync_master.c
    trunk/vhffs-fssync/vhffsfssync_slave.c

Modified: trunk/vhffs-fssync/vhffsfssync_master.c
===================================================================
--- trunk/vhffs-fssync/vhffsfssync_master.c	2010-05-09 06:39:56 UTC (rev 1604)
+++ trunk/vhffs-fssync/vhffsfssync_master.c	2010-05-09 23:18:54 UTC (rev 1605)
@@ -48,6 +48,7 @@
 #include <netdb.h>
 #include <arpa/inet.h>
 #include <netinet/in.h>
+#include <netinet/tcp.h>
 #include <sys/sendfile.h>
 #include <getopt.h>
 
@@ -1772,7 +1773,7 @@
 	signal(SIGPIPE, SIG_IGN);
 
 	/* listening for network connections */
-	if( (listenfd = socket(AF_INET, SOCK_STREAM, 0) ) < 0) {
+	if( (listenfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP) ) < 0) {
 		fprintf(stderr, "socket() failed: %s\n", strerror(errno));
 		return -1;
 	}
@@ -1942,7 +1943,7 @@
 #if DEBUG_NET
 					printf("Welcome %s ! (using fd %d)\n", inet_ntoa(conn->sockaddr.sin_addr), conn->fd);
 #endif
-					vhffsfssync_net_send_event(conn, g_strdup_printf("hello%c%llu%c", '\0', (long long int)ntohl(conn->sockaddr.sin_addr.s_addr), '\0') , VHFFSFSSYNC_NET_PRIO_HIGHEST);
+					vhffsfssync_net_send_event(conn, g_strdup_printf("hello%c%lld%c", '\0', (long long int)ntohl(conn->sockaddr.sin_addr.s_addr), '\0') , VHFFSFSSYNC_NET_PRIO_HIGHEST);
 				}
 			}
 

Modified: trunk/vhffs-fssync/vhffsfssync_slave.c
===================================================================
--- trunk/vhffs-fssync/vhffsfssync_slave.c	2010-05-09 06:39:56 UTC (rev 1604)
+++ trunk/vhffs-fssync/vhffsfssync_slave.c	2010-05-09 23:18:54 UTC (rev 1605)
@@ -45,6 +45,7 @@
 #include <netdb.h>
 #include <arpa/inet.h>
 #include <netinet/in.h>
+#include <netinet/tcp.h>
 #include <getopt.h>
 #include <utime.h>
 #include <sys/time.h>
@@ -957,6 +958,7 @@
 	printf ("Usage: %s [OPTION]... HOST[:PORT] DIRECTORY\n"
 		"Remote synchronous file-copying tool, this is the client (the slave)\n\n"
 		"  -f, --foreground\tDo not daemonise the client, display errors on the console\n"
+		"  -t, --timeout=s\tConnection timeout in seconds, default is 3600s, 0 disable keepalive\n"
 		"  -r, --limit-rate=kB/s\tLimit I/O bandwidth; kBytes per second\n"
 		"  -p, --preserve\tPreserve owners, groups and permissions\n"
 		"      --prevent-loop\tAbort if the host seen by the master is the host we are connecting to (loopback)\n"
@@ -977,6 +979,7 @@
 	char *host = NULL;
 	int port = 4567;
 	char *root = NULL;
+	int timeout = 3600;
 	int limitrate = 0;
 
 	vhffsfssync_preserve = 0;
@@ -987,6 +990,7 @@
 
 	struct option long_options[] = {
 		{ "foreground", no_argument, NULL, 'f' },
+		{ "timeout", required_argument, NULL, 't' },
 		{ "limit-rate", required_argument, NULL, 'r' },
 		{ "preserve", no_argument, NULL, 'p' },
 		{ "prevent-loop", no_argument, NULL, 1000 },
@@ -997,7 +1001,7 @@
 
 	while(1) {
 		int option_index = 0, c;
-		c = getopt_long(argc, argv, "fr:phv", long_options, &option_index);
+		c = getopt_long(argc, argv, "ft:r:phv", long_options, &option_index);
 		if(c == -1)
 			break;
 
@@ -1006,6 +1010,10 @@
 				foreground = 1;
 				break;
 
+			case 't':
+				timeout = atoi(optarg);
+				break;
+
 			case 'r':
 				limitrate = atoi(optarg)*1000;
 				break;
@@ -1095,6 +1103,8 @@
 
 	/* -- main loop -- */
 	while(1)  {
+		int opt;
+
 		/* clean the previous connection */
 		if(conn->fd >= 0) {
 			shutdown(conn->fd, SHUT_RDWR);
@@ -1131,12 +1141,41 @@
 		conn->sockaddr.sin_family = AF_INET;
 		conn->sockaddr.sin_port = htons(port);
 
-		conn->fd = socket(conn->sockaddr.sin_family, SOCK_STREAM, IPPROTO_IP);
+		conn->fd = socket(conn->sockaddr.sin_family, SOCK_STREAM, IPPROTO_TCP);
 		if(conn->fd < 0)  {
 			fprintf(stderr, "socket() failed: %s\n", strerror(errno));
 			return -1;
 		}
 
+		/* use TCP keepalive */
+		if(timeout) {
+			opt = 1;
+			if( setsockopt(conn->fd, SOL_SOCKET, SO_KEEPALIVE, (char*)&opt, sizeof(opt) ) )  {
+				fprintf(stderr, "setsockopt() SO_KEEPALIVE failed on socket %d: %s\n", conn->fd, strerror(errno));
+			}
+
+			/* start keepalive at 9/10 of the timeout value. If timeout is too low, reserve 10s for keepalive probes */
+			opt = timeout-timeout/10;
+			if(opt > timeout-10) opt = timeout-10;
+ 			if(opt <= 0) opt=1;
+			if( setsockopt(conn->fd, SOL_TCP, TCP_KEEPIDLE, (char*)&opt, sizeof(opt) ) )  {
+				fprintf(stderr, "setsockopt() TCP_KEEPIDLE failed on socket %d: %s\n", conn->fd, strerror(errno));
+			}
+
+			/* consider session down after 10 missed probes */
+			opt = 10;
+			if( setsockopt(conn->fd, SOL_TCP, TCP_KEEPCNT, (char*)&opt, sizeof(opt) ) )  {
+				fprintf(stderr, "setsockopt() TCP_KEEPCNT failed on socket %d: %s\n", conn->fd, strerror(errno));
+			}
+
+			/* 10 probes in 1/10 of total time = 1/100 of total time interval between probes */
+			opt = timeout/100;
+			if(!opt) opt=1;
+			if( setsockopt(conn->fd, SOL_TCP, TCP_KEEPINTVL, (char*)&opt, sizeof(opt) ) )  {
+				fprintf(stderr, "setsockopt() TCP_KEEPINTVL failed on socket %d: %s\n", conn->fd, strerror(errno));
+			}
+		}
+
 		if( connect(conn->fd, (struct sockaddr*)&conn->sockaddr, sizeof(conn->sockaddr)) < 0 )  {
 
 			fprintf(stderr, "connect() failed: %s\n", strerror(errno));


Mail converted by MHonArc 2.6.19+ http://listengine.tuxfamily.org/