mirror of
https://github.com/eclipse/paho.mqtt-sn.embedded-c.git
synced 2025-12-15 16:36:52 +01:00
1.Return CONNACK instead of the broker when the gateway receives CONNECT while the client is Sleep or Awake mode. 2.Define the max size of a que for PUBLISH while the client state is Asleep mode. Despose packets when the que is full of packets. 3.Return PUBACK or PUBREL to the broker when the client is Asleep or Awake. Signed-off-by: tomoaki <tomoaki@tomy-tech.com> Signed-off-by: tomoaki <tomoaki@tomy-tech.com>
294 lines
7.8 KiB
C++
294 lines
7.8 KiB
C++
/**************************************************************************************
|
|
* 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
|
|
**************************************************************************************/
|
|
|
|
#include "MQTTSNGWConnectionHandler.h"
|
|
#include "MQTTSNGateway.h"
|
|
#include "MQTTSNGWPacket.h"
|
|
#include "MQTTGWPacket.h"
|
|
#include <string.h>
|
|
|
|
using namespace std;
|
|
using namespace MQTTSNGW;
|
|
|
|
/*=====================================
|
|
Class MQTTSNConnectionHandler
|
|
=====================================*/
|
|
MQTTSNConnectionHandler::MQTTSNConnectionHandler(Gateway* gateway)
|
|
{
|
|
_gateway = gateway;
|
|
}
|
|
|
|
MQTTSNConnectionHandler::~MQTTSNConnectionHandler()
|
|
{
|
|
|
|
}
|
|
|
|
/*
|
|
* ADVERTISE
|
|
*/
|
|
void MQTTSNConnectionHandler::sendADVERTISE()
|
|
{
|
|
MQTTSNPacket* adv = new MQTTSNPacket();
|
|
adv->setADVERTISE(_gateway->getGWParams()->gatewayId, _gateway->getGWParams()->keepAlive);
|
|
Event* ev1 = new Event();
|
|
ev1->setBrodcastEvent(adv); //broadcast
|
|
_gateway->getClientSendQue()->post(ev1);
|
|
}
|
|
|
|
/*
|
|
* SEARCHGW
|
|
*/
|
|
void MQTTSNConnectionHandler::handleSearchgw(MQTTSNPacket* packet)
|
|
{
|
|
if (packet->getType() == MQTTSN_SEARCHGW)
|
|
{
|
|
MQTTSNPacket* gwinfo = new MQTTSNPacket();
|
|
gwinfo->setGWINFO(_gateway->getGWParams()->gatewayId);
|
|
Event* ev1 = new Event();
|
|
ev1->setBrodcastEvent(gwinfo);
|
|
_gateway->getClientSendQue()->post(ev1);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* CONNECT
|
|
*/
|
|
void MQTTSNConnectionHandler::handleConnect(Client* client, MQTTSNPacket* packet)
|
|
{
|
|
MQTTSNPacket_connectData data;
|
|
if ( packet->getCONNECT(&data) == 0 )
|
|
{
|
|
return;
|
|
}
|
|
|
|
/* return CONNACK when the client is sleeping */
|
|
if ( client->isSleep() || client->isAwake() )
|
|
{
|
|
MQTTSNPacket* packet = new MQTTSNPacket();
|
|
packet->setCONNACK(MQTTSN_RC_ACCEPTED);
|
|
Event* ev = new Event();
|
|
ev->setClientSendEvent(client, packet);
|
|
_gateway->getClientSendQue()->post(ev);
|
|
return;
|
|
}
|
|
|
|
//* clear ConnectData of Client */
|
|
Connect* connectData = client->getConnectData();
|
|
memset(connectData, 0, sizeof(Connect));
|
|
client->disconnected();
|
|
|
|
Topics* topics = client->getTopics();
|
|
|
|
/* CONNECT was not sent yet. prepare Connect data */
|
|
connectData->header.bits.type = CONNECT;
|
|
connectData->clientID = client->getClientId();
|
|
connectData->version = _gateway->getGWParams()->mqttVersion;
|
|
connectData->keepAliveTimer = data.duration;
|
|
connectData->flags.bits.will = data.willFlag;
|
|
|
|
if ((const char*) _gateway->getGWParams()->loginId != 0 && (const char*) _gateway->getGWParams()->password != 0)
|
|
{
|
|
connectData->flags.bits.password = 1;
|
|
connectData->flags.bits.username = 1;
|
|
}
|
|
|
|
client->setSessionStatus(false);
|
|
if (data.cleansession)
|
|
{
|
|
connectData->flags.bits.cleanstart = 1;
|
|
/* reset the table of msgNo and TopicId pare */
|
|
client->clearWaitedPubTopicId();
|
|
client->clearWaitedSubTopicId();
|
|
|
|
/* renew the TopicList */
|
|
if (topics)
|
|
{
|
|
delete topics;
|
|
}
|
|
topics = new Topics();
|
|
client->setTopics(topics);
|
|
client->setSessionStatus(true);
|
|
}
|
|
|
|
if (data.willFlag)
|
|
{
|
|
/* create & send WILLTOPICREQ message to the client */
|
|
MQTTSNPacket* reqTopic = new MQTTSNPacket();
|
|
reqTopic->setWILLTOPICREQ();
|
|
Event* evwr = new Event();
|
|
evwr->setClientSendEvent(client, reqTopic);
|
|
|
|
/* Send WILLTOPICREQ to the client */
|
|
_gateway->getClientSendQue()->post(evwr);
|
|
}
|
|
else
|
|
{
|
|
/* CONNECT message was not qued in.
|
|
* create CONNECT message & send it to the broker */
|
|
MQTTGWPacket* mqMsg = new MQTTGWPacket();
|
|
mqMsg->setCONNECT(client->getConnectData(), (unsigned char*)_gateway->getGWParams()->loginId, (unsigned char*)_gateway->getGWParams()->password);
|
|
Event* ev1 = new Event();
|
|
ev1->setBrokerSendEvent(client, mqMsg);
|
|
_gateway->getBrokerSendQue()->post(ev1);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* WILLTOPIC
|
|
*/
|
|
void MQTTSNConnectionHandler::handleWilltopic(Client* client, MQTTSNPacket* packet)
|
|
{
|
|
int willQos;
|
|
uint8_t willRetain;
|
|
MQTTSNString willTopic;
|
|
|
|
if ( packet->getWILLTOPIC(&willQos, &willRetain, &willTopic) == 0 )
|
|
{
|
|
return;
|
|
}
|
|
client->setWillTopic(willTopic);
|
|
Connect* connectData = client->getConnectData();
|
|
|
|
/* add the connectData for MQTT CONNECT message */
|
|
connectData->willTopic = client->getWillTopic();
|
|
connectData->flags.bits.willQoS = willQos;
|
|
connectData->flags.bits.willRetain = willRetain;
|
|
|
|
/* Send WILLMSGREQ to the client */
|
|
client->setWaitWillMsgFlg(true);
|
|
MQTTSNPacket* reqMsg = new MQTTSNPacket();
|
|
reqMsg->setWILLMSGREQ();
|
|
Event* evt = new Event();
|
|
evt->setClientSendEvent(client, reqMsg);
|
|
_gateway->getClientSendQue()->post(evt);
|
|
}
|
|
|
|
/*
|
|
* WILLMSG
|
|
*/
|
|
void MQTTSNConnectionHandler::handleWillmsg(Client* client, MQTTSNPacket* packet)
|
|
{
|
|
if ( !client->isWaitWillMsg() )
|
|
{
|
|
DEBUGLOG(" MQTTSNConnectionHandler::handleWillmsg WaitWillMsgFlg is off.\n");
|
|
return;
|
|
}
|
|
|
|
MQTTSNString willmsg;
|
|
Connect* connectData = client->getConnectData();
|
|
|
|
if( client->isConnectSendable() )
|
|
{
|
|
/* save WillMsg in the client */
|
|
if ( packet->getWILLMSG(&willmsg) == 0 )
|
|
{
|
|
return;
|
|
}
|
|
client->setWillMsg(willmsg);
|
|
|
|
/* create CONNECT message */
|
|
MQTTGWPacket* mqttPacket = new MQTTGWPacket();
|
|
connectData->willMsg = client->getWillMsg();
|
|
mqttPacket->setCONNECT(connectData, (unsigned char*)_gateway->getGWParams()->loginId, (unsigned char*)_gateway->getGWParams()->password);
|
|
|
|
/* Send CONNECT to the broker */
|
|
Event* evt = new Event();
|
|
evt->setBrokerSendEvent(client, mqttPacket);
|
|
client->setWaitWillMsgFlg(false);
|
|
_gateway->getBrokerSendQue()->post(evt);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* DISCONNECT
|
|
*/
|
|
void MQTTSNConnectionHandler::handleDisconnect(Client* client, MQTTSNPacket* packet)
|
|
{
|
|
Event* ev = new Event();
|
|
MQTTSNPacket* snMsg = new MQTTSNPacket();
|
|
snMsg->setDISCONNECT(0);
|
|
ev->setClientSendEvent(client, snMsg);
|
|
_gateway->getClientSendQue()->post(ev);
|
|
|
|
uint16_t duration = 0;
|
|
if ( packet->getDISCONNECT(&duration) == 0 )
|
|
{
|
|
return;
|
|
}
|
|
if ( duration == 0 )
|
|
{
|
|
MQTTGWPacket* mqMsg = new MQTTGWPacket();
|
|
mqMsg->setHeader(DISCONNECT);
|
|
ev = new Event();
|
|
ev->setBrokerSendEvent(client, mqMsg);
|
|
_gateway->getBrokerSendQue()->post(ev);
|
|
}
|
|
}
|
|
|
|
/*
|
|
* WILLTOPICUPD
|
|
*/
|
|
void MQTTSNConnectionHandler::handleWilltopicupd(Client* client, MQTTSNPacket* packet)
|
|
{
|
|
/* send NOT_SUPPORTED responce to the client */
|
|
MQTTSNPacket* respMsg = new MQTTSNPacket();
|
|
respMsg->setWILLTOPICRESP(MQTTSN_RC_NOT_SUPPORTED);
|
|
Event* evt = new Event();
|
|
evt->setClientSendEvent(client, respMsg);
|
|
_gateway->getClientSendQue()->post(evt);
|
|
}
|
|
|
|
/*
|
|
* WILLMSGUPD
|
|
*/
|
|
void MQTTSNConnectionHandler::handleWillmsgupd(Client* client, MQTTSNPacket* packet)
|
|
{
|
|
/* send NOT_SUPPORTED responce to the client */
|
|
MQTTSNPacket* respMsg = new MQTTSNPacket();
|
|
respMsg->setWILLMSGRESP(MQTTSN_RC_NOT_SUPPORTED);
|
|
Event* evt = new Event();
|
|
evt->setClientSendEvent(client, respMsg);
|
|
_gateway->getClientSendQue()->post(evt);
|
|
}
|
|
|
|
/*
|
|
* PINGREQ
|
|
*/
|
|
void MQTTSNConnectionHandler::handlePingreq(Client* client, MQTTSNPacket* packet)
|
|
{
|
|
MQTTGWPacket* msg = 0;
|
|
|
|
if ( client->isSleep() || client->isAwake() )
|
|
{
|
|
while ( ( msg = client->getClientSleepPacket() ) != 0 )
|
|
{
|
|
// ToDo: This version can't re-send PUBLISH when PUBACK is not returned.
|
|
client->deleteFirstClientSleepPacket(); // pop the que to delete element.
|
|
|
|
Event* ev = new Event();
|
|
ev->setBrokerRecvEvent(client, msg);
|
|
_gateway->getPacketEventQue()->post(ev);
|
|
}
|
|
}
|
|
|
|
/* send PINGREQ to the broker */
|
|
MQTTGWPacket* pingreq = new MQTTGWPacket();
|
|
pingreq->setHeader(PINGREQ);
|
|
Event* evt = new Event();
|
|
evt->setBrokerSendEvent(client, pingreq);
|
|
_gateway->getBrokerSendQue()->post(evt);
|
|
}
|