in source/MutualAuthMQTTExample.c [788:883]
static void prvMQTTSubscribeWithBackoffRetries( MQTTContext_t * pxMQTTContext )
{
MQTTStatus_t xResult = MQTTSuccess;
BackoffAlgorithmStatus_t xBackoffAlgStatus = BackoffAlgorithmSuccess;
BackoffAlgorithmContext_t xRetryParams;
uint16_t usNextRetryBackOff = 0U;
MQTTSubscribeInfo_t xMQTTSubscription[ mqttexampleTOPIC_COUNT ];
bool xFailedSubscribeToTopic = false;
uint32_t ulTopicCount = 0U;
/* Some fields not used by this demo so start with everything at 0. */
( void ) memset( ( void * ) &xMQTTSubscription, 0x00, sizeof( xMQTTSubscription ) );
/* Get a unique packet id. */
usSubscribePacketIdentifier = MQTT_GetPacketId( pxMQTTContext );
/* Subscribe to the mqttexampleTOPIC topic filter. This example subscribes to
* only one topic and uses QoS1. */
xMQTTSubscription[ 0 ].qos = MQTTQoS1;
xMQTTSubscription[ 0 ].pTopicFilter = pExampleTopic;
xMQTTSubscription[ 0 ].topicFilterLength = ( uint16_t ) strlen( pExampleTopic );
/* Initialize context for backoff retry attempts if SUBSCRIBE request fails. */
BackoffAlgorithm_InitializeParams( &xRetryParams,
mqttexampleRETRY_BACKOFF_BASE_MS,
mqttexampleRETRY_MAX_BACKOFF_DELAY_MS,
mqttexampleRETRY_MAX_ATTEMPTS );
do
{
/* The client is now connected to the broker. Subscribe to the topic
* as specified in mqttexampleTOPIC at the top of this file by sending a
* subscribe packet then waiting for a subscribe acknowledgment (SUBACK).
* This client will then publish to the same topic it subscribed to, so it
* will expect all the messages it sends to the broker to be sent back to it
* from the broker. This demo uses QOS0 in Subscribe, therefore, the Publish
* messages received from the broker will have QOS0. */
LogInfo( ( "Attempt to subscribe to the MQTT topic %s.\r\n", pExampleTopic ) );
xResult = MQTT_Subscribe( pxMQTTContext,
xMQTTSubscription,
sizeof( xMQTTSubscription ) / sizeof( MQTTSubscribeInfo_t ),
usSubscribePacketIdentifier );
configASSERT( xResult == MQTTSuccess );
LogInfo( ( "SUBSCRIBE sent for topic %s to broker.\n\n", pExampleTopic ) );
/* Process incoming packet from the broker. After sending the subscribe, the
* client may receive a publish before it receives a subscribe ack. Therefore,
* call generic incoming packet processing function. Since this demo is
* subscribing to the topic to which no one is publishing, probability of
* receiving Publish message before subscribe ack is zero; but application
* must be ready to receive any packet. This demo uses the generic packet
* processing function everywhere to highlight this fact. */
xResult = MQTT_ProcessLoop( pxMQTTContext, mqttexamplePROCESS_LOOP_TIMEOUT_MS );
configASSERT( xResult == MQTTSuccess );
/* Reset flag before checking suback responses. */
xFailedSubscribeToTopic = false;
/* Check if recent subscription request has been rejected. #xTopicFilterContext is updated
* in the event callback to reflect the status of the SUBACK sent by the broker. It represents
* either the QoS level granted by the server upon subscription, or acknowledgement of
* server rejection of the subscription request. */
for( ulTopicCount = 0; ulTopicCount < mqttexampleTOPIC_COUNT; ulTopicCount++ )
{
if( xTopicFilterContext[ ulTopicCount ].xSubAckStatus == MQTTSubAckFailure )
{
xFailedSubscribeToTopic = true;
/* Generate a random number and calculate backoff value (in milliseconds) for
* the next connection retry.
* Note: It is recommended to seed the random number generator with a device-specific
* entropy source so that possibility of multiple devices retrying failed network operations
* at similar intervals can be avoided. */
xBackoffAlgStatus = BackoffAlgorithm_GetNextBackoff( &xRetryParams, uxRand(), &usNextRetryBackOff );
if( xBackoffAlgStatus == BackoffAlgorithmRetriesExhausted )
{
LogError( ( "Server rejected subscription request. All retry attempts have exhausted. Topic=%s",
xTopicFilterContext[ ulTopicCount ].pcTopicFilter ) );
}
else if( xBackoffAlgStatus == BackoffAlgorithmSuccess )
{
LogWarn( ( "Server rejected subscription request. Attempting to re-subscribe to topic %s.",
xTopicFilterContext[ ulTopicCount ].pcTopicFilter ) );
/* Backoff before the next re-subscribe attempt. */
vTaskDelay( pdMS_TO_TICKS( usNextRetryBackOff ) );
}
break;
}
}
configASSERT( xBackoffAlgStatus != BackoffAlgorithmRetriesExhausted );
} while( ( xFailedSubscribeToTopic == true ) && ( xBackoffAlgStatus == BackoffAlgorithmSuccess ) );
}