Jack Hansdampf / mbed-mqtt-GSOE1

Dependents:   ESP8266MQTT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers LRegisterManager.cpp Source File

LRegisterManager.cpp

00001 /**************************************************************************************
00002  * Copyright (c) 2016, Tomoaki Yamaguchi
00003  *
00004  * All rights reserved. This program and the accompanying materials
00005  * are made available under the terms of the Eclipse Public License v1.0
00006  * and Eclipse Distribution License v1.0 which accompany this distribution.
00007  *
00008  * The Eclipse Public License is available at
00009  *    http://www.eclipse.org/legal/epl-v10.html
00010  * and the Eclipse Distribution License is available at
00011  *   http://www.eclipse.org/org/documents/edl-v10.php.
00012  *
00013  * Contributors:
00014  *    Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
00015  **************************************************************************************/
00016 
00017 #include <stdlib.h>
00018 #include <string.h>
00019 
00020 #include "LMqttsnClientApp.h"
00021 #include "LTimer.h"
00022 #include "LGwProxy.h"
00023 #include "LMqttsnClient.h"
00024 #include "LRegisterManager.h"
00025 
00026 using namespace std;
00027 using namespace linuxAsyncClient;
00028 
00029 extern void setUint16(uint8_t* pos, uint16_t val);
00030 extern LMqttsnClient* theClient;
00031 /*=====================================
00032  Class RegisterQue
00033  =====================================*/
00034 LRegisterManager::LRegisterManager()
00035 {
00036     _first = 0;
00037     _last = 0;
00038 }
00039 
00040 LRegisterManager::~LRegisterManager()
00041 {
00042     RegQueElement* elm = _first;
00043     RegQueElement* sav = 0;
00044     while (elm)
00045     {
00046         sav = elm->next;
00047         if (elm != 0)
00048         {
00049             free(elm);
00050         }
00051         elm = sav;
00052     }
00053 }
00054 
00055 RegQueElement* LRegisterManager::add(const char* topic, uint16_t msgId)
00056 {
00057     RegQueElement* elm = (RegQueElement*) calloc(1, sizeof(RegQueElement));
00058 
00059     if (elm)
00060     {
00061         if (_last == 0)
00062         {
00063             _first = elm;
00064             _last = elm;
00065         }
00066         else
00067         {
00068             elm->prev = _last;
00069             _last->next = elm;
00070             _last = elm;
00071         }
00072         elm->topicName = topic;
00073         elm->msgId = msgId;
00074         elm->retryCount = MQTTSN_RETRY_COUNT;
00075         elm->sendUTC = 0;
00076     }
00077     return elm;
00078 }
00079 
00080 void LRegisterManager::remove(RegQueElement* elm)
00081 {
00082     if (elm)
00083         {
00084             if (elm->prev == 0)
00085             {
00086                 _first = elm->next;
00087                 if (elm->next == 0)
00088                 {
00089                     _last = 0;
00090                 }
00091                 else
00092                 {
00093                     elm->next->prev = 0;
00094                     _last = elm->next;
00095                 }
00096             }
00097             else
00098             {
00099                 if ( elm->next == 0 )
00100                 {
00101                     _last = elm->prev;
00102                 }
00103                 elm->prev->next = elm->next;
00104             }
00105             free(elm);
00106         }
00107 }
00108 
00109 bool LRegisterManager::isDone(void)
00110 {
00111     return _first == 0;
00112 }
00113 
00114 const char* LRegisterManager::getTopic(uint16_t msgId)
00115 {
00116     RegQueElement* elm = _first;
00117     while (elm)
00118     {
00119         if (elm->msgId == msgId)
00120         {
00121             return elm->topicName;
00122         }
00123         else
00124         {
00125             elm = elm->next;
00126         }
00127     }
00128     return 0;
00129 }
00130 
00131 void LRegisterManager::send(RegQueElement* elm)
00132 {
00133     uint8_t msg[MQTTSN_MAX_MSG_LENGTH + 1];
00134     msg[0] = 6 + strlen(elm->topicName);
00135     msg[1] = MQTTSN_TYPE_REGISTER;
00136     msg[2] = msg[3] = 0;
00137     setUint16(msg + 4, elm->msgId);
00138     strcpy((char*) msg + 6, elm->topicName);
00139     theClient->getGwProxy()->connect();
00140     theClient->getGwProxy()->writeMsg(msg);
00141     elm->sendUTC = time(NULL);
00142     elm->retryCount--;
00143 }
00144 
00145 RegQueElement* LRegisterManager::getElement(const char* topicName)
00146 {
00147     RegQueElement* elm = _first;
00148     while (elm)
00149     {
00150         if (strcmp(elm->topicName, topicName))
00151         {
00152             elm = elm->next;
00153         }
00154         else
00155         {
00156             return elm;
00157         }
00158     }
00159     return 0;
00160 }
00161 
00162 RegQueElement* LRegisterManager::getElement(uint16_t msgId)
00163 {
00164     RegQueElement* elm = _first;
00165     while (elm)
00166     {
00167         if (elm->msgId == msgId)
00168         {
00169             break;
00170         }
00171         else
00172         {
00173             elm = elm->next;
00174         }
00175     }
00176     return elm;
00177 }
00178 
00179 void LRegisterManager::registerTopic(char* topicName)
00180 {
00181     RegQueElement* elm = getElement(topicName);
00182     if (elm == 0)
00183     {
00184         uint16_t msgId = theClient->getGwProxy()->getNextMsgId();
00185         elm = add(topicName, msgId);
00186         send(elm);
00187     }
00188 }
00189 
00190 void LRegisterManager::responceRegAck(uint16_t msgId, uint16_t topicId)
00191 {
00192     const char* topicName = getTopic(msgId);
00193     MQTTSN_topicTypes type = MQTTSN_TOPIC_TYPE_NORMAL;
00194     if (topicName)
00195     {
00196         theClient->getGwProxy()->getTopicTable()->setTopicId((char*) topicName, topicId,  type); // Add Topic to TopicTable
00197         RegQueElement* elm = getElement(msgId);
00198         remove(elm);
00199         theClient->getPublishManager()->sendSuspend((char*) topicName, topicId, type);
00200     }
00201 }
00202 
00203 void LRegisterManager::responceRegister(uint8_t* msg, uint16_t msglen)
00204 {
00205     // *msg is terminated with 0x00 by Network::getMessage()
00206     uint8_t regack[7];
00207     regack[0] = 7;
00208     regack[1] = MQTTSN_TYPE_REGACK;
00209     memcpy(regack + 2, msg + 1, 4);
00210 
00211     LTopic* tp = theClient->getGwProxy()->getTopicTable()->match((char*) msg + 5);
00212     if (tp)
00213     {
00214         TopicCallback callback = tp->getCallback();
00215         void* topicName = calloc(strlen((char*) msg + 5) + 1, sizeof(char));
00216         theClient->getGwProxy()->getTopicTable()->add((char*) topicName, MQTTSN_TOPIC_TYPE_NORMAL, 0, callback, 1);
00217         regack[6] = MQTTSN_RC_ACCEPTED;
00218     }
00219     else
00220     {
00221         regack[6] = MQTTSN_RC_REJECTED_INVALID_TOPIC_ID;
00222     }
00223     theClient->getGwProxy()->writeMsg(regack);
00224 }
00225 
00226 uint8_t LRegisterManager::checkTimeout(void)
00227 {
00228     RegQueElement* elm = _first;
00229     RegQueElement* sav;
00230     while (elm)
00231     {
00232         if (elm->sendUTC + MQTTSN_TIME_RETRY < time(NULL))
00233         {
00234             if (elm->retryCount >= 0)
00235             {
00236                 send(elm);
00237             }
00238             else
00239             {
00240                 if (elm->next)
00241                 {
00242                     sav = elm->prev;
00243                     remove(elm);
00244                     if (sav)
00245                     {
00246                         elm = sav;
00247                     }
00248                     else
00249                     {
00250                         break;
00251                     }
00252                 }
00253                 else
00254                 {
00255                     remove(elm);
00256                     break;
00257                 }
00258             }
00259         }
00260         elm = elm->next;
00261     }
00262     return 0;
00263 }