Selaa lähdekoodia

优化客户端销毁逻辑、更新测试用例、代码逻辑优化

ryancw 2 vuotta sitten
vanhempi
sitoutus
2138d2a378

+ 2 - 1
.gitignore

@@ -5,4 +5,5 @@
 platform/linux/*
 platform/FreeRTOS/*
 
-null
+null
+.vscode

+ 7 - 6
example/RyanMqttTest.c

@@ -240,7 +240,7 @@ static int MqttConnect(int argc, char *argv[])
 {
     if (RyanMqttConnectState == RyanMqttGetState(client))
     {
-        rlog_w("mqtt客户端没有连接");
+        rlog_w("mqtt客户端已经连接,请不要重复连接");
         return 0;
     }
 
@@ -316,6 +316,7 @@ static int MqttReconnect(int argc, char *argv[])
 static int MqttDestroy(int argc, char *argv[])
 {
     RyanMqttDestroy(client);
+    client = NULL;
     return 0;
 }
 
@@ -554,22 +555,22 @@ static const struct RyanMqttCmdDes cmdTab[] =
         // {"disc",        "mqtt客户端断开连接         params: null", MqttDisconnect},
         // {"reconnect",   "mqtt断开连接时重新连接     params: null", MqttReconnect},
         // {"destory",     "mqtt销毁客户端             params: null", MqttDestroy},
-        // {"pub",         "mqtt发布消息               params: topic、 qos、 payload内容、 发送条数、 间隔时间(可以为0)", Mqttpublish},
-        // {"sub",         "mqtt订阅主题               params: topic、 qos", Mqttsubscribe},
+        // {"pub",         "mqtt发布消息               params: topic、qos、payload内容、发送条数、间隔时间(可以为0)", Mqttpublish},
+        // {"sub",         "mqtt订阅主题               params: topic、qos", Mqttsubscribe},
         // {"unsub",       "mqtt取消订阅主题           params: 取消订阅主题", MqttUnSubscribe},
         // {"listsub",     "mqtt获取已订阅主题         params: null", MqttListSubscribe},
         // {"listack",     "打印ack链表                params: null", MqttListAck},
         // {"listmsg",     "打印msg链表                params: null", MqttListMsg},
         // {"data",        "打印测试信息用户自定义的    params: null", Mqttdata},
 
-        {"help", "打印帮助信息", MqttHelp},
+        {"help", "打印帮助信息               params: null", MqttHelp},
         {"state", "打印mqtt客户端状态         params: null", MqttState},
         {"connect", "mqtt客户端连接服务器       params: null", MqttConnect},
         {"disc", "mqtt客户端断开连接         params: null", MqttDisconnect},
         {"reconnect", "mqtt断开连接时重新连接     params: null", MqttReconnect},
         {"destory", "mqtt销毁客户端             params: null", MqttDestroy},
-        {"pub", "mqtt发布消息               params: topic、 qos、 payload内容、 发送条数、 间隔时间(可以为0)", Mqttpublish},
-        {"sub", "mqtt订阅主题               params: topic、 qos", Mqttsubscribe},
+        {"pub", "mqtt发布消息               params: topic、qos、payload内容、发送条数、间隔时间(可以为0)", Mqttpublish},
+        {"sub", "mqtt订阅主题               params: topic、qos", Mqttsubscribe},
         {"unsub", "mqtt取消订阅主题           params: 取消订阅主题", MqttUnSubscribe},
         {"listsub", "mqtt获取已订阅主题         params: null", MqttListSubscribe},
         {"listack", "打印ack链表                params: null", MqttListAck},

+ 20 - 3
mqttclient/RyanMqttClient.c

@@ -98,6 +98,7 @@ RyanMqttError_e RyanMqttInit(RyanMqttClient_t **pClient)
  *  由于直接删除mqtt线程是很危险的行为。这里设置标志位,由mqtt线程自己删除自己所有资源。
  *  mqtt删除自己的延时最大不会超过config里面 recvTimeout + 1秒
  *  mqtt删除自己前会调用 RyanMqttEventDestoryBefore 事件回调
+ *  * 调用此函数后就不应该在对该客户端进行任何操作
  * @param client
  * @return RyanMqttError_e
  */
@@ -233,12 +234,17 @@ RyanMqttError_e RyanMqttSubscribe(RyanMqttClient_t *client, char *topic, RyanMqt
     // 确定节点是否已存在,存在就删除
     result = RyanMqttAckListNodeFind(client, SUBACK, packetId, &ackHandler);
     if (RyanMqttSuccessError == result)
+    {
+        RyanMqttAckListRemove(client, ackHandler);
         RyanMqttAckHandlerDestroy(client, ackHandler);
+    }
 
     result = RyanMqttAckListAdd(client, ackHandler);
 
     result = RyanMqttSendPacket(client, ackHandler->packet, ackHandler->packetLen);
-    RyanMqttCheckCode(RyanMqttSuccessError == result, result, rlog_d, { RyanMqttAckHandlerDestroy(client, ackHandler); });
+    RyanMqttCheckCode(RyanMqttSuccessError == result, result, rlog_d,
+                      { RyanMqttAckListRemove(client, ackHandler);
+                        RyanMqttAckHandlerDestroy(client, ackHandler); });
     return result;
 }
 
@@ -282,12 +288,17 @@ RyanMqttError_e RyanMqttUnSubscribe(RyanMqttClient_t *client, char *topic)
     // 确定节点是否已存在,存在就删除
     result = RyanMqttAckListNodeFind(client, UNSUBACK, packetId, &ackHandler);
     if (RyanMqttSuccessError == result)
+    {
+        RyanMqttAckListRemove(client, ackHandler);
         RyanMqttAckHandlerDestroy(client, ackHandler);
+    }
 
     result = RyanMqttAckListAdd(client, ackHandler);
 
     result = RyanMqttSendPacket(client, ackHandler->packet, ackHandler->packetLen);
-    RyanMqttCheckCode(RyanMqttSuccessError == result, result, rlog_d, { RyanMqttAckHandlerDestroy(client, ackHandler); });
+    RyanMqttCheckCode(RyanMqttSuccessError == result, result, rlog_d,
+                      { RyanMqttAckListRemove(client, ackHandler);
+                        RyanMqttAckHandlerDestroy(client, ackHandler); });
 
     return result;
 }
@@ -359,12 +370,17 @@ RyanMqttError_e RyanMqttPublish(RyanMqttClient_t *client, char *topic, char *pay
     // 确定节点是否已存在,存在就删除,理论上不会存在
     result = RyanMqttAckListNodeFind(client, (RyanMqttQos1 == qos) ? PUBACK : PUBREC, packetId, &ackHandler);
     if (RyanMqttSuccessError == result)
+    {
+        RyanMqttAckListRemove(client, ackHandler);
         RyanMqttAckHandlerDestroy(client, ackHandler);
+    }
 
     result = RyanMqttAckListAdd(client, ackHandler);
 
     result = RyanMqttSendPacket(client, ackHandler->packet, ackHandler->packetLen);
-    RyanMqttCheckCode(RyanMqttSuccessError == result, result, rlog_d, { RyanMqttAckHandlerDestroy(client, ackHandler); });
+    RyanMqttCheckCode(RyanMqttSuccessError == result, result, rlog_d,
+                      { RyanMqttAckListRemove(client, ackHandler);
+                        RyanMqttAckHandlerDestroy(client, ackHandler); });
 
     // 提前设置重发标志位
     RyanMqttSetPublishDup(&ackHandler->packet[0], 1);
@@ -614,6 +630,7 @@ RyanMqttError_e RyanMqttDiscardAckHandler(RyanMqttClient_t *client, enum msgType
 
     RyanMqttEventMachine(client, RyanMqttEventAckHandlerdiscard, (void *)ackHandler); // 回调函数
 
+    RyanMqttAckListRemove(client, ackHandler);
     RyanMqttAckHandlerDestroy(client, ackHandler);
     return RyanMqttSuccessError;
 }

+ 16 - 15
mqttclient/RyanMqttPublic.h

@@ -81,22 +81,23 @@ extern "C"
     typedef enum
     {
         RyanMqttEventError = RyanMqttBit0,                 // 保留事件
-        RyanMqttEventConnected = RyanMqttBit1,             // 连接成功 正数为RyanMqttConnectStatus_e*,负数为RyanMqttError_e*
-        RyanMqttEventDisconnected = RyanMqttBit2,          // 可能由用户触发,断开连接 正数为RyanMqttConnectStatus_e*,负数为RyanMqttError_e*
-        RyanMqttEventSubscribed = RyanMqttBit3,            // 订阅成功事件,服务端可以授予比订阅者要求的低的QoS等级。 RyanMqttMsgHandler_t*
-        RyanMqttEventSubscribedFaile = RyanMqttBit4,       // 订阅失败事件,超时 / 服务器返回订阅失败 RyanMqttMsgHandler_t*
-        RyanMqttEventUnSubscribed = RyanMqttBit5,          // 取消订阅事件 RyanMqttMsgHandler_t*
-        RyanMqttEventUnSubscribedFaile = RyanMqttBit6,     // 取消订阅失败事件,超时 RyanMqttMsgHandler_t*
-        RyanMqttEventPublished = RyanMqttBit7,             // qos1 / qos2发送成功事件。发送没有失败,只会重发或者用户手动丢弃。RyanMqttAckHandler_t*
-        RyanMqttEventRepeatPublishPacket = RyanMqttBit8,   // qos1 / qos2数据(或者ack)重发回调函数 RyanMqttAckHandler_t*
-        RyanMqttEventAckRepeatCountWarning = RyanMqttBit9, // ack重发次数超过警戒值 RyanMqttAckHandler_t*
-        RyanMqttEventAckCountWarning = RyanMqttBit10,      // ack记数值超过警戒值 uint16_t* ackHandlerCount; // 等待ack的记录个数
-        RyanMqttEventAckHandlerdiscard = RyanMqttBit11,    /*!< 用户触发,ack句柄丢弃事件,由用户手动调用RyanMqttDestroyAckHandler函数触发
-                                                            * 可能是发送qos1 / qos2消息丢弃 ack丢弃,也可能是publish报文的ack丢弃 RyanMqttAckHandler_t*
+        RyanMqttEventConnected = RyanMqttBit1,             // 连接成功                                                      eventData: 正数为RyanMqttConnectStatus_e*, 负数为RyanMqttError_e*
+        RyanMqttEventDisconnected = RyanMqttBit2,          // 可能由用户触发,断开连接                                        eventData: 正数为RyanMqttConnectStatus_e*, 负数为RyanMqttError_e*
+        RyanMqttEventSubscribed = RyanMqttBit3,            // 订阅成功事件,服务端可以授予比订阅者要求的低的QoS等级。            eventData: RyanMqttMsgHandler_t*
+        RyanMqttEventSubscribedFaile = RyanMqttBit4,       // 订阅失败事件,超时 / 服务器返回订阅失败                           eventData: RyanMqttMsgHandler_t*
+        RyanMqttEventUnSubscribed = RyanMqttBit5,          // 取消订阅事件                                                   eventData: RyanMqttMsgHandler_t*
+        RyanMqttEventUnSubscribedFaile = RyanMqttBit6,     // 取消订阅失败事件,超时                                          eventData: RyanMqttMsgHandler_t*
+        RyanMqttEventPublished = RyanMqttBit7,             // qos1 / qos2发送成功事件。发送没有失败,只会重发或者用户手动丢弃。   eventData: RyanMqttAckHandler_t*
+        RyanMqttEventRepeatPublishPacket = RyanMqttBit8,   // qos1 / qos2数据(或者ack)重发回调函数                            eventData: RyanMqttAckHandler_t*
+        RyanMqttEventAckRepeatCountWarning = RyanMqttBit9, // ack重发次数超过警戒值                                           eventData: RyanMqttAckHandler_t*
+        RyanMqttEventAckCountWarning = RyanMqttBit10,      // ack记数值超过警戒值                                             eventData: uint16_t* ackHandlerCount;  等待ack的记录个数
+        RyanMqttEventAckHandlerdiscard = RyanMqttBit11,    /* 用户触发,ack句柄丢弃事件,由用户手动调用RyanMqttDestroyAckHandler函数触发
+                                                            * 可能是发送qos1 / qos2消息丢弃、ack丢弃,也可能是publish报文的ack丢弃
+                                                            * eventData: RyanMqttAckHandler_t*
                                                             */
-        RyanMqttEventReconnectBefore = RyanMqttBit12,      // 重连前事件,用户可以在此时更改connect信息 NULL
-        RyanMqttEventDestoryBefore = RyanMqttBit13,        // 用户触发,销毁客户端前回调 NULL
-        RyanMqttEventData = RyanMqttBit14,                 // 接收到订阅主题数据事件,支持通配符识别,返回的主题信息是报文主题 RyanMqttMsgData_t*
+        RyanMqttEventReconnectBefore = RyanMqttBit12,      // 重连前事件,用户可以在此时更改connect信息                          eventData: NULL
+        RyanMqttEventDestoryBefore = RyanMqttBit13,        // 用户触发,销毁客户端前回调                                        eventData: NULL
+        RyanMqttEventData = RyanMqttBit14,                 // 接收到订阅主题数据事件,支持通配符识别,返回的主题信息是报文主题       eventData: RyanMqttMsgData_t*
         RyanMqttEventAnyId = UINT32_MAX,
     } RyanMqttEventId_e;
 

+ 22 - 3
mqttclient/RyanMqttThread.c

@@ -104,6 +104,7 @@ static RyanMqttError_e RyanMqttPubackAndPubcompPacketHandler(RyanMqttClient_t *c
 
     RyanMqttEventMachine(client, RyanMqttEventPublished, (void *)ackHandler); // 回调函数
 
+    RyanMqttAckListRemove(client, ackHandler);
     RyanMqttAckHandlerDestroy(client, ackHandler); // 销毁ackHandler
     return result;
 }
@@ -140,7 +141,10 @@ static RyanMqttError_e RyanMqttPubrelPacketHandler(RyanMqttClient_t *client)
     // 删除pubrel记录
     result = RyanMqttAckListNodeFind(client, PUBREL, packetId, &ackHandler);
     if (RyanMqttSuccessError == result)
+    {
+        RyanMqttAckListRemove(client, ackHandler);
         RyanMqttAckHandlerDestroy(client, ackHandler);
+    }
 
     return RyanMqttSuccessError;
 }
@@ -174,11 +178,15 @@ static RyanMqttError_e RyanMqttPubrecPacketHandler(RyanMqttClient_t *client)
         // 查找ack链表是否存在pubcomp报文,不存在表示首次接收到
         result = RyanMqttAckListNodeFind(client, PUBCOMP, packetId, &ackHandler);
         if (RyanMqttSuccessError != result)
+        {
             fastFlag = RyanMqttTrue;
-
+        }
         // 出现pubrec和pubcomp同时存在的情况,清除pubrec理论上不会出现
         else
+        {
+            RyanMqttAckListRemove(client, ackHandlerPubrec);
             RyanMqttAckHandlerDestroy(client, ackHandlerPubrec);
+        }
     }
 
     // 制作确认数据包并发送
@@ -213,6 +221,7 @@ static RyanMqttError_e RyanMqttPubrecPacketHandler(RyanMqttClient_t *client)
     {
         result = RyanMqttAckListAdd(client, ackHandler);
         // 保证等待PUBCOMP记录成功后再清除PUBREC记录
+        RyanMqttAckListRemove(client, ackHandlerPubrec);
         RyanMqttAckHandlerDestroy(client, ackHandlerPubrec);
     }
 
@@ -350,6 +359,7 @@ static RyanMqttError_e RyanMqttSubackHandler(RyanMqttClient_t *client)
     {
         // mqtt事件回调
         RyanMqttEventMachine(client, RyanMqttEventSubscribedFaile, (void *)ackHandler->msgHandler);
+        RyanMqttAckListRemove(client, ackHandler);
         RyanMqttAckHandlerDestroy(client, ackHandler); // 销毁ackHandler
         return RyanMqttSuccessError;
     }
@@ -358,7 +368,10 @@ static RyanMqttError_e RyanMqttSubackHandler(RyanMqttClient_t *client)
     // 查找是否有同名订阅,如果有就销毁之前的
     result = RyanMqttMsgHandlerFind(client, ackHandler->msgHandler->topic, strlen(ackHandler->msgHandler->topic), RyanMqttFalse, &msgHandler);
     if (RyanMqttSuccessError == result)
+    {
+        RyanMqttMsgHandlerRemove(msgHandler);
         RyanMqttMsgHandlerDestory(msgHandler);
+    }
 
     // 服务端可以授予比订阅者要求的低一些的 QoS 等级。
     result = RyanMqttMsgHandlerCreate(ackHandler->msgHandler->topic,
@@ -368,7 +381,8 @@ static RyanMqttError_e RyanMqttSubackHandler(RyanMqttClient_t *client)
 
     RyanMqttMsgHandlerAdd(client, msgHandler);                                 // 将msg信息添加到订阅链表上
     RyanMqttEventMachine(client, RyanMqttEventSubscribed, (void *)msgHandler); // mqtt回调函数
-    RyanMqttAckHandlerDestroy(client, ackHandler);                             // 销毁ackHandler
+    RyanMqttAckListRemove(client, ackHandler);
+    RyanMqttAckHandlerDestroy(client, ackHandler); // 销毁ackHandler
 
     return result;
 }
@@ -396,6 +410,7 @@ static RyanMqttError_e RyanMqttUnSubackHandler(RyanMqttClient_t *client)
     // mqtt事件回调
     RyanMqttEventMachine(client, RyanMqttEventUnSubscribed, (void *)ackHandler->msgHandler);
 
+    RyanMqttAckListRemove(client, ackHandler);
     RyanMqttAckHandlerDestroy(client, ackHandler); // 销毁ackHandler
 
     return result;
@@ -553,6 +568,7 @@ static void RyanMqttAckListScan(RyanMqttClient_t *client, RyanMqttBool_e WaitFla
             RyanMqttEventMachine(client, (SUBACK == ackHandler->packetType) ? RyanMqttEventSubscribedFaile : RyanMqttEventUnSubscribedFaile,
                                  (void *)ackHandler->msgHandler);
             // 清除句柄
+            RyanMqttAckListRemove(client, ackHandler);
             RyanMqttAckHandlerDestroy(client, ackHandler);
             break;
         }
@@ -757,6 +773,9 @@ void RyanMqttThread(void *argument)
             // 清除session  ack链表和msg链表
             RyanMqttCleanSession(client);
 
+            platformThread_t mqttThread = *client->mqttThread;
+            void *userData = client->config->userData;
+
             // 清除掉线程动态资源
             platformMemoryFree(client->mqttThread);
             client->mqttThread = NULL;
@@ -765,7 +784,7 @@ void RyanMqttThread(void *argument)
             client = NULL;
 
             // 销毁自身线程
-            platformThreadDestroy(client->config->userData, client->mqttThread);
+            platformThreadDestroy(userData, &mqttThread);
         }
 
         // 客户端状态变更状态机

+ 46 - 11
mqttclient/RyanMqttUtile.c

@@ -343,8 +343,6 @@ void RyanMqttMsgHandlerDestory(RyanMqttMsgHandler_t *msgHandler)
     RyanMqttAssert(NULL != msgHandler);
     RyanMqttAssert(NULL != msgHandler->topic);
 
-    RyanListDel(&msgHandler->list);
-
     platformMemoryFree(msgHandler->topic);
     msgHandler->topic = NULL;
 
@@ -422,6 +420,25 @@ RyanMqttError_e RyanMqttMsgHandlerAdd(RyanMqttClient_t *client, RyanMqttMsgHandl
     return RyanMqttSuccessError;
 }
 
+/**
+ * @brief 将msg句柄client msg链表移除
+ *
+ * @param client
+ * @param msgHandler
+ * @return int32_t
+ */
+RyanMqttError_e RyanMqttMsgHandlerRemove(RyanMqttMsgHandler_t *msgHandler)
+{
+    RyanMqttAssert(NULL != msgHandler);
+    RyanMqttAssert(NULL != msgHandler->topic);
+
+    platformCriticalEnter();
+    RyanListDel(&msgHandler->list);
+    platformCriticalExit();
+
+    return RyanMqttSuccessError;
+}
+
 /**
  * @brief 创建ack句柄
  *
@@ -475,17 +492,9 @@ void RyanMqttAckHandlerDestroy(RyanMqttClient_t *client, RyanMqttAckHandler_t *a
     RyanMqttAssert(NULL != ackHandler->msgHandler);
     RyanMqttAssert(NULL != ackHandler->msgHandler->topic);
 
-    if (NULL == &ackHandler->list)
-        return;
-
-    RyanListDel(&ackHandler->list);
-
+    RyanMqttMsgHandlerRemove(ackHandler->msgHandler);
     RyanMqttMsgHandlerDestory(ackHandler->msgHandler); // 释放msgHandler
-
     platformMemoryFree(ackHandler);
-
-    if (client->ackHandlerCount > 0)
-        client->ackHandlerCount--;
 }
 
 /**
@@ -549,6 +558,30 @@ RyanMqttError_e RyanMqttAckListAdd(RyanMqttClient_t *client, RyanMqttAckHandler_
     return RyanMqttSuccessError;
 }
 
+/**
+ * @brief 从链表移除ack
+ *
+ * @param client
+ * @param ackHandler
+ * @return RyanMqttError_e
+ */
+RyanMqttError_e RyanMqttAckListRemove(RyanMqttClient_t *client, RyanMqttAckHandler_t *ackHandler)
+{
+    RyanMqttAssert(NULL != client);
+    RyanMqttAssert(NULL != ackHandler);
+    RyanMqttAssert(NULL != ackHandler->msgHandler);
+    RyanMqttAssert(NULL != ackHandler->msgHandler->topic);
+
+    // 将ack节点添加到链表尾部
+    platformCriticalEnter();
+    RyanListDel(&ackHandler->list);
+    if (client->ackHandlerCount > 0)
+        client->ackHandlerCount--;
+    platformCriticalExit();
+
+    return RyanMqttSuccessError;
+}
+
 /**
  * @brief 清理session
  *
@@ -568,6 +601,7 @@ void RyanMqttCleanSession(RyanMqttClient_t *client)
         RyanListForEachSafe(curr, next, &client->ackHandlerList)
         {
             ackHandler = RyanListEntry(curr, RyanMqttAckHandler_t, list);
+            RyanMqttAckListRemove(client, ackHandler);
             RyanMqttAckHandlerDestroy(client, ackHandler);
         }
         RyanListDelInit(&client->ackHandlerList);
@@ -579,6 +613,7 @@ void RyanMqttCleanSession(RyanMqttClient_t *client)
         RyanListForEachSafe(curr, next, &client->msgHandlerList)
         {
             msgHandler = RyanListEntry(curr, RyanMqttMsgHandler_t, list);
+            RyanMqttMsgHandlerRemove(msgHandler);
             RyanMqttMsgHandlerDestory(msgHandler);
         }
         RyanListDelInit(&client->msgHandlerList);

+ 7 - 5
mqttclient/RyanMqttUtile.h

@@ -20,15 +20,17 @@ extern "C"
     extern RyanMqttError_e RyanMqttSendPacket(RyanMqttClient_t *client, char *buf, int32_t length);
     extern RyanMqttError_e RyanMqttRecvPacket(RyanMqttClient_t *client, char *buf, int32_t length);
 
-    extern RyanMqttError_e RyanMqttAckHandlerCreate(RyanMqttClient_t *client, enum msgTypes packetType, uint16_t packetId, uint16_t packetLen, RyanMqttMsgHandler_t *msgHandler, RyanMqttAckHandler_t **pAckHandler);
-    extern void RyanMqttAckHandlerDestroy(RyanMqttClient_t *client, RyanMqttAckHandler_t *ackHandler);
-    extern RyanMqttError_e RyanMqttAckListAdd(RyanMqttClient_t *client, RyanMqttAckHandler_t *ackHandler);
-    extern RyanMqttError_e RyanMqttAckListNodeFind(RyanMqttClient_t *client, enum msgTypes packetType, uint16_t packetId, RyanMqttAckHandler_t **pAckHandler);
-
     extern RyanMqttError_e RyanMqttMsgHandlerCreate(char *topic, uint16_t topicLen, RyanMqttQos_e qos, RyanMqttMsgHandler_t **pMsgHandler);
     extern void RyanMqttMsgHandlerDestory(RyanMqttMsgHandler_t *msgHandler);
     extern RyanMqttError_e RyanMqttMsgHandlerFind(RyanMqttClient_t *client, char *topic, uint16_t topicLen, RyanMqttBool_e topicMatchedFlag, RyanMqttMsgHandler_t **pMsgHandler);
     extern RyanMqttError_e RyanMqttMsgHandlerAdd(RyanMqttClient_t *client, RyanMqttMsgHandler_t *msgHandler);
+    extern RyanMqttError_e RyanMqttMsgHandlerRemove(RyanMqttMsgHandler_t *msgHandler);
+
+    extern RyanMqttError_e RyanMqttAckHandlerCreate(RyanMqttClient_t *client, enum msgTypes packetType, uint16_t packetId, uint16_t packetLen, RyanMqttMsgHandler_t *msgHandler, RyanMqttAckHandler_t **pAckHandler);
+    extern void RyanMqttAckHandlerDestroy(RyanMqttClient_t *client, RyanMqttAckHandler_t *ackHandler);
+    extern RyanMqttError_e RyanMqttAckListAdd(RyanMqttClient_t *client, RyanMqttAckHandler_t *ackHandler);
+    extern RyanMqttError_e RyanMqttAckListNodeFind(RyanMqttClient_t *client, enum msgTypes packetType, uint16_t packetId, RyanMqttAckHandler_t **pAckHandler);
+    extern RyanMqttError_e RyanMqttAckListRemove(RyanMqttClient_t *client, RyanMqttAckHandler_t *ackHandler);
 
     extern RyanMqttError_e RyanMqttStringCopy(char **dest, char *rest, uint32_t strLen);
     extern RyanMqttError_e RyanMqttSetPublishDup(char *headerBuf, uint8_t dup);