Jack Hansdampf / mbed-mqtt-GSOE1

Dependents:   ESP8266MQTT

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers MQTTSNGWClientList.cpp Source File

MQTTSNGWClientList.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  *    Tieto Poland Sp. z o.o. - Gateway improvements
00016  **************************************************************************************/
00017 #include "MQTTSNGWClientList.h"
00018 #include "MQTTSNGateway.h"
00019 #include <string.h>
00020 #include <string>
00021 
00022 using namespace MQTTSNGW;
00023 extern Gateway* theGateway;
00024 /*=====================================
00025  Class ClientList
00026  =====================================*/
00027 const char* common_topic = "*";
00028 
00029 ClientList::ClientList()
00030 {
00031     _clientCnt = 0;
00032     _authorize = false;
00033     _firstClient = nullptr;
00034     _endClient = nullptr;
00035 }
00036 
00037 ClientList::~ClientList()
00038 {
00039     _mutex.lock();
00040     Client* cl = _firstClient;
00041     Client* ncl;
00042 
00043     while (cl != nullptr)
00044     {
00045         ncl = cl->_nextClient;
00046         delete cl;
00047         cl = ncl;
00048     };
00049     _mutex.unlock();
00050 }
00051 
00052 void ClientList::initialize(bool aggregate)
00053 {
00054     if (theGateway->getGWParams()->clientAuthentication )
00055     {
00056         int type = TRANSPEARENT_TYPE;
00057         if ( aggregate )
00058         {
00059             type = AGGREGATER_TYPE;
00060         }
00061         setClientList(type);
00062         _authorize = true;
00063     }
00064 }
00065 
00066 void ClientList::setClientList(int type)
00067 {
00068     char param[MQTTSNGW_PARAM_MAX];
00069     string fileName;
00070     GatewayParams* params = theGateway->getGWParams();
00071     if (theGateway->getParam("ClientsList", param) == 0)
00072     {
00073         fileName = string(param);
00074     }
00075     else
00076     {
00077         fileName = params->configDir + string(CLIENT_LIST);
00078     }
00079 
00080     if (!createList(fileName.c_str(), type))
00081     {
00082         throw Exception("ClientList::initialize(): No client list defined by the configuration.");
00083     }
00084 
00085     if ( params->clientListName == nullptr )
00086     {
00087         params->clientListName = strdup(fileName.c_str());
00088     }
00089 }
00090 
00091 void ClientList::setPredefinedTopics(bool aggrecate)
00092 {
00093     char param[MQTTSNGW_PARAM_MAX];
00094 
00095     string fileName;
00096     GatewayParams* params = theGateway->getGWParams();
00097 
00098     if (theGateway->getParam("PredefinedTopicList", param) == 0)
00099     {
00100         fileName = string(param);
00101     }
00102     else
00103     {
00104         fileName = params->configDir + string(PREDEFINEDTOPIC_FILE);
00105     }
00106 
00107     if ( readPredefinedList(fileName.c_str(), aggrecate) )
00108     {
00109         params->predefinedTopicFileName = strdup(fileName.c_str());
00110     }
00111 }
00112 
00113 /**
00114  * Create ClientList from a client list file.
00115  * @param File name of the client list
00116  * @return true: Reject client connection that is not registered in the client list
00117  *
00118  * File format is:
00119  *     Lines bigning with # are comment line.
00120  *     ClientId, SensorNetAddress, "unstableLine", "secureConnection"
00121  *     in case of UDP, SensorNetAddress format is portNo@IPAddress.
00122  *     if the SensorNetwork is not stable, write unstableLine.
00123  *     if BrokerConnection is SSL, write secureConnection.
00124  *     if the client send PUBLISH QoS-1, QoS-1 is required.
00125  *
00126  * Ex:
00127  *     #Client List
00128  *     ClientId1,11200@192.168.10.10
00129  *     ClientID2,35000@192.168.50.200,unstableLine
00130  *     ClientID3,40000@192.168.200.50,secureConnection
00131  *     ClientID4,41000@192.168.200.51,unstableLine,secureConnection
00132  *      ClientID5,41000@192.168.200.51,unstableLine,secureConnection,QoS-1
00133  */
00134 
00135 bool ClientList::createList(const char* fileName, int type)
00136 {
00137     FILE* fp;
00138     char buf[MAX_CLIENTID_LENGTH + 256];
00139     size_t pos;
00140     bool secure;
00141     bool stable;
00142     bool qos_1;
00143     bool forwarder;
00144     bool rc = true;
00145     SensorNetAddress netAddr;
00146     MQTTSNString clientId = MQTTSNString_initializer;
00147 
00148     if ((fp = fopen(fileName, "r")) != 0)
00149     {
00150         while (fgets(buf, MAX_CLIENTID_LENGTH + 254, fp) != 0)
00151         {
00152             if (*buf == '#')
00153             {
00154                 continue;
00155             }
00156             string data = string(buf);
00157             while ((pos = data.find_first_of("  \t\n")) != string::npos)
00158             {
00159                 data.erase(pos, 1);
00160             }
00161             if (data.empty())
00162             {
00163                 continue;
00164             }
00165             pos = data.find_first_of(",");
00166             string id = data.substr(0, pos);
00167             clientId.cstring = strdup(id.c_str());
00168             string addr = data.substr(pos + 1);
00169 
00170             if (netAddr.setAddress(&addr) == 0)
00171             {
00172                 qos_1 = (data.find("QoS-1") != string::npos);
00173                 forwarder = (data.find("forwarder") != string::npos);
00174                 secure = (data.find("secureConnection") != string::npos);
00175                 stable = !(data.find("unstableLine") != string::npos);
00176                 if ( (qos_1 && type == QOSM1PROXY_TYPE) || (!qos_1 && type == AGGREGATER_TYPE) )
00177                 {
00178                     createClient(&netAddr, &clientId, stable, secure, type);
00179                 }
00180                 else if ( forwarder && type == FORWARDER_TYPE)
00181                 {
00182                     theGateway->getAdapterManager()->getForwarderList()->addForwarder(&netAddr, &clientId);
00183                 }
00184                 else if (type == TRANSPEARENT_TYPE )
00185                 {
00186                     createClient(&netAddr, &clientId, stable, secure, type);
00187                 }
00188             }
00189             else
00190             {
00191                 WRITELOG("Invalid address     %s\n", data.c_str());
00192                 rc = false;
00193             }
00194             free(clientId.cstring);
00195         }
00196         fclose(fp);
00197     }
00198     return rc;
00199 }
00200 
00201 bool ClientList::readPredefinedList(const char* fileName, bool aggregate)
00202 {
00203     FILE* fp;
00204     char buf[MAX_CLIENTID_LENGTH + 256];
00205     size_t pos0, pos1;
00206     MQTTSNString clientId = MQTTSNString_initializer;;
00207     bool rc = false;
00208 
00209     if ((fp = fopen(fileName, "r")) != 0)
00210     {
00211         while (fgets(buf, MAX_CLIENTID_LENGTH + 254, fp) != 0)
00212         {
00213             if (*buf == '#')
00214             {
00215                 continue;
00216             }
00217             string data = string(buf);
00218             while ((pos0 = data.find_first_of("  \t\n")) != string::npos)
00219             {
00220                 data.erase(pos0, 1);
00221             }
00222             if (data.empty())
00223             {
00224                 continue;
00225             }
00226 
00227             pos0 = data.find_first_of(",");
00228             pos1 = data.find(",", pos0 + 1) ;
00229             string id = data.substr(0, pos0);
00230             clientId.cstring = strdup(id.c_str());
00231             string topicName = data.substr(pos0 + 1, pos1 - pos0 -1);
00232             uint16_t topicID = stoul(data.substr(pos1 + 1));
00233             createPredefinedTopic( &clientId, topicName,  topicID, aggregate);
00234             free(clientId.cstring);
00235         }
00236         fclose(fp);
00237         rc = true;
00238     }
00239     else
00240     {
00241         WRITELOG("ClientList can not open the Predefined Topic List.     %s\n", fileName);
00242         return false;
00243     }
00244     return rc;
00245 }
00246 
00247 void ClientList::erase(Client*& client)
00248 {
00249     if ( !_authorize && client->erasable())
00250     {
00251         _mutex.lock();
00252         Client* prev = client->_prevClient;
00253         Client* next = client->_nextClient;
00254 
00255         if (prev)
00256         {
00257             prev->_nextClient = next;
00258         }
00259         else
00260         {
00261             _firstClient = next;
00262 
00263         }
00264         if (next)
00265         {
00266             next->_prevClient = prev;
00267         }
00268         else
00269         {
00270             _endClient = prev;
00271         }
00272         _clientCnt--;
00273         Forwarder* fwd = client->getForwarder();
00274         if ( fwd )
00275         {
00276             fwd->eraseClient(client);
00277         }
00278         delete client;
00279         client = nullptr;
00280         _mutex.unlock();
00281     }
00282 }
00283 
00284 Client* ClientList::getClient(SensorNetAddress* addr)
00285 {
00286     if ( addr )
00287     {
00288         _mutex.lock();
00289         Client* client = _firstClient;
00290 
00291         while (client != nullptr)
00292         {
00293             if (client->getSensorNetAddress()->isMatch(addr) )
00294             {
00295                 _mutex.unlock();
00296                 return client;
00297             }
00298             client = client->_nextClient;
00299         }
00300         _mutex.unlock();
00301     }
00302     return 0;
00303 }
00304 
00305 Client* ClientList::getClient(int index)
00306 {
00307    Client* client = _firstClient;
00308    int p = 0;
00309    while ( client != nullptr )
00310    {
00311        if ( p == index )
00312        {
00313            return client;
00314        }
00315        else
00316        {
00317            client = client->_nextClient;
00318            p++;
00319        }
00320    }
00321    return nullptr;
00322 }
00323 
00324 
00325 Client* ClientList::getClient(MQTTSNString* clientId)
00326 {
00327     _mutex.lock();
00328     Client* client = _firstClient;
00329     const char* clID =clientId->cstring;
00330 
00331     if (clID == nullptr )
00332     {
00333         clID = clientId->lenstring.data;
00334     }
00335 
00336     while (client != nullptr)
00337     {
00338         if (strncmp((const char*)client->getClientId(), clID, MQTTSNstrlen(*clientId)) == 0 )
00339         {
00340             _mutex.unlock();
00341             return client;
00342         }
00343         client = client->_nextClient;
00344     }
00345     _mutex.unlock();
00346     return 0;
00347 }
00348 
00349 Client* ClientList::createClient(SensorNetAddress* addr, MQTTSNString* clientId, int type)
00350 {
00351     return createClient(addr, clientId, false, false, type);
00352 }
00353 
00354 Client* ClientList::createClient(SensorNetAddress* addr, MQTTSNString* clientId, bool unstableLine, bool secure, int type)
00355 {
00356     Client* client = nullptr;
00357 
00358     /*  anonimous clients */
00359     if ( _clientCnt > MAX_CLIENTS )
00360     {
00361         return 0;  // full of clients
00362     }
00363 
00364     client = getClient(addr);
00365     if ( client )
00366     {
00367         return client;
00368     }
00369 
00370     /* creat a new client */
00371     client = new Client(secure);
00372     if ( addr )
00373     {
00374         client->setClientAddress(addr);
00375     }
00376     client->setSensorNetType(unstableLine);
00377     if ( MQTTSNstrlen(*clientId) )
00378     {
00379         client->setClientId(*clientId);
00380     }
00381     else
00382     {
00383         MQTTSNString  dummyId MQTTSNString_initializer;;
00384         dummyId.cstring = strdup("");
00385         client->setClientId(dummyId);
00386          free(dummyId.cstring);
00387     }
00388 
00389     if ( type == AGGREGATER_TYPE )
00390     {
00391         client->setAggregated();
00392     }
00393     else if ( type == QOSM1PROXY_TYPE )
00394     {
00395         client->setQoSm1();
00396     }
00397 
00398     _mutex.lock();
00399 
00400     /* add the list */
00401     if ( _firstClient == nullptr )
00402     {
00403         _firstClient = client;
00404         _endClient = client;
00405     }
00406     else
00407     {
00408         _endClient->_nextClient = client;
00409         client->_prevClient = _endClient;
00410         _endClient = client;
00411     }
00412     _clientCnt++;
00413     _mutex.unlock();
00414     return client;
00415 }
00416 
00417 Client* ClientList::createPredefinedTopic( MQTTSNString* clientId, string topicName, uint16_t topicId, bool aggregate)
00418 {
00419     if ( clientId->cstring == common_topic )
00420     {
00421         _gateway->getTopics()->add((const char*)topicName.c_str(), topicId);
00422         return 0;
00423     }
00424     else
00425     {
00426         Client* client = getClient(clientId);
00427 
00428         if ( _authorize && client == nullptr )
00429         {
00430             return 0;
00431         }
00432 
00433         /*  anonimous clients */
00434         if ( _clientCnt > MAX_CLIENTS )
00435         {
00436             return nullptr;  // full of clients
00437         }
00438 
00439         if ( client == nullptr )
00440         {
00441             /* creat a new client */
00442             client = new Client();
00443             client->setClientId(*clientId);
00444             if ( aggregate )
00445             {
00446                 client->setAggregated();
00447             }
00448             _mutex.lock();
00449 
00450             /* add the list */
00451             if ( _firstClient == nullptr )
00452             {
00453                 _firstClient = client;
00454                 _endClient = client;
00455             }
00456             else
00457             {
00458                 _endClient->_nextClient = client;
00459                 client->_prevClient = _endClient;
00460                 _endClient = client;
00461             }
00462             _clientCnt++;
00463             _mutex.unlock();
00464         }
00465 
00466         // create Topic & Add it
00467         client->getTopics()->add((const char*)topicName.c_str(), topicId);
00468         client->_hasPredefTopic = true;
00469         return client;
00470     }
00471 }
00472 
00473 uint16_t ClientList::getClientCount()
00474 {
00475     return _clientCnt;
00476 }
00477 
00478 bool ClientList::isAuthorized()
00479 {
00480     return _authorize;
00481 }
00482 
00483