Update: Add Aggregate Gateway functions. #127

Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
This commit is contained in:
tomoaki
2018-08-04 17:46:42 +09:00
parent 862e501512
commit f7fc5c49f5
65 changed files with 4368 additions and 1982 deletions

View File

@@ -0,0 +1,519 @@
/**************************************************************************************
* Copyright (c) 2016, Tomoaki Yamaguchi
*
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* and Eclipse Distribution License v1.0 which accompany this distribution.
*
* The Eclipse Public License is available at
* http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Tomoaki Yamaguchi - initial API and implementation and/or initial documentation
* Tieto Poland Sp. z o.o. - Gateway improvements
**************************************************************************************/
#include "MQTTSNGWTopic.h"
#include "MQTTSNGWDefines.h"
#include "MQTTSNGateway.h"
#include <string.h>
using namespace MQTTSNGW;
/*=====================================
Class Topic
======================================*/
Topic::Topic()
{
_type = MQTTSN_TOPIC_TYPE_NORMAL;
_topicName = nullptr;
_topicId = 0;
_next = nullptr;
}
Topic::Topic(string* topic, MQTTSN_topicTypes type)
{
_type = type;
_topicName = topic;
_topicId = 0;
_next = nullptr;
}
Topic::~Topic()
{
if ( _topicName )
{
delete _topicName;
}
}
string* Topic::getTopicName(void)
{
return _topicName;
}
uint16_t Topic::getTopicId(void)
{
return _topicId;
}
MQTTSN_topicTypes Topic::getType(void)
{
return _type;
}
bool Topic::isMatch(string* topicName)
{
string::size_type tlen = _topicName->size();
string::size_type tpos = 0;
string::size_type tloc = 0;
string::size_type pos = 0;
string::size_type loc = 0;
string wildcard = "#";
string wildcards = "+";
while(true)
{
loc = topicName->find('/', pos);
tloc = _topicName->find('/', tpos);
if ( loc != string::npos && tloc != string::npos )
{
string subtopic = topicName->substr(pos, loc - pos);
string subtopict = _topicName->substr(tpos, tloc - tpos);
if (subtopict == wildcard)
{
return true;
}
else if (subtopict == wildcards)
{
if ( (tpos = tloc + 1 ) > tlen )
{
pos = loc + 1;
loc = topicName->find('/', pos);
if ( loc == string::npos )
{
return true;
}
else
{
return false;
}
}
pos = loc + 1;
}
else if ( subtopic != subtopict )
{
return false;
}
else
{
if ( (tpos = tloc + 1) > tlen )
{
return false;
}
pos = loc + 1;
}
}
else if ( loc == string::npos && tloc == string::npos )
{
string subtopic = topicName->substr(pos);
string subtopict = _topicName->substr(tpos);
if ( subtopict == wildcard || subtopict == wildcards)
{
return true;
}
else if ( subtopic == subtopict )
{
return true;
}
else
{
return false;
}
}
else if ( loc == string::npos && tloc != string::npos )
{
string subtopic = topicName->substr(pos);
string subtopict = _topicName->substr(tpos, tloc - tpos);
if ( subtopic != subtopict)
{
return false;
}
tpos = tloc + 1;
return _topicName->substr(tpos) == wildcard;
}
else if ( loc != string::npos && tloc == string::npos )
{
return _topicName->substr(tpos) == wildcard;
}
}
}
void Topic::print(void)
{
WRITELOG("TopicName=%s ID=%d Type=%d\n", _topicName->c_str(), _topicId, _type);
}
/*=====================================
Class Topics
======================================*/
Topics::Topics()
{
_first = nullptr;
_nextTopicId = 0;
_cnt = 0;
}
Topics::~Topics()
{
Topic* p = _first;
while (p)
{
Topic* q = p->_next;
delete p;
p = q;
}
}
Topic* Topics::getTopicByName(const MQTTSN_topicid* topicid)
{
Topic* p = _first;
char* ch = topicid->data.long_.name;
string sname = string(ch, ch + topicid->data.long_.len);
while (p)
{
if ( p->_topicName->compare(sname) == 0 )
{
return p;
}
p = p->_next;
}
return 0;
}
Topic* Topics::getTopicById(const MQTTSN_topicid* topicid)
{
Topic* p = _first;
while (p)
{
if ( p->_type == topicid->type && p->_topicId == topicid->data.id )
{
return p;
}
p = p->_next;
}
return 0;
}
// For MQTTSN_TOPIC_TYPE_NORMAL */
Topic* Topics::add(const MQTTSN_topicid* topicid)
{
if (topicid->type != MQTTSN_TOPIC_TYPE_NORMAL )
{
return 0;
}
Topic* topic = getTopicByName(topicid);
if ( topic )
{
return topic;
}
string name(topicid->data.long_.name, topicid->data.long_.len);
return add(name.c_str(), 0);
}
Topic* Topics::add(const char* topicName, uint16_t id)
{
MQTTSN_topicid topicId;
if ( _cnt >= MAX_TOPIC_PAR_CLIENT )
{
return 0;
}
topicId.data.long_.name = (char*)const_cast<char*>(topicName);
topicId.data.long_.len = strlen(topicName);
Topic* topic = getTopicByName(&topicId);
if ( topic )
{
return topic;
}
topic = new Topic();
if (topic == nullptr)
{
return nullptr;
}
string* name = new string(topicName);
topic->_topicName = name;
if ( id == 0 )
{
topic->_type = MQTTSN_TOPIC_TYPE_NORMAL;
topic->_topicId = getNextTopicId();
}
else
{
topic->_type = MQTTSN_TOPIC_TYPE_PREDEFINED;
topic->_topicId = id;
}
_cnt++;
if ( _first == nullptr)
{
_first = topic;
}
else
{
Topic* tp = _first;
while (tp)
{
if (tp->_next == nullptr)
{
tp->_next = topic;
break;
}
else
{
tp = tp->_next;
}
}
}
return topic;
}
uint16_t Topics::getNextTopicId()
{
return ++_nextTopicId == 0xffff ? _nextTopicId += 2 : _nextTopicId;
}
Topic* Topics::match(const MQTTSN_topicid* topicid)
{
if (topicid->type != MQTTSN_TOPIC_TYPE_NORMAL)
{
return 0;
}
string topicName(topicid->data.long_.name, topicid->data.long_.len);
Topic* topic = _first;
while (topic)
{
if (topic->isMatch(&topicName))
{
return topic;
}
topic = topic->_next;
}
return 0;
}
void Topics::eraseNormal(void)
{
Topic* topic = _first;
Topic* next = nullptr;
Topic* prev = nullptr;
while (topic)
{
if ( topic->_type == MQTTSN_TOPIC_TYPE_NORMAL )
{
next = topic->_next;
if ( _first == topic )
{
_first = next;
}
if ( prev )
{
prev->_next = next;
}
delete topic;
_cnt--;
topic = next;
}
else
{
prev = topic;
topic = topic->_next;
}
}
}
void Topics::print(void)
{
Topic* topic = _first;
if (topic == nullptr )
{
WRITELOG("No Topic.\n");
}
else
{
while (topic)
{
topic->print();
topic = topic->_next;
}
}
}
uint8_t Topics::getCount(void)
{
return _cnt;
}
/*=====================================
Class TopicIdMap
=====================================*/
TopicIdMapElement::TopicIdMapElement(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type)
{
_msgId = msgId;
_topicId = topicId;
_type = type;
_next = nullptr;
_prev = nullptr;
}
TopicIdMapElement::~TopicIdMapElement()
{
}
MQTTSN_topicTypes TopicIdMapElement::getTopicType(void)
{
return _type;
}
uint16_t TopicIdMapElement::getTopicId(void)
{
return _topicId;
}
TopicIdMap::TopicIdMap()
{
_maxInflight = MAX_INFLIGHTMESSAGES;
_msgIds = 0;
_first = nullptr;
_end = nullptr;
_cnt = 0;
}
TopicIdMap::~TopicIdMap()
{
TopicIdMapElement* p = _first;
while ( p )
{
TopicIdMapElement* q = p->_next;
delete p;
p = q;
}
}
TopicIdMapElement* TopicIdMap::getElement(uint16_t msgId)
{
TopicIdMapElement* p = _first;
while ( p )
{
if ( p->_msgId == msgId )
{
return p;
}
p = p->_next;
}
return 0;
}
TopicIdMapElement* TopicIdMap::add(uint16_t msgId, uint16_t topicId, MQTTSN_topicTypes type)
{
if ( _cnt > _maxInflight * 2 || ( topicId == 0 && type != MQTTSN_TOPIC_TYPE_SHORT ) )
{
return 0;
}
if ( getElement(msgId) > 0 )
{
erase(msgId);
}
TopicIdMapElement* elm = new TopicIdMapElement(msgId, topicId, type);
if ( elm == 0 )
{
return 0;
}
if ( _first == nullptr )
{
_first = elm;
_end = elm;
}
else
{
elm->_prev = _end;
_end->_next = elm;
_end = elm;
}
_cnt++;
return elm;
}
void TopicIdMap::erase(uint16_t msgId)
{
TopicIdMapElement* p = _first;
while ( p )
{
if ( p->_msgId == msgId )
{
if ( p->_prev == nullptr )
{
_first = p->_next;
}
else
{
p->_prev->_next = p->_next;
}
if ( p->_next == nullptr )
{
_end = p->_prev;
}
else
{
p->_next->_prev = p->_prev;
}
delete p;
break;
}
p = p->_next;
}
_cnt--;
}
void TopicIdMap::clear(void)
{
TopicIdMapElement* p = _first;
while ( p )
{
TopicIdMapElement* q = p->_next;
delete p;
p = q;
}
_first = nullptr;
_end = nullptr;
_cnt = 0;
}