From 5d4121da9de2be9dfa86485ba82c1d3b672d9222 Mon Sep 17 00:00:00 2001 From: Dom Postorivo Date: Fri, 27 Nov 2020 14:45:45 -0500 Subject: [PATCH] This keeps backwards compatibility by converting params from seconds if they are less than 100 (minInterval) or 1000 (maxInterval). This also makes the connectTimeout consistent with the reconnect interval params. Signed-off-by: Dom Postorivo --- src/MQTTAsync.c | 31 +++++++++++++++++++++++++------ src/MQTTAsync.h | 19 ++++++++++++++++--- src/MQTTAsyncUtils.c | 10 +++++----- src/MQTTAsyncUtils.h | 12 ++++++------ 4 files changed, 52 insertions(+), 20 deletions(-) diff --git a/src/MQTTAsync.c b/src/MQTTAsync.c index c6a11f6d3..5e0d3f6a2 100644 --- a/src/MQTTAsync.c +++ b/src/MQTTAsync.c @@ -645,7 +645,7 @@ int MQTTAsync_connect(MQTTAsync handle, const MQTTAsync_connectOptions* options) m->connect.onFailure5 = options->onFailure5; } m->connect.context = options->context; - m->connectTimeout = options->connectTimeout; + m->connectTimeoutMs = options->connectTimeout * 1000; /* don't lock async mutex if we are being called from a callback */ thread_id = Paho_thread_getid(); @@ -679,8 +679,27 @@ int MQTTAsync_connect(MQTTAsync handle, const MQTTAsync_connectOptions* options) if (options->struct_version >= 4) { m->automaticReconnect = options->automaticReconnect; - m->minRetryInterval = options->minRetryInterval; - m->maxRetryInterval = options->maxRetryInterval; + // Old retry time params were in seconds, but we want to support + // millisecond min retry intervals. + // To remain backwards compatible, if the param is under 100, we + // assume it's in seconds, otherwise, milliseconds. + if (options->minRetryInterval < 100) + { + m->minRetryIntervalMs = options->minRetryInterval * 1000; + } + else + { + m->minRetryIntervalMs = options->minRetryInterval; + } + // Similar for max interval, if it's under 1000, we assume seconds + if (options->maxRetryInterval < 1000) + { + m->maxRetryIntervalMs = options->maxRetryInterval * 1000; + } + else + { + m->maxRetryIntervalMs = options->maxRetryInterval; + } } if (options->struct_version >= 7) { @@ -847,7 +866,7 @@ int MQTTAsync_connect(MQTTAsync handle, const MQTTAsync_connectOptions* options) m->c->retryInterval = options->retryInterval; m->shouldBeConnected = 1; - m->connectTimeout = options->connectTimeout; + m->connectTimeoutMs = options->connectTimeout * 1000; MQTTAsync_freeServerURIs(m); if (options->struct_version >= 2 && options->serverURIcount > 0) @@ -949,8 +968,8 @@ int MQTTAsync_reconnect(MQTTAsync handle) if (m->shouldBeConnected) { m->reconnectNow = 1; - m->currentIntervalBase = m->minRetryInterval; - m->currentInterval = m->minRetryInterval; + m->currentIntervalBaseMs = m->minRetryIntervalMs; + m->currentIntervalMs = m->minRetryIntervalMs; m->retrying = 1; rc = MQTTASYNC_SUCCESS; } diff --git a/src/MQTTAsync.h b/src/MQTTAsync.h index e11af0482..39bfc1a39 100644 --- a/src/MQTTAsync.h +++ b/src/MQTTAsync.h @@ -1267,6 +1267,9 @@ typedef struct const char* password; /** * The time interval in seconds to allow a connect to complete. + * The time interval in milliseconds to allow a connect to complete. + * For backwards compatibility and consistency with the retry intervals + * this is considered to be seconds if it is under 1000. */ int connectTimeout; /** @@ -1324,15 +1327,25 @@ typedef struct */ int MQTTVersion; /** - * Reconnect automatically in the case of a connection being lost. 0=false, 1=true + * Reconnect automatically in the case of a connection being lost? + * This retries with exponential backoff starting from the minRetryInterval + * up to the maxRetryInterval, +/- 20% random jitter. */ int automaticReconnect; /** - * The minimum automatic reconnect retry interval in seconds. Doubled on each failed retry. + * Minimum retry interval in milliseconds. Doubled on each failed retry. + * For backwards compatibility, if the value is under 100, + * it is assumed to be in seconds rather than milliseconds. + * Random jitter is applied to the value with +/- 20% */ int minRetryInterval; /** - * The maximum automatic reconnect retry interval in seconds. The doubling stops here on failed retries. + * Maximum retry interval in milliseconds. The doubling stops here on failed retries. + * For backwards compatibility, if the value is under 1000, + * it is assumed to be in seconds rather than milliseconds. + * Note: due to random jitter, the actual max time interval could be as much as 20% higher, + * but this will change on each retry. + * e.g. for maxRetryInterval of 60 seconds, the actual wait time could be anywhere from 48 to 72 seconds */ int maxRetryInterval; /** diff --git a/src/MQTTAsyncUtils.c b/src/MQTTAsyncUtils.c index 6d9330403..245b5294d 100644 --- a/src/MQTTAsyncUtils.c +++ b/src/MQTTAsyncUtils.c @@ -923,14 +923,14 @@ void MQTTAsync_startConnectRetry(MQTTAsyncs* m) m->lastConnectionFailedTime = MQTTTime_start_clock(); if (m->retrying) { - m->currentIntervalBase = min(m->currentIntervalBase * 2, m->maxRetryInterval); + m->currentIntervalBaseMs = min(m->currentIntervalBaseMs * 2, m->maxRetryIntervalMs); } else { - m->currentIntervalBase = m->minRetryInterval; + m->currentIntervalBaseMs = m->minRetryIntervalMs; m->retrying = 1; } - m->currentInterval = MQTTAsync_randomJitter(m->currentIntervalBase, m->minRetryInterval, m->maxRetryInterval); + m->currentIntervalMs = MQTTAsync_randomJitter(m->currentIntervalBaseMs, m->minRetryIntervalMs, m->maxRetryIntervalMs); } } @@ -1701,7 +1701,7 @@ static void MQTTAsync_checkTimeouts(void) MQTTAsync_checkDisconnect(m, &m->disconnect); /* check connect timeout */ - if (m->c->connect_state != NOT_IN_PROGRESS && MQTTTime_elapsed(m->connect.start_time) > (ELAPSED_TIME_TYPE)(m->connectTimeout * 1000)) + if (m->c->connect_state != NOT_IN_PROGRESS && MQTTTime_elapsed(m->connect.start_time) > (ELAPSED_TIME_TYPE)(m->connectTimeoutMs)) { nextOrClose(m, MQTTASYNC_FAILURE, "TCP connect timeout"); continue; @@ -1715,7 +1715,7 @@ static void MQTTAsync_checkTimeouts(void) if (m->automaticReconnect && m->retrying) { - if (m->reconnectNow || MQTTTime_elapsed(m->lastConnectionFailedTime) > (ELAPSED_TIME_TYPE)(m->currentInterval * 1000)) + if (m->reconnectNow || MQTTTime_elapsed(m->lastConnectionFailedTime) > (ELAPSED_TIME_TYPE)(m->currentIntervalMs)) { /* to reconnect put the connect command to the head of the command queue */ MQTTAsync_queuedCommand* conn = malloc(sizeof(MQTTAsync_queuedCommand)); diff --git a/src/MQTTAsyncUtils.h b/src/MQTTAsyncUtils.h index 0e08beac1..72576d1a1 100644 --- a/src/MQTTAsyncUtils.h +++ b/src/MQTTAsyncUtils.h @@ -126,16 +126,16 @@ typedef struct MQTTAsync_struct int shouldBeConnected; int noBufferedMessages; /* the current number of buffered (publish) messages for this client */ - /* added for automatic reconnect */ + /* added for automatic reconnect, intervals are in MS */ int automaticReconnect; - int minRetryInterval; - int maxRetryInterval; + int minRetryIntervalMs; + int maxRetryIntervalMs; int serverURIcount; char** serverURIs; - int connectTimeout; + int connectTimeoutMs; - int currentInterval; - int currentIntervalBase; + int currentIntervalMs; + int currentIntervalBaseMs; START_TIME_TYPE lastConnectionFailedTime; int retrying; int reconnectNow;