socket: socket_keepalive()
authorMarko Kreen <markokr@gmail.com>
Tue, 2 Mar 2010 14:37:37 +0000 (16:37 +0200)
committerMarko Kreen <markokr@gmail.com>
Wed, 3 Mar 2010 07:50:22 +0000 (09:50 +0200)
usual/socket.c
usual/socket.h

index 19d303e66fb73c011a8f09ddc3c9de860fd4f0c0..e2a2cf746a69c352dfc3955859806aea0cdc2630 100644 (file)
@@ -80,6 +80,77 @@ bool socket_setup(int sock, bool non_block)
        return true;
 }
 
+bool socket_set_keepalive(int fd, int onoff, int keepidle, int keepintvl, int keepcnt)
+{
+       int val, res;
+
+       if (!onoff) {
+               /* turn keepalive off */
+               val = 0;
+               res = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val));
+               return (res == 0);
+       }
+
+       /* turn keepalive on */
+       val = 1;
+       res = setsockopt(fd, SOL_SOCKET, SO_KEEPALIVE, &val, sizeof(val));
+       if (res < 0)
+               return false;
+
+       /* Darwin */
+#ifdef TCP_KEEPALIVE
+       if (keepidle) {
+               val = keepidle;
+               res = setsockopt(fd, IPPROTO_TCP, TCP_KEEPALIVE, &val, sizeof(val));
+               if (res < 0 && errno != ENOPROTOOPT)
+                       return false;
+       }
+#endif
+
+       /* Linux, NetBSD */
+#ifdef TCP_KEEPIDLE
+       if (keepidle) {
+               val = keepidle;
+               res = setsockopt(fd, IPPROTO_TCP, TCP_KEEPIDLE, &val, sizeof(val));
+               if (res < 0 && errno != ENOPROTOOPT)
+                       return false;
+       }
+#endif
+#ifdef TCP_KEEPINTVL
+       if (keepintvl) {
+               val = keepintvl;
+               res = setsockopt(fd, IPPROTO_TCP, TCP_KEEPINTVL, &val, sizeof(val));
+               if (res < 0 && errno != ENOPROTOOPT)
+                       return false;
+       }
+#endif
+#ifdef TCP_KEEPCNT
+       if (keepcnt > 0) {
+               val = keepcnt;
+               res = setsockopt(fd, IPPROTO_TCP, TCP_KEEPCNT, &val, sizeof(val));
+               if (res < 0 && errno != ENOPROTOOPT)
+                       return false;
+       }
+#endif
+
+       /* Windows */
+#ifdef SIO_KEEPALIVE_VALS
+       if (keepidle || keepintvl) {
+               struct tcp_keepalive vals;
+               DWORD outlen = 0;
+               if (!keepidle) keepidle = 5 * 60;
+               if (!keepintvl) keepintvl = 15;
+               vals.onoff = 1;
+               vals.keepalivetime = keepidle * 1000;
+               vals.keepaliveinterval = keepintvl * 1000;
+               res = WSAIoctl(fd, SIO_KEEPALIVE_VALS, &vals, sizeof(vals), NULL, 0, &outlen, NULL, NULL, NULL, NULL);
+               if (res != 0)
+                       return false;
+       }
+#endif
+       return true;
+}
+
 /*
  * Convert sockaddr to string.  Supports ipv4, ipv6 and unix sockets.
  */
index f77f9c9891cb19dbbba3cd88cd0d7a7996741e64..bd31a3779823d68fadd2a48e358ef12959422b07 100644 (file)
@@ -61,6 +61,7 @@
 
 bool socket_setup(int sock, bool non_block);
 bool socket_set_nonblocking(int sock, bool non_block);
+bool socket_set_keepalive(int fd, int onoff, int keepidle, int keepintvl, int keepcnt);
 
 const char *sa2str(const struct sockaddr *sa, char *buf, int buflen);