/************************************************************************************** * 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 "MQTTSNGWClientRecvTask.h" #include "MQTTSNPacket.h" #include "MQTTSNGWQoSm1Proxy.h" #include "MQTTSNGWEncapsulatedPacket.h" #include using namespace MQTTSNGW; char* currentDateTime(void); /*===================================== Class ClientRecvTask =====================================*/ ClientRecvTask::ClientRecvTask(Gateway* gateway) { _gateway = gateway; _gateway->attach((Thread*) this); _sensorNetwork = _gateway->getSensorNetwork(); setTaskName("ClientRecvTask"); } ClientRecvTask::~ClientRecvTask() { } void ClientRecvTask::initialize(int argc, char** argv) { } /* * Receive a packet from clients via sensor netwwork * and creats a event to execute the packet handling procedure * of MQTTSNPacketHandlingTask. */ void ClientRecvTask::run() { Event* ev = nullptr; AdapterManager* adpMgr = _gateway->getAdapterManager(); QoSm1Proxy* qosm1Proxy = adpMgr->getQoSm1Proxy(); int clientType = adpMgr->isAggregaterActive() ? AGGREGATER_TYPE : TRANSPEARENT_TYPE; ClientList* clientList = _gateway->getClientList(); EventQue* packetEventQue = _gateway->getPacketEventQue(); EventQue* clientsendQue = _gateway->getClientSendQue(); char buf[128]; while (true) { Client* client = nullptr; Forwarder* fwd = nullptr; WirelessNodeId nodeId; MQTTSNPacket* packet = new MQTTSNPacket(); int packetLen = packet->recv(_sensorNetwork); if (CHK_SIGINT) { WRITELOG("%s %s stopped.\n", currentDateTime(), getTaskName()); delete packet; return; } if (packetLen < 2) { delete packet; continue; } if (packet->getType() <= MQTTSN_ADVERTISE || packet->getType() == MQTTSN_GWINFO) { delete packet; continue; } if (packet->getType() == MQTTSN_SEARCHGW) { /* write log and post Event */ log(0, packet, 0); ev = new Event(); ev->setBrodcastEvent(packet); packetEventQue->post(ev); continue; } SensorNetAddress senderAddr = *_gateway->getSensorNetwork()->getSenderAddress(); if (packet->getType() == MQTTSN_ENCAPSULATED) { fwd = _gateway->getAdapterManager()->getForwarderList()->getForwarder(&senderAddr); if (fwd != nullptr) { MQTTSNString fwdName = MQTTSNString_initializer; fwdName.cstring = const_cast(fwd->getName()); log(0, packet, &fwdName); /* get the packet from the encapsulation message */ MQTTSNGWEncapsulatedPacket encap; encap.desirialize(packet->getPacketData(), packet->getPacketLength()); nodeId.setId(encap.getWirelessNodeId()); client = fwd->getClient(&nodeId); packet = encap.getMQTTSNPacket(); } } else { /* Check the client belonging to QoS-1Proxy ? */ if (qosm1Proxy->isActive()) { const char *clientName = qosm1Proxy->getClientId(&senderAddr); if (clientName != nullptr) { client = qosm1Proxy->getClient(); if (!packet->isQoSMinusPUBLISH()) { log(clientName, packet); WRITELOG("%s %s %s can send only PUBLISH with QoS-1.%s\n", ERRMSG_HEADER, clientName, senderAddr.sprint(buf), ERRMSG_FOOTER); delete packet; continue; } } } if (client == nullptr) { client = _gateway->getClientList()->getClient(&senderAddr); } } if (client != nullptr) { log(client, packet, 0); if (client->isDisconnect() && packet->getType() != MQTTSN_CONNECT) { WRITELOG("%s MQTTSNGWClientRecvTask %s is not connecting.%s\n", ERRMSG_HEADER, client->getClientId(), ERRMSG_FOOTER); /* send DISCONNECT to the client, if it is not connected */ MQTTSNPacket* snPacket = new MQTTSNPacket(); snPacket->setDISCONNECT(0); ev = new Event(); ev->setClientSendEvent(client, snPacket); clientsendQue->post(ev); delete packet; continue; } else { ev = new Event(); ev->setClientRecvEvent(client, packet); packetEventQue->post(ev); } } else { /* new client */ if (packet->getType() == MQTTSN_CONNECT) { MQTTSNPacket_connectData data; memset(&data, 0, sizeof(MQTTSNPacket_connectData)); if (!packet->getCONNECT(&data)) { log(0, packet, &data.clientID); WRITELOG("%s CONNECT message form %s is incorrect.%s\n", ERRMSG_HEADER, senderAddr.sprint(buf), ERRMSG_FOOTER); delete packet; continue; } client = clientList->getClient(&data.clientID); if (fwd != nullptr) { if (client == nullptr) { /* create a new client */ client = clientList->createClient(0, &data.clientID, clientType); } /* Add to a forwarded client list of forwarder. */ fwd->addClient(client, &nodeId); } else { if (client) { /* Authentication is not required */ if (_gateway->getGWParams()->clientAuthentication == false) { client->setClientAddress(&senderAddr); } } else { /* create a new client */ client = clientList->createClient(&senderAddr, &data.clientID, clientType); } } log(client, packet, &data.clientID); if (client == nullptr) { WRITELOG("%s Client(%s) was rejected. CONNECT message has been discarded.%s\n", ERRMSG_HEADER, senderAddr.sprint(buf), ERRMSG_FOOTER); delete packet; continue; } /* post Client RecvEvent */ ev = new Event(); ev->setClientRecvEvent(client, packet); packetEventQue->post(ev); } else { log(client, packet, 0); if (packet->getType() == MQTTSN_ENCAPSULATED) { WRITELOG( "%s MQTTSNGWClientRecvTask Forwarder(%s) is not declared by ClientList file. message has been discarded.%s\n", ERRMSG_HEADER, _sensorNetwork->getSenderAddress()->sprint(buf), ERRMSG_FOOTER); } else { WRITELOG("%s MQTTSNGWClientRecvTask Client(%s) is not connecting. message has been discarded.%s\n", ERRMSG_HEADER, senderAddr.sprint(buf), ERRMSG_FOOTER); } delete packet; } } } } void ClientRecvTask::log(Client* client, MQTTSNPacket* packet, MQTTSNString* id) { const char* clientId; char cstr[MAX_CLIENTID_LENGTH + 1]; if (id) { if (id->cstring) { strncpy(cstr, id->cstring, strlen(id->cstring)); clientId = cstr; } else { memset((void*) cstr, 0, id->lenstring.len + 1); strncpy(cstr, id->lenstring.data, id->lenstring.len); clientId = cstr; } } else if (client) { clientId = client->getClientId(); } else { clientId = UNKNOWNCL; } log(clientId, packet); } void ClientRecvTask::log(const char* clientId, MQTTSNPacket* packet) { char pbuf[ SIZE_OF_LOG_PACKET * 3 + 1]; char msgId[6]; switch (packet->getType()) { case MQTTSN_SEARCHGW: WRITELOG(FORMAT_Y_G_G_NL, currentDateTime(), packet->getName(), LEFTARROW, CLIENT, packet->print(pbuf)); break; case MQTTSN_CONNECT: case MQTTSN_PINGREQ: WRITELOG(FORMAT_Y_G_G_NL, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf)); break; case MQTTSN_DISCONNECT: case MQTTSN_WILLTOPICUPD: case MQTTSN_WILLMSGUPD: case MQTTSN_WILLTOPIC: case MQTTSN_WILLMSG: WRITELOG(FORMAT_Y_G_G, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf)); break; case MQTTSN_PUBLISH: case MQTTSN_REGISTER: case MQTTSN_SUBSCRIBE: case MQTTSN_UNSUBSCRIBE: WRITELOG(FORMAT_G_MSGID_G_G_NL, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROW, clientId, packet->print(pbuf)); break; case MQTTSN_REGACK: case MQTTSN_PUBACK: case MQTTSN_PUBREC: case MQTTSN_PUBREL: case MQTTSN_PUBCOMP: WRITELOG(FORMAT_G_MSGID_G_G, currentDateTime(), packet->getName(), packet->getMsgId(msgId), LEFTARROW, clientId, packet->print(pbuf)); break; case MQTTSN_ENCAPSULATED: WRITELOG(FORMAT_Y_G_G, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf)); break; default: WRITELOG(FORMAT_W_NL, currentDateTime(), packet->getName(), LEFTARROW, clientId, packet->print(pbuf)); break; } }