/************************************************************************************** * 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 "MQTTSNGWSubscribeHandler.h" #include "MQTTSNGWPacket.h" #include "MQTTGWPacket.h" #include "MQTTSNGateway.h" #include "MQTTSNGWClient.h" using namespace std; using namespace MQTTSNGW; MQTTSNSubscribeHandler::MQTTSNSubscribeHandler(Gateway* gateway) { _gateway = gateway; } MQTTSNSubscribeHandler::~MQTTSNSubscribeHandler() { } MQTTGWPacket* MQTTSNSubscribeHandler::handleSubscribe(Client* client, MQTTSNPacket* packet) { uint8_t dup; int qos; uint16_t msgId; MQTTSN_topicid topicFilter; Topic* topic = nullptr; uint16_t topicId = 0; MQTTGWPacket* subscribe; Event* ev1; Event* evsuback; if ( packet->getSUBSCRIBE(&dup, &qos, &msgId, &topicFilter) == 0 ) { return nullptr; } if ( msgId == 0 ) { return nullptr; } if ( topicFilter.type == MQTTSN_TOPIC_TYPE_PREDEFINED ) { topic = client->getTopics()->getTopicById(&topicFilter); if ( topic ) { topicId = topic->getTopicId(); subscribe = new MQTTGWPacket(); subscribe->setSUBSCRIBE((char*)topic->getTopicName()->c_str(), (uint8_t)qos, (uint16_t)msgId); } else { goto RespExit; } } else if (topicFilter.type == MQTTSN_TOPIC_TYPE_NORMAL) { topic = client->getTopics()->getTopicByName(&topicFilter); if ( topic == nullptr ) { topic = client->getTopics()->add(&topicFilter); if ( topic == nullptr ) { WRITELOG("%s Client(%s) can't add the Topic.%s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); return nullptr; } } topicId = topic->getTopicId(); subscribe = new MQTTGWPacket(); subscribe->setSUBSCRIBE((char*)topic->getTopicName()->c_str(), (uint8_t)qos, (uint16_t)msgId); } else //MQTTSN_TOPIC_TYPE_SHORT { char topicstr[3]; topicstr[0] = topicFilter.data.short_name[0]; topicstr[1] = topicFilter.data.short_name[1]; topicstr[2] = 0; topicId = 0; subscribe = new MQTTGWPacket(); subscribe->setSUBSCRIBE(topicstr, (uint8_t)qos, (uint16_t)msgId); } client->setWaitedSubTopicId(msgId, topicId, topicFilter.type); if ( !client->isAggregated() ) { ev1 = new Event(); ev1->setBrokerSendEvent(client, subscribe); _gateway->getBrokerSendQue()->post(ev1); return nullptr; } else { return subscribe; } RespExit: MQTTSNPacket* sSuback = new MQTTSNPacket(); sSuback->setSUBACK(qos, topicFilter.data.id, msgId, MQTTSN_RC_NOT_SUPPORTED); evsuback = new Event(); evsuback->setClientSendEvent(client, sSuback); _gateway->getClientSendQue()->post(evsuback); return nullptr; } MQTTGWPacket* MQTTSNSubscribeHandler::handleUnsubscribe(Client* client, MQTTSNPacket* packet) { uint16_t msgId; MQTTSN_topicid topicFilter; MQTTGWPacket* unsubscribe = nullptr; if ( packet->getUNSUBSCRIBE(&msgId, &topicFilter) == 0 ) { return nullptr; } if ( msgId == 0 ) { return nullptr; } Topic* topic = client->getTopics()->getTopicById(&topicFilter); if (topicFilter.type == MQTTSN_TOPIC_TYPE_SHORT) { char shortTopic[3]; shortTopic[0] = topicFilter.data.short_name[0]; shortTopic[1] = topicFilter.data.short_name[1]; shortTopic[2] = 0; unsubscribe = new MQTTGWPacket(); unsubscribe->setUNSUBSCRIBE(shortTopic, msgId); } else { if ( topic == nullptr ) { MQTTSNPacket* sUnsuback = new MQTTSNPacket(); sUnsuback->setUNSUBACK(msgId); Event* evsuback = new Event(); evsuback->setClientSendEvent(client, sUnsuback); _gateway->getClientSendQue()->post(evsuback); return nullptr; } else { unsubscribe = new MQTTGWPacket(); unsubscribe->setUNSUBSCRIBE(topic->getTopicName()->c_str(), msgId); } } if ( !client->isAggregated() ) { Event* ev1 = new Event(); ev1->setBrokerSendEvent(client, unsubscribe); _gateway->getBrokerSendQue()->post(ev1); return nullptr; } else { return unsubscribe; } } void MQTTSNSubscribeHandler::handleAggregateSubscribe(Client* client, MQTTSNPacket* packet) { MQTTGWPacket* subscribe = handleSubscribe(client, packet); if ( subscribe != nullptr ) { UTF8String str = subscribe->getTopic(); string* topicName = new string(str.data, str.len); Topic topic = Topic(topicName, MQTTSN_TOPIC_TYPE_NORMAL); _gateway->getAdapterManager()->addAggregateTopic(&topic, client); int msgId = 0; if ( packet->isDuplicate() ) { msgId = _gateway->getAdapterManager()->getAggregater()->getMsgId(client, packet->getMsgId()); } else { msgId = _gateway->getAdapterManager()->getAggregater()->addMessageIdTable(client, packet->getMsgId()); } if ( msgId == 0 ) { WRITELOG("%s MQTTSNSubscribeHandler can't create MessageIdTableElement %s%s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); return; } WRITELOG("msgId=%d\n",msgId); subscribe->setMsgId(msgId); Event* ev = new Event(); ev->setBrokerSendEvent(client, subscribe); _gateway->getBrokerSendQue()->post(ev); } } void MQTTSNSubscribeHandler::handleAggregateUnsubscribe(Client* client, MQTTSNPacket* packet) { MQTTGWPacket* unsubscribe = handleUnsubscribe(client, packet); if ( unsubscribe != nullptr ) { UTF8String str = unsubscribe->getTopic(); string* topicName = new string(str.data, str.len); Topic topic = Topic(topicName, MQTTSN_TOPIC_TYPE_NORMAL); _gateway->getAdapterManager()->removeAggregateTopic(&topic, client); int msgId = 0; if ( packet->isDuplicate() ) { msgId = _gateway->getAdapterManager()->getAggregater()->getMsgId(client, packet->getMsgId()); } else { msgId = _gateway->getAdapterManager()->getAggregater()->addMessageIdTable(client, packet->getMsgId()); } if ( msgId == 0 ) { WRITELOG("%s MQTTSNUnsubscribeHandler can't create MessageIdTableElement %s%s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); return; } unsubscribe->setMsgId(msgId); Event* ev = new Event(); ev->setBrokerSendEvent(client, unsubscribe); _gateway->getBrokerSendQue()->post(ev); } }