This commit adds new configuration options to use TCP
keepalives. They can be useful when using a
bandwidth-constrained connection. The broker can realize
earlier that a client has disconnected before the next MQTT
ping takes place
---
  config.mk                       |  7 +++++++
  mosquitto.conf                  |  9 +++++++++
  src/conf.c                      | 30 ++++++++++++++++++++++++++++++
  src/mosquitto_broker_internal.h |  6 ++++++
  src/net.c                       | 25 +++++++++++++++++++++++++
  5 files changed, 77 insertions(+)
diff --git a/config.mk b/config.mk
index 0185027..297abfa 100644
--- a/config.mk
+++ b/config.mk
@@ -92,6 +92,9 @@ WITH_STATIC_LIBRARIES:=no
  # Build with epoll support.
  WITH_EPOLL:=yes
  
+# Build with support for TCP keepalives. Requires Linux
+WITH_TCPKEEPALIVE:=yes
+
  # =============================================================================
  # End of user configuration
  # =============================================================================
@@ -255,6 +258,10 @@ ifeq ($(WITH_EC),yes)
  	BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_EC
  endif
  
+ifeq ($(WITH_TCPKEEPALIVE),yes)
+	BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_TCPKEEPALIVE
+endif
+
  ifeq ($(WITH_ADNS),yes)
  	BROKER_LIBS:=$(BROKER_LIBS) -lanl
  	BROKER_CFLAGS:=$(BROKER_CFLAGS) -DWITH_ADNS
diff --git a/mosquitto.conf b/mosquitto.conf
index b383c0a..31cf71a 100644
--- a/mosquitto.conf
+++ b/mosquitto.conf
@@ -136,6 +136,15 @@
  # of packets being sent.
  #set_tcp_nodelay false
  
+# Additionally use TCP keepalive as a lower-overhead way to check if a session
+# is still alive. Might allow to set a bigger ping rate.
+# The properties are directly passed to setsockopt.
+# See http://man7.org/linux/man-pages/man7/tcp.7.html for explanation
+#use_tcp_keepalive true
+#tcp_keepcnt 5
+#tcp_keepidle 900
+#tcp_keepintvl 180
+
  # =================================================================
  # Default listener
  # =================================================================
diff --git a/src/conf.c b/src/conf.c
index 44207d4..3b8aa7e 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -251,6 +251,12 @@ void config__init(struct mosquitto__config *config)
  	config->auth_plugins = NULL;
  	config->verbose = false;
  	config->message_size_limit = 0;
+#ifdef WITH_TCPKEEPALIVE
+	config->use_tcp_keepalive = false;
+	config->tcp_keepcnt = 5;
+	config->tcp_keepidle = 900;
+	config->tcp_keepintvl = 180;
+#endif
  }
  
  void config__cleanup(struct mosquitto__config *config)
@@ -1854,6 +1860,30 @@ int config__read_file_core(struct mosquitto__config *config, bool reload, const
  						|| !strcmp(token, "max_log_entries")
  						|| !strcmp(token, "trace_output")){
  					log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Unsupported rsmb configuration option \"%s\".", token);
+				}else if(!strcmp(token, "use_tcp_keepalive")){
+#ifdef WITH_TCPKEEPALIVE
+					if(conf__parse_bool(&token, "use_tcp_keepalive", &config->use_tcp_keepalive, saveptr)) return MOSQ_ERR_INVAL;
+#else
+					log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TCPKEEPALIVE support not available.");
+#endif
+				}else if(!strcmp(token, "tcp_keepcnt")){
+#ifdef WITH_TCPKEEPALIVE
+					if(conf__parse_int(&token, "tcp_keepcnt", &config->tcp_keepcnt, saveptr)) return MOSQ_ERR_INVAL;
+#else
+					log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TCPKEEPALIVE support not available.");
+#endif
+				}else if(!strcmp(token, "tcp_keepidle")){
+#ifdef WITH_TCPKEEPALIVE
+					if(conf__parse_int(&token, "tcp_keepidle", &config->tcp_keepidle, saveptr)) return MOSQ_ERR_INVAL;
+#else
+					log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TCPKEEPALIVE support not available.");
+#endif
+				}else if(!strcmp(token, "tcp_keepintvl")){
+#ifdef WITH_TCPKEEPALIVE
+					if(conf__parse_int(&token, "tcp_keepintvl", &config->tcp_keepintvl, saveptr)) return MOSQ_ERR_INVAL;
+#else
+					log__printf(NULL, MOSQ_LOG_WARNING, "Warning: TCPKEEPALIVE support not available.");
+#endif
  				}else{
  					log__printf(NULL, MOSQ_LOG_ERR, "Error: Unknown configuration variable \"%s\".", token);
  					return MOSQ_ERR_INVAL;
diff --git a/src/mosquitto_broker_internal.h
b/src/mosquitto_broker_internal.h index 92fac93..85b9cbf 100644
--- a/src/mosquitto_broker_internal.h
+++ b/src/mosquitto_broker_internal.h
@@ -223,6 +223,12 @@ struct mosquitto__config {
  	struct mosquitto__bridge *bridges;
  	int bridge_count;
  #endif
+#ifdef WITH_TCPKEEPALIVE
+	bool use_tcp_keepalive;
+	int tcp_keepcnt;
+	int tcp_keepidle;
+	int tcp_keepintvl;
+#endif
  	struct mosquitto__auth_plugin_config *auth_plugins;
  	int auth_plugin_count;
  };
diff --git a/src/net.c b/src/net.c
index a0f90b8..ae9c5bc 100644
--- a/src/net.c
+++ b/src/net.c
@@ -27,6 +27,11 @@ Contributors:
  #include <ws2tcpip.h>
  #endif
  
+#ifdef WITH_TCPKEEPALIVE
+#	include <sys/socket.h>
+#	include <netinet/tcp.h>
+#endif
+
  #include <assert.h>
  #include <errno.h>
  #include <fcntl.h>
@@ -127,6 +132,26 @@ int net__socket_accept(struct mosquitto_db *db, mosq_sock_t listensock)
  		setsockopt(new_sock, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(int));
  	}
  
+#ifdef WITH_TCPKEEPALIVE
+	if (db->config->use_tcp_keepalive){
+		int optval = 1;
+		if (setsockopt(new_sock, SOL_SOCKET, SO_KEEPALIVE, &optval, sizeof(optval)) < 0) {
+			log__printf(NULL, MOSQ_LOG_WARNING, "TCP keepalive could not be enabled");
+		}
+		else {
+			int keepcnt  =  db->config->tcp_keepcnt;
+			int keepidle =  db->config->tcp_keepidle;
+			int keepintvl = db->config->tcp_keepintvl;
+
+			setsockopt(new_sock, IPPROTO_TCP, TCP_KEEPCNT, &keepcnt, sizeof(keepcnt));
+			setsockopt(new_sock, IPPROTO_TCP, TCP_KEEPIDLE, &keepidle, sizeof(keepidle));
+			setsockopt(new_sock, IPPROTO_TCP, TCP_KEEPINTVL, &keepintvl, sizeof(keepintvl));
+
+			log__printf(NULL, MOSQ_LOG_DEBUG, "TCP keepalive enabled with %d, %d, %d", keepcnt, keepidle, keepintvl);
+		}
+	}
+#endif
+
  	new_context = context__init(db, new_sock);
  	if(!new_context){
  		COMPAT_CLOSE(new_sock);
--
2.7.4
_______________________________________________
mosquitto-dev mailing list
mosquitto-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or
unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/mosquitto-dev
_______________________________________________
mosquitto-dev mailing list
mosquitto-dev@xxxxxxxxxxx
To change your delivery options, retrieve your password, or unsubscribe from this list, visit
https://dev.eclipse.org/mailman/listinfo/mosquitto-dev