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.
MQTTSNGWTopic.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 "MQTTSNGWTopic.h" 00018 #include "MQTTSNGWDefines.h" 00019 #include "MQTTSNGateway.h" 00020 #include <string.h> 00021 00022 using namespace MQTTSNGW; 00023 00024 /*===================================== 00025 Class Topic 00026 ======================================*/ 00027 Topic::Topic() 00028 { 00029 _type = MQTTSN_TOPIC_TYPE_NORMAL; 00030 _topicName = nullptr; 00031 _topicId = 0; 00032 _next = nullptr; 00033 } 00034 00035 Topic::Topic(string* topic, MQTTSN_topicTypes type) 00036 { 00037 _type = type; 00038 _topicName = topic; 00039 _topicId = 0; 00040 _next = nullptr; 00041 } 00042 00043 Topic::~Topic() 00044 { 00045 if ( _topicName ) 00046 { 00047 delete _topicName; 00048 } 00049 } 00050 00051 string* Topic::getTopicName(void) 00052 { 00053 return _topicName; 00054 } 00055 00056 uint16_t Topic::getTopicId(void) 00057 { 00058 return _topicId; 00059 } 00060 00061 MQTTSN_topicTypes Topic::getType(void) 00062 { 00063 return _type; 00064 } 00065 00066 bool Topic::isMatch(string* topicName) 00067 { 00068 string::size_type tlen = _topicName->size(); 00069 00070 string::size_type tpos = 0; 00071 string::size_type tloc = 0; 00072 string::size_type pos = 0; 00073 string::size_type loc = 0; 00074 string wildcard = "#"; 00075 string wildcards = "+"; 00076 00077 while(true) 00078 { 00079 loc = topicName->find('/', pos); 00080 tloc = _topicName->find('/', tpos); 00081 00082 if ( loc != string::npos && tloc != string::npos ) 00083 { 00084 string subtopic = topicName->substr(pos, loc - pos); 00085 string subtopict = _topicName->substr(tpos, tloc - tpos); 00086 if (subtopict == wildcard) 00087 { 00088 return true; 00089 } 00090 else if (subtopict == wildcards) 00091 { 00092 if ( (tpos = tloc + 1 ) > tlen ) 00093 { 00094 pos = loc + 1; 00095 loc = topicName->find('/', pos); 00096 if ( loc == string::npos ) 00097 { 00098 return true; 00099 } 00100 else 00101 { 00102 return false; 00103 } 00104 } 00105 pos = loc + 1; 00106 } 00107 else if ( subtopic != subtopict ) 00108 { 00109 return false; 00110 } 00111 else 00112 { 00113 if ( (tpos = tloc + 1) > tlen ) 00114 { 00115 return false; 00116 } 00117 00118 pos = loc + 1; 00119 } 00120 } 00121 else if ( loc == string::npos && tloc == string::npos ) 00122 { 00123 string subtopic = topicName->substr(pos); 00124 string subtopict = _topicName->substr(tpos); 00125 if ( subtopict == wildcard || subtopict == wildcards) 00126 { 00127 return true; 00128 } 00129 else if ( subtopic == subtopict ) 00130 { 00131 return true; 00132 } 00133 else 00134 { 00135 return false; 00136 } 00137 } 00138 else if ( loc == string::npos && tloc != string::npos ) 00139 { 00140 string subtopic = topicName->substr(pos); 00141 string subtopict = _topicName->substr(tpos, tloc - tpos); 00142 if ( subtopic != subtopict) 00143 { 00144 return false; 00145 } 00146 00147 tpos = tloc + 1; 00148 00149 return _topicName->substr(tpos) == wildcard; 00150 } 00151 else if ( loc != string::npos && tloc == string::npos ) 00152 { 00153 return _topicName->substr(tpos) == wildcard; 00154 } 00155 } 00156 } 00157 00158 void Topic::print(void) 00159 { 00160 WRITELOG("TopicName=%s ID=%d Type=%d\n", _topicName->c_str(), _topicId, _type); 00161 } 00162 00163 /*===================================== 00164 Class Topics 00165 ======================================*/ 00166 Topics::Topics() 00167 { 00168 _first = nullptr; 00169 _nextTopicId = 0; 00170 _cnt = 0; 00171 } 00172 00173 Topics::~Topics() 00174 { 00175 Topic* p = _first; 00176 while (p) 00177 { 00178 Topic* q = p->_next; 00179 delete p; 00180 p = q; 00181 } 00182 } 00183 00184 Topic* Topics::getTopicByName(const MQTTSN_topicid* topicid) 00185 { 00186 Topic* p = _first; 00187 char* ch = topicid->data.long_.name; 00188 00189 string sname = string(ch, ch + topicid->data.long_.len); 00190 while (p) 00191 { 00192 if ( p->_topicName->compare(sname) == 0 ) 00193 { 00194 return p; 00195 } 00196 p = p->_next; 00197 } 00198 return 0; 00199 } 00200 00201 Topic* Topics::getTopicById(const MQTTSN_topicid* topicid) 00202 { 00203 Topic* p = _first; 00204 00205 while (p) 00206 { 00207 if ( p->_type == topicid->type && p->_topicId == topicid->data.id ) 00208 { 00209 return p; 00210 } 00211 p = p->_next; 00212 } 00213 return 0; 00214 } 00215 00216 // For MQTTSN_TOPIC_TYPE_NORMAL */ 00217 Topic* Topics::add(const MQTTSN_topicid* topicid) 00218 { 00219 if (topicid->type != MQTTSN_TOPIC_TYPE_NORMAL ) 00220 { 00221 return 0; 00222 } 00223 00224 Topic* topic = getTopicByName(topicid); 00225 00226 if ( topic ) 00227 { 00228 return topic; 00229 } 00230 string name(topicid->data.long_.name, topicid->data.long_.len); 00231 return add(name.c_str(), 0); 00232 } 00233 00234 Topic* Topics::add(const char* topicName, uint16_t id) 00235 { 00236 MQTTSN_topicid topicId; 00237 00238 if ( _cnt >= MAX_TOPIC_PAR_CLIENT ) 00239 { 00240 return 0; 00241 } 00242 00243 topicId.data.long_.name = (char*)const_cast<char*>(topicName); 00244 topicId.data.long_.len = strlen(topicName); 00245 00246 00247 Topic* topic = getTopicByName(&topicId); 00248 00249 if ( topic ) 00250 { 00251 return topic; 00252 } 00253 00254 topic = new Topic(); 00255 00256 if (topic == nullptr) 00257 { 00258 return nullptr; 00259 } 00260 00261 string* name = new string(topicName); 00262 topic->_topicName = name; 00263 00264 if ( id == 0 ) 00265 { 00266 topic->_type = MQTTSN_TOPIC_TYPE_NORMAL; 00267 topic->_topicId = getNextTopicId(); 00268 } 00269 else 00270 { 00271 topic->_type = MQTTSN_TOPIC_TYPE_PREDEFINED; 00272 topic->_topicId = id; 00273 } 00274 00275 _cnt++; 00276 00277 if ( _first == nullptr) 00278 { 00279 _first = topic; 00280 } 00281 else 00282 { 00283 Topic* tp = _first; 00284 while (tp) 00285 { 00286 if (tp->_next == nullptr) 00287 { 00288 tp->_next = topic; 00289 break; 00290 } 00291 else 00292 { 00293 tp = tp->_next; 00294 } 00295 } 00296 } 00297 return topic; 00298 } 00299 00300 uint16_t Topics::getNextTopicId() 00301 { 00302 return ++_nextTopicId == 0xffff ? _nextTopicId += 2 : _nextTopicId; 00303 } 00304 00305 Topic* Topics::match(const MQTTSN_topicid* topicid) 00306 { 00307 if (topicid->type != MQTTSN_TOPIC_TYPE_NORMAL) 00308 { 00309 return 0; 00310 } 00311 string topicName(topicid->data.long_.name, topicid->data.long_.len); 00312 00313 Topic* topic = _first; 00314 while (topic) 00315 { 00316 if (topic->isMatch(&topicName)) 00317 { 00318 return topic; 00319 } 00320 topic = topic->_next; 00321 } 00322 return 0; 00323 } 00324 00325 00326 void Topics::eraseNormal(void) 00327 { 00328 Topic* topic = _first; 00329 Topic* next = nullptr; 00330 Topic* prev = nullptr; 00331 00332 while (topic) 00333 { 00334 if ( topic->_type == MQTTSN_TOPIC_TYPE_NORMAL ) 00335 { 00336 next = topic->_next; 00337 if ( _first == topic ) 00338 { 00339 _first = next; 00340 } 00341 if ( prev ) 00342 { 00343 prev->_next = next; 00344 } 00345 delete topic; 00346 _cnt--; 00347 topic = next; 00348 } 00349 else 00350 { 00351 prev = topic; 00352 topic = topic->_next; 00353 } 00354 } 00355 } 00356 00357 void Topics::print(void) 00358 { 00359 Topic* topic = _first; 00360 if (topic == nullptr ) 00361 { 00362 WRITELOG("No Topic.\n"); 00363 } 00364 else 00365 { 00366 while (topic) 00367 { 00368 topic->print(); 00369 topic = topic->_next; 00370 } 00371 } 00372 } 00373 00374 uint8_t Topics::getCount(void) 00375 { 00376 return _cnt; 00377 } 00378 00379 /*===================================== 00380 Class TopicIdMap 00381 =====================================*/ 00382 TopicIdMapElement::TopicIdMapElement(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type) 00383 { 00384 _msgId = msgId; 00385 _topicId = topicId; 00386 _type = type; 00387 _next = nullptr; 00388 _prev = nullptr; 00389 } 00390 00391 TopicIdMapElement::~TopicIdMapElement() 00392 { 00393 00394 } 00395 00396 MQTTSN_topicTypes TopicIdMapElement::getTopicType(void) 00397 { 00398 return _type; 00399 } 00400 00401 uint16_t TopicIdMapElement::getTopicId(void) 00402 { 00403 return _topicId; 00404 } 00405 00406 TopicIdMap::TopicIdMap() 00407 { 00408 _maxInflight = MAX_INFLIGHTMESSAGES; 00409 _msgIds = 0; 00410 _first = nullptr; 00411 _end = nullptr; 00412 _cnt = 0; 00413 } 00414 00415 TopicIdMap::~TopicIdMap() 00416 { 00417 TopicIdMapElement* p = _first; 00418 while ( p ) 00419 { 00420 TopicIdMapElement* q = p->_next; 00421 delete p; 00422 p = q; 00423 } 00424 } 00425 00426 TopicIdMapElement* TopicIdMap::getElement(uint16_t msgId) 00427 { 00428 TopicIdMapElement* p = _first; 00429 while ( p ) 00430 { 00431 if ( p->_msgId == msgId ) 00432 { 00433 return p; 00434 } 00435 p = p->_next; 00436 } 00437 return 0; 00438 } 00439 00440 TopicIdMapElement* TopicIdMap::add(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type) 00441 { 00442 if ( _cnt > _maxInflight * 2 || ( topicId == 0 && type != MQTTSN_TOPIC_TYPE_SHORT ) ) 00443 { 00444 return 0; 00445 } 00446 if ( getElement(msgId) ) 00447 { 00448 erase(msgId); 00449 } 00450 00451 TopicIdMapElement* elm = new TopicIdMapElement(msgId, topicId, type); 00452 if ( elm == 0 ) 00453 { 00454 return 0; 00455 } 00456 if ( _first == nullptr ) 00457 { 00458 _first = elm; 00459 _end = elm; 00460 } 00461 else 00462 { 00463 elm->_prev = _end; 00464 _end->_next = elm; 00465 _end = elm; 00466 } 00467 _cnt++; 00468 return elm; 00469 } 00470 00471 void TopicIdMap::erase(uint16_t msgId) 00472 { 00473 TopicIdMapElement* p = _first; 00474 while ( p ) 00475 { 00476 if ( p->_msgId == msgId ) 00477 { 00478 if ( p->_prev == nullptr ) 00479 { 00480 _first = p->_next; 00481 } 00482 else 00483 { 00484 p->_prev->_next = p->_next; 00485 } 00486 00487 if ( p->_next == nullptr ) 00488 { 00489 _end = p->_prev; 00490 } 00491 else 00492 { 00493 p->_next->_prev = p->_prev; 00494 } 00495 delete p; 00496 break; 00497 00498 } 00499 p = p->_next; 00500 } 00501 _cnt--; 00502 } 00503 00504 void TopicIdMap::clear(void) 00505 { 00506 TopicIdMapElement* p = _first; 00507 while ( p ) 00508 { 00509 TopicIdMapElement* q = p->_next; 00510 delete p; 00511 p = q; 00512 } 00513 _first = nullptr; 00514 _end = nullptr; 00515 _cnt = 0; 00516 } 00517 00518 00519
Generated on Wed Jul 13 2022 10:46:03 by
1.7.2