A small footprint MQTT library

Dependents:   STM32F746_iothub_client_sample_mqtt FXOS8700CQ_To_Azure_IoT f767zi_mqtt FXOS8700CQ_To_Azure_IoT ... more

Revision:
23:80794cfb3565
Parent:
19:e283dcf26037
Child:
24:75f5b91d1c6e
--- a/mqtt_client.c	Fri Nov 17 13:58:21 2017 -0800
+++ b/mqtt_client.c	Wed Jan 17 08:57:29 2018 -0800
@@ -16,7 +16,6 @@
 #include "azure_umqtt_c/mqtt_codec.h"
 #include <inttypes.h>
 
-#define KEEP_ALIVE_BUFFER_SEC           10
 #define VARIABLE_HEADER_OFFSET          2
 #define RETAIN_FLAG_MASK                0x1
 #define QOS_LEAST_ONCE_FLAG_MASK        0x2
@@ -25,7 +24,7 @@
 #define CONNECT_PACKET_MASK             0xf0
 #define TIME_MAX_BUFFER                 16
 #define DEFAULT_MAX_PING_RESPONSE_TIME  80  // % of time to send pings
-#define MAX_CLOSE_RETRIES               10
+#define MAX_CLOSE_RETRIES               2
 
 static const char* TRUE_CONST = "true";
 static const char* FALSE_CONST = "false";
@@ -73,16 +72,26 @@
 
 static void close_connection(MQTT_CLIENT* mqtt_client)
 {
-    (void)xio_close(mqtt_client->xioHandle, on_connection_closed, mqtt_client);
-    if (mqtt_client->disconnect_cb == NULL)
+    if (mqtt_client->socketConnected)
     {
-        size_t counter = 0;
-        do
+        (void)xio_close(mqtt_client->xioHandle, on_connection_closed, mqtt_client);
+        if (mqtt_client->disconnect_cb == NULL)
         {
-            xio_dowork(mqtt_client->xioHandle);
-            counter++;
-            ThreadAPI_Sleep(2);
-        } while (mqtt_client->clientConnected && counter < MAX_CLOSE_RETRIES);
+            size_t counter = 0;
+            do
+            {
+                xio_dowork(mqtt_client->xioHandle);
+                counter++;
+                ThreadAPI_Sleep(2);
+            } while (mqtt_client->clientConnected && counter < MAX_CLOSE_RETRIES);
+        }
+    }
+    else
+    {
+        if (mqtt_client->disconnect_cb)
+        {
+            mqtt_client->disconnect_cb(mqtt_client->disconnect_ctx);
+        }
     }
 }
 
@@ -1153,43 +1162,56 @@
     }
     else
     {
-        BUFFER_HANDLE disconnectPacket = mqtt_codec_disconnect();
-        if (disconnectPacket == NULL)
+        if (mqtt_client->clientConnected)
         {
-            /*Codes_SRS_MQTT_CLIENT_07_011: [If any failure is encountered then mqtt_client_disconnect shall return a non-zero value.]*/
-            LOG(AZ_LOG_ERROR, LOG_LINE, "Error: mqtt_client_disconnect failed");
-            mqtt_client->packetState = PACKET_TYPE_ERROR;
-            result = __FAILURE__;
-        }
-        else
-        {
-            /* Codes_SRS_MQTT_CLIENT_07_037: [ if callback is not NULL callback shall be called once the mqtt connection has been disconnected ] */
-            mqtt_client->disconnect_cb = callback;
-            mqtt_client->disconnect_ctx = ctx;
-            mqtt_client->packetState = DISCONNECT_TYPE;
-
-            size_t size = BUFFER_length(disconnectPacket);
-            /*Codes_SRS_MQTT_CLIENT_07_012: [On success mqtt_client_disconnect shall send the MQTT DISCONNECT packet to the endpoint.]*/
-            if (sendPacketItem(mqtt_client, BUFFER_u_char(disconnectPacket), size) != 0)
+            BUFFER_HANDLE disconnectPacket = mqtt_codec_disconnect();
+            if (disconnectPacket == NULL)
             {
                 /*Codes_SRS_MQTT_CLIENT_07_011: [If any failure is encountered then mqtt_client_disconnect shall return a non-zero value.]*/
-                LOG(AZ_LOG_ERROR, LOG_LINE, "Error: mqtt_client_disconnect send failed");
+                LOG(AZ_LOG_ERROR, LOG_LINE, "Error: mqtt_client_disconnect failed");
+                mqtt_client->packetState = PACKET_TYPE_ERROR;
                 result = __FAILURE__;
             }
             else
             {
-                if (mqtt_client->logTrace)
+                /* Codes_SRS_MQTT_CLIENT_07_037: [ if callback is not NULL callback shall be called once the mqtt connection has been disconnected ] */
+                mqtt_client->disconnect_cb = callback;
+                mqtt_client->disconnect_ctx = ctx;
+                mqtt_client->packetState = DISCONNECT_TYPE;
+
+                size_t size = BUFFER_length(disconnectPacket);
+                /*Codes_SRS_MQTT_CLIENT_07_012: [On success mqtt_client_disconnect shall send the MQTT DISCONNECT packet to the endpoint.]*/
+                if (sendPacketItem(mqtt_client, BUFFER_u_char(disconnectPacket), size) != 0)
                 {
-                    STRING_HANDLE trace_log = STRING_construct("DISCONNECT");
-                    log_outgoing_trace(mqtt_client, trace_log);
-                    STRING_delete(trace_log);
+                    /*Codes_SRS_MQTT_CLIENT_07_011: [If any failure is encountered then mqtt_client_disconnect shall return a non-zero value.]*/
+                    LOG(AZ_LOG_ERROR, LOG_LINE, "Error: mqtt_client_disconnect send failed");
+                    result = __FAILURE__;
                 }
-                result = 0;
+                else
+                {
+                    if (mqtt_client->logTrace)
+                    {
+                        STRING_HANDLE trace_log = STRING_construct("DISCONNECT");
+                        log_outgoing_trace(mqtt_client, trace_log);
+                        STRING_delete(trace_log);
+                    }
+                    result = 0;
+                }
+                BUFFER_delete(disconnectPacket);
             }
-            BUFFER_delete(disconnectPacket);
             clear_mqtt_options(mqtt_client);
             mqtt_client->xioHandle = NULL;
         }
+        else
+        {
+            // If the client is not connected then just close the underlying socket
+            mqtt_client->disconnect_cb = callback;
+            mqtt_client->disconnect_ctx = ctx;
+
+            close_connection(mqtt_client);
+            clear_mqtt_options(mqtt_client);
+            result = 0;
+        }
     }
     return result;
 }
@@ -1223,7 +1245,7 @@
                     mqtt_client->packetSendTimeMs = 0;
                     mqtt_client->packetState = UNKNOWN_TYPE;
                 }
-                else if ((((current_ms - mqtt_client->packetSendTimeMs) / 1000) + KEEP_ALIVE_BUFFER_SEC) > mqtt_client->keepAliveInterval)
+                else if (((current_ms - mqtt_client->packetSendTimeMs) / 1000) >= mqtt_client->keepAliveInterval)
                 {
                     /*Codes_SRS_MQTT_CLIENT_07_026: [if keepAliveInternal is > 0 and the send time is greater than the MQTT KeepAliveInterval then it shall construct an MQTT PINGREQ packet.]*/
                     BUFFER_HANDLE pingPacket = mqtt_codec_ping();