Use TCP keepalives on Linux if available; if not, fallback to manual keepalives.
authorSenko Rasic <senko.rasic@collabora.co.uk>
Mon, 29 Oct 2007 17:02:16 +0100
changeset 292 bb7269466be2
parent 291 cebf76f7f0e9
child 293 b4336dfa5b91
Use TCP keepalives on Linux if available; if not, fallback to manual keepalives.
loudmouth/lm-connection.c
loudmouth/lm-internals.h
loudmouth/lm-sock.c
loudmouth/lm-socket.c
loudmouth/lm-socket.h
--- a/loudmouth/lm-connection.c	Mon Oct 29 16:59:36 2007 +0100
+++ b/loudmouth/lm-connection.c	Mon Oct 29 17:02:16 2007 +0100
@@ -321,6 +321,12 @@
 static void
 connection_start_keep_alive (LmConnection *connection)
 {
+	/* try using TCP keepalives if possible */
+	if ((connection->keep_alive_rate > 0) &&
+		lm_socket_set_keepalive (connection->socket,
+			connection->keep_alive_rate))
+		return;
+
 	if (connection->keep_alive_source) {
 		connection_stop_keep_alive (connection);
 	}
--- a/loudmouth/lm-internals.h	Mon Oct 29 16:59:36 2007 +0100
+++ b/loudmouth/lm-internals.h	Mon Oct 29 17:02:16 2007 +0100
@@ -109,4 +109,8 @@
 const gchar *    _lm_sock_get_error_str           (int                    err);
 const gchar *    _lm_sock_addrinfo_get_error_str  (int                    err);
 
+#ifdef USE_TCP_KEEPALIVES
+gboolean         _lm_sock_set_keepalive (LmSocketT sock, int delay);
+#endif /* USE_TCP_KEEPALIVES */
+
 #endif /* __LM_INTERNALS_H__ */
--- a/loudmouth/lm-sock.c	Mon Oct 29 16:59:36 2007 +0100
+++ b/loudmouth/lm-sock.c	Mon Oct 29 17:02:16 2007 +0100
@@ -289,3 +289,34 @@
 
 	return _("The remote address could not be obtained ");
 }
+
+#ifdef USE_TCP_KEEPALIVES
+gboolean
+_lm_sock_set_keepalive (LmSocketT sock, int delay)
+{
+	int opt;
+
+	opt = 1;
+	if (setsockopt (sock, SOL_SOCKET, SO_KEEPALIVE, &opt, sizeof (opt)) < 0) {
+		return FALSE;
+	}
+
+	opt = 3; /* 3 keepalives before considering connection dead */
+	if (setsockopt (sock, IPPROTO_TCP, TCP_KEEPCNT, &opt, sizeof (opt)) < 0) {
+		return FALSE;
+	}
+
+	opt = 30; /* start keepalives after 30s idle time */
+	if (setsockopt (sock, IPPROTO_TCP, TCP_KEEPIDLE, &opt, sizeof (opt)) < 0) {
+		return FALSE;
+	}
+
+	opt = 30; /* send keepalive every 30s */
+	if (setsockopt (sock, IPPROTO_TCP, TCP_KEEPINTVL, &opt, sizeof (opt)) < 0) {
+		return FALSE;
+	}
+
+	return TRUE;
+}
+#endif /* USE_TCP_KEEPALIVES */
+
--- a/loudmouth/lm-socket.c	Mon Oct 29 16:59:36 2007 +0100
+++ b/loudmouth/lm-socket.c	Mon Oct 29 17:02:16 2007 +0100
@@ -1119,3 +1119,13 @@
 	}
 }
 
+gboolean
+lm_socket_set_keepalive (LmSocket *socket, int delay)
+{
+#ifdef USE_TCP_KEEPALIVES
+	return _lm_sock_set_keepalive (socket->fd, delay);
+#else
+	return FALSE;
+#endif /* USE_TCP_KEEPALIVES */
+}
+
--- a/loudmouth/lm-socket.h	Mon Oct 29 16:59:36 2007 +0100
+++ b/loudmouth/lm-socket.h	Mon Oct 29 17:02:16 2007 +0100
@@ -70,6 +70,7 @@
 void	    _asyncns_cancel               (LmSocket *socket);
 #endif
 gboolean    lm_socket_starttls            (LmSocket *socket);
+gboolean    lm_socket_set_keepalive       (LmSocket *socket, int delay);
 
 #endif /* __LM_SOCKET_H__ */