[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));