Merge branch 'bridge_tcp_user_timeout' of git://github.com/abiliojr/mosquitto into abiliojr-bridge_tcp_user_timeout

pull/2386/head
Roger Light 4 years ago
commit 3eaed4c730

@ -1697,23 +1697,45 @@ openssl dhparam -out dhparam.pem 2048</programlisting>
<replaceable>mqttv311</replaceable>.</para> <replaceable>mqttv311</replaceable>.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry> <varlistentry>
<term><option>bridge_tcp_keepalive</option> <replaceable>idle</replaceable> <replaceable>interval</replaceable> <replaceable>counter</replaceable></term> <term><option>bridge_tcp_keepalive</option> <replaceable>idle</replaceable> <replaceable>interval</replaceable> <replaceable>counter</replaceable></term>
<listitem> <listitem>
<para> <para>
Set TCP keepalive parameters for this bridge connection. Set TCP keepalive parameters for this bridge connection.
Use this option to allow you to set a long MQTT Use this option to allow you to set a long MQTT
keepalive value, whilst still being able to detect the keepalive value, whilst still being able to detect the
connection dropping in a reasonable time. connection dropping in a reasonable time.
</para> </para>
<para> <para>
This may be useful when bridging to services that bill This may be useful when bridging to services that bill
for PINGREQ messages. for PINGREQ messages.
</para> </para>
<para>Disabled by default.</para> <para>Disabled by default.</para>
</listitem> </listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>bridge_tcp_user_timeout</option> <replaceable>timeout</replaceable></term>
<listitem>
<para>
It specifies the maximum amount of time (in milliseconds) that
transmitted data may remain unacknowledged at TCP level.
Popular Linux distributions seem to set this time to "up to 20
minutes with system defaults" (from Linux tcp man page).
The default time is related to tcp_retries2.
Reducing this value helps detecting dropped connections faster.
</para>
<para>
Be aware that when used in combination with TCP Keepalive, it might
change the latter's behavior.
</para>
<para>
You can find more details about this setting at:
<ulink url="https://blog.cloudflare.com/when-tcp-sockets-refuse-to-die/"/>
<para>
Only available on Linux.
</para>
</listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><option>cleansession</option> [ true | false ]</term> <term><option>cleansession</option> [ true | false ]</term>
<listitem> <listitem>

@ -723,6 +723,16 @@
# Disabled by default. # Disabled by default.
#bridge_tcp_keepalive <idle> <interval> <counter> #bridge_tcp_keepalive <idle> <interval> <counter>
# Change the maximum amount of time (in milliseconds) that transmitted data
# may remain unacknowledged at TCP level.
# Popular Linux distributions seem to set this time to "up to 20 minutes with
# system defaults" (from Linux tcp man page). Reducing this value helps
# detecting dropped connections faster.
# When used together with TCP Keepalive, it might change it's behavior.
# More details at: https://blog.cloudflare.com/when-tcp-sockets-refuse-to-die/
# Only available on Linux.
#bridge_tcp_user_timeout <ms>
# Set the clientid to use on the local broker. If not defined, this defaults to # Set the clientid to use on the local broker. If not defined, this defaults to
# 'local.<clientid>'. If you are bridging a broker to itself, it is important # 'local.<clientid>'. If you are bridging a broker to itself, it is important
# that local_clientid and clientid do not match. # that local_clientid and clientid do not match.

@ -177,7 +177,7 @@ static int bridge__set_tcp_keepalive(struct mosquitto *context)
unsigned int enabled = 1; unsigned int enabled = 1;
bool ret; bool ret;
if (idle == 0 || interval == 0 || counter == 0) return MOSQ_ERR_SUCCESS; if(idle == 0 || interval == 0 || counter == 0) return MOSQ_ERR_SUCCESS;
#ifdef WIN32 #ifdef WIN32
ret = ret =
@ -193,11 +193,24 @@ static int bridge__set_tcp_keepalive(struct mosquitto *context)
setsockopt(context->sock, IPPROTO_TCP, TCP_KEEPCNT, (const void*)&counter, sizeof(counter)); setsockopt(context->sock, IPPROTO_TCP, TCP_KEEPCNT, (const void*)&counter, sizeof(counter));
#endif #endif
if (ret) return MOSQ_ERR_UNKNOWN; if(ret) return MOSQ_ERR_UNKNOWN;
return MOSQ_ERR_SUCCESS; return MOSQ_ERR_SUCCESS;
} }
#ifdef WITH_TCP_USER_TIMEOUT
static int bridge__set_tcp_user_timeout(struct mosquitto *context) {
int timeout = context->bridge->tcp_user_timeout;
if(timeout >= 0) {
if(setsockopt(context->sock, IPPROTO_TCP, TCP_USER_TIMEOUT, (char *)&timeout, sizeof(timeout))) {
return MOSQ_ERR_UNKNOWN;
}
}
return MOSQ_ERR_SUCCESS;
}
#endif
#if defined(__GLIBC__) && defined(WITH_ADNS) #if defined(__GLIBC__) && defined(WITH_ADNS)
static int bridge__connect_step1(struct mosquitto *context) static int bridge__connect_step1(struct mosquitto *context)
{ {
@ -373,6 +386,9 @@ int bridge__connect_step3(struct mosquitto *context)
} }
if (bridge__set_tcp_keepalive(context) != MOSQ_ERR_SUCCESS) return MOSQ_ERR_UNKNOWN; if (bridge__set_tcp_keepalive(context) != MOSQ_ERR_SUCCESS) return MOSQ_ERR_UNKNOWN;
#ifdef WITH_TCP_USER_TIMEOUT
if(bridge__set_tcp_user_timeout(context)) return MOSQ_ERR_UNKNOWN;
#endif
if(context->bridge->max_topic_alias != 0){ if(context->bridge->max_topic_alias != 0){
topic_alias_max.next = NULL; topic_alias_max.next = NULL;
@ -526,6 +542,9 @@ int bridge__connect(struct mosquitto *context)
HASH_ADD(hh_sock, db.contexts_by_sock, sock, sizeof(context->sock), context); HASH_ADD(hh_sock, db.contexts_by_sock, sock, sizeof(context->sock), context);
if (bridge__set_tcp_keepalive(context) != MOSQ_ERR_SUCCESS) return MOSQ_ERR_UNKNOWN; if (bridge__set_tcp_keepalive(context) != MOSQ_ERR_SUCCESS) return MOSQ_ERR_UNKNOWN;
#ifdef WITH_TCP_USER_TIMEOUT
if(bridge__set_tcp_user_timeout(context)) return MOSQ_ERR_UNKNOWN;
#endif
if(context->bridge->max_topic_alias){ if(context->bridge->max_topic_alias){
topic_alias_max.next = NULL; topic_alias_max.next = NULL;

@ -1273,6 +1273,22 @@ static int config__read_file_core(struct mosquitto__config *config, bool reload,
cur_bridge->tcp_keepalive_counter = (unsigned int)tmp_int; cur_bridge->tcp_keepalive_counter = (unsigned int)tmp_int;
#else #else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge support not available."); log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge support not available.");
#endif
}else if(!strcmp(token, "bridge_tcp_user_timeout")){
#if defined(WITH_BRIDGE) && defined(WITH_TCP_USER_TIMEOUT)
if(!cur_bridge){
log__printf(NULL, MOSQ_LOG_ERR, "Error: Invalid bridge configuration.");
return MOSQ_ERR_INVAL;
}
if(conf__parse_int(&token, "bridge_tcp_user_timeout", &tmp_int, &saveptr)) return MOSQ_ERR_INVAL;
if(tmp_int < 0) {
log__printf(NULL, MOSQ_LOG_ERR, "Error: invalid TCP user timeout value.");
return MOSQ_ERR_INVAL;
}
cur_bridge->tcp_user_timeout = (unsigned int) tmp_int;
#else
log__printf(NULL, MOSQ_LOG_WARNING, "Warning: Bridge and/or TCP user timeout support not available.");
#endif #endif
}else if(!strcmp(token, "bridge_tls_version")){ }else if(!strcmp(token, "bridge_tls_version")){
#if defined(WITH_BRIDGE) && defined(WITH_TLS) #if defined(WITH_BRIDGE) && defined(WITH_TLS)
@ -1416,6 +1432,9 @@ static int config__read_file_core(struct mosquitto__config *config, bool reload,
cur_bridge->clean_start_local = -1; cur_bridge->clean_start_local = -1;
cur_bridge->reload_type = brt_lazy; cur_bridge->reload_type = brt_lazy;
cur_bridge->max_topic_alias = 10; cur_bridge->max_topic_alias = 10;
#ifdef WITH_TCP_USER_TIMEOUT
cur_bridge->tcp_user_timeout = -1;
#endif
}else{ }else{
log__printf(NULL, MOSQ_LOG_ERR, "Error: Empty connection value in configuration."); log__printf(NULL, MOSQ_LOG_ERR, "Error: Empty connection value in configuration.");
return MOSQ_ERR_INVAL; return MOSQ_ERR_INVAL;

@ -30,6 +30,10 @@ Contributors:
# endif # endif
#endif #endif
#ifdef __linux__
#define WITH_TCP_USER_TIMEOUT
#endif
#include "mosquitto_internal.h" #include "mosquitto_internal.h"
#include "mosquitto_broker.h" #include "mosquitto_broker.h"
#include "mosquitto_plugin.h" #include "mosquitto_plugin.h"
@ -533,6 +537,9 @@ struct mosquitto__bridge{
unsigned int tcp_keepalive_idle; unsigned int tcp_keepalive_idle;
unsigned int tcp_keepalive_interval; unsigned int tcp_keepalive_interval;
unsigned int tcp_keepalive_counter; unsigned int tcp_keepalive_counter;
#ifdef WITH_TCP_USER_TIMEOUT
unsigned int tcp_user_timeout;
#endif
struct mosquitto__bridge_topic *topics; struct mosquitto__bridge_topic *topics;
int topic_count; int topic_count;
bool topic_remapping; bool topic_remapping;

Loading…
Cancel
Save