Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
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
Generated on Wed Jul 13 2022 10:46:03 by
1.7.2