int MQTTSProtocol_handleAdvertises(void* pack, int sock, char* clientAddr, Clients* client) { MQTTS_Advertise* advertisePack = (MQTTS_Advertise*)pack; Listener* listener = NULL; char* topic = NULL; char* data = NULL; int offset = 0; struct timeb ts; struct tm *timeinfo; FUNC_ENTRY; Log(LOG_PROTOCOL, 31, NULL, sock, "", clientAddr, advertisePack->gwId, advertisePack->duration); ftime(&ts); timeinfo = localtime(&ts.time); listener = Socket_getParentListener(sock); topic = malloc(40); sprintf(topic, "$SYS/broker/mqtts/listener/%d", listener->port); data = malloc(80); offset = strftime(data, 60, "%Y%m%d %H%M%S ", timeinfo); sprintf(&data[offset], "advertise from %s gateway id: %d duration: %d", clientAddr, advertisePack->gwId, advertisePack->duration); MQTTSPacket_free_packet(pack); MQTTProtocol_sys_publish(topic, data); free(topic); free(data); FUNC_EXIT; return 0; }
int MQTTSProtocol_handlePubacks(void* pack, int sock, char* clientAddr, Clients* client) { int rc = 0; MQTTS_PubAck* puback = (MQTTS_PubAck*)pack; FUNC_ENTRY; Log(LOG_PROTOCOL, 57, NULL, sock, clientAddr, client ? client->clientID : "", puback->msgId); /* look for the message by message id in the records of outbound messages for this client */ if (ListFindItem(client->outboundMsgs, &(puback->msgId), messageIDCompare) == NULL) Log(LOG_WARNING, 50, NULL, "PUBACK", client->clientID, puback->msgId); else { Messages* m = (Messages*)(client->outboundMsgs->current->content); if (m->qos != 1) Log(LOG_WARNING, 51, NULL, "PUBACK", client->clientID, puback->msgId, m->qos); else { Log(TRACE_MAX, 4, NULL, client->clientID, puback->msgId); MQTTProtocol_removePublication(m->publish); ListRemove(client->outboundMsgs, m); /* TODO: msgs counts */ /* (++state.msgs_sent);*/ } } MQTTSPacket_free_packet(pack); FUNC_EXIT_RC(rc); return rc; }
int MQTTSProtocol_handlePingresps(void* pack, int sock, char* clientAddr, Clients* client) { FUNC_ENTRY; client->ping_outstanding = 0; time( &(client->lastContact) ); MQTTSPacket_free_packet(pack); FUNC_EXIT; return 0; }
int MQTTSProtocol_handleSubscribes(void* pack, int sock, char* clientAddr, Clients* client) { int rc = 0; MQTTS_Subscribe* sub = (MQTTS_Subscribe*)pack; int isnew; int topicId = 0; char* topicName = NULL , *preDefinedTopicName = NULL; FUNC_ENTRY; Log(LOG_PROTOCOL, 67, NULL, sock, clientAddr, client ? client->clientID : "", sub->msgId, (sub->flags.QoS == 3) ? -1: sub->flags.QoS, sub->flags.topicIdType); // NORMAL (topic name is in subscribe packet) or SHORT topic name if (sub->flags.topicIdType == MQTTS_TOPIC_TYPE_NORMAL || sub->flags.topicIdType == MQTTS_TOPIC_TYPE_SHORT) { topicName = sub->topicName; sub->topicName = NULL; } // Pre-defined topic else if (sub->flags.topicIdType == MQTTS_TOPIC_TYPE_PREDEFINED && client != NULL && sub->topicId != 0) { char *name = MQTTSProtocol_getPreRegisteredTopicName(client, sub->topicId) ; if (name) { preDefinedTopicName = MQTTSProtocol_replaceTopicNamePlaceholders(client , name ) ; } topicName = preDefinedTopicName ; topicId = sub->topicId; } // If topic name not found send SubAck with Rejected - Invalid topic ID if (topicName == NULL) rc = MQTTSPacket_send_subAck(client, sub, 0, sub->flags.QoS, MQTTS_RC_REJECTED_INVALID_TOPIC_ID); else { if (sub->flags.topicIdType == MQTTS_TOPIC_TYPE_NORMAL && !Topics_hasWildcards(topicName)) { char* regTopicName = malloc(strlen(topicName)+1); strcpy(regTopicName, topicName); topicId = (MQTTSProtocol_registerTopic(client, regTopicName))->id; } isnew = SubscriptionEngines_subscribe(bstate->se, client->clientID, topicName, sub->flags.QoS, client->noLocal, (client->cleansession == 0), PRIORITY_NORMAL); if ( (rc = MQTTSPacket_send_subAck(client, sub, topicId, sub->flags.QoS, MQTTS_RC_ACCEPTED)) == 0) if ((client->noLocal == 0) || isnew) MQTTProtocol_processRetaineds(client, topicName,sub->flags.QoS, PRIORITY_NORMAL); } time( &(client->lastContact) ); MQTTSPacket_free_packet(pack); if (preDefinedTopicName) free (preDefinedTopicName); FUNC_EXIT_RC(rc); return rc; }
int MQTTSProtocol_handlePingreqs(void* pack, int sock, char* clientAddr, Clients* client) { int rc = 0; FUNC_ENTRY; rc = MQTTSPacket_send_pingResp(client); time( &(client->lastContact) ); MQTTSPacket_free_packet(pack); FUNC_EXIT_RC(rc); return rc; }
int MQTTSProtocol_handleRegacks(void* pack, int sock, char* clientAddr, Clients* client) { int rc = 0; MQTTS_RegAck* regack = (MQTTS_RegAck*)pack; FUNC_ENTRY; if (client->pendingRegistration == NULL || regack->msgId != client->pendingRegistration->msgId) { /* unexpected regack*/ } else if (!client->outbound) { if (regack->topicId != client->pendingRegistration->registration->id) { /* unexpected regack*/ } else if (regack->returnCode != MQTTS_RC_ACCEPTED) { /* rejected ack... what do we do now? */ } else { free(client->pendingRegistration); client->pendingRegistration = NULL; rc = MQTTProtocol_processQueued(client); } } else /* outbound client */ { if (regack->returnCode != MQTTS_RC_ACCEPTED) { /* rejected ack... what do we do now? */ } else { Registration* reg = client->pendingRegistration->registration; free(client->pendingRegistration); client->pendingRegistration = NULL; reg->id = regack->topicId; ListAppend(client->registrations, reg, sizeof(reg) + strlen(reg->topicName)+1); rc = MQTTProtocol_processQueued(client); } } time( &(client->lastContact) ); MQTTSPacket_free_packet(pack); FUNC_EXIT_RC(rc); return rc; }
int MQTTSProtocol_handleWillMsgUpds(void* pack, int sock, char* clientAddr, Clients* client) { int rc = 0; MQTTS_WillMsgUpd* willMsg = (MQTTS_WillMsgUpd*)pack; FUNC_ENTRY; MQTTProtocol_setWillMsg(client, willMsg->willMsg); willMsg->willMsg = NULL; rc = MQTTSPacket_send_willMsgResp(client); time( &(client->lastContact) ); MQTTSPacket_free_packet(pack); FUNC_EXIT_RC(rc); return rc; }
int MQTTSProtocol_handlePubrels(void* pack, int sock, char* clientAddr, Clients* client) { int rc = 0; MQTTS_PubRel* pubrel = (MQTTS_PubRel*)pack; FUNC_ENTRY; /* look for the message by message id in the records of inbound messages for this client */ if (ListFindItem(client->inboundMsgs, &(pubrel->msgId), messageIDCompare) == NULL) { /* TODO: no dup flag in mqtts... not sure this is right if (pubrel->header.dup == 0) Log(LOG_WARNING, 50, "PUBREL", client->clientID, pubrel->msgId); else */ /* Apparently this is "normal" behavior, so we don't need to issue a warning */ rc = MQTTSPacket_send_pubcomp(client,pubrel->msgId); } else { Messages* m = (Messages*)(client->inboundMsgs->current->content); if (m->qos != 2) Log(LOG_WARNING, 51, NULL, "PUBREL", client->clientID, pubrel->msgId, m->qos); else if (m->nextMessageType != PUBREL) Log(LOG_WARNING, 52, NULL, "PUBREL", client->clientID, pubrel->msgId); else { Publish publish; /* send pubcomp before processing the publications because a lot of return publications could fill up the socket buffer */ rc = MQTTSPacket_send_pubcomp(client, pubrel->msgId); publish.header.bits.qos = m->qos; publish.header.bits.retain = m->retain; publish.msgId = m->msgid; publish.topic = m->publish->topic; publish.payload = m->publish->payload; publish.payloadlen = m->publish->payloadlen; Protocol_processPublication(&publish, client->clientID); MQTTProtocol_removePublication(m->publish); ListRemove(client->inboundMsgs, m); /* TODO: msgs counts */ /* ++(state.msgs_received); */ } } time( &(client->lastContact) ); MQTTSPacket_free_packet(pack); FUNC_EXIT_RC(rc); return rc; }
int MQTTSProtocol_handleWillMsgReqs(void* pack, int sock, char* clientAddr) { Clients* client = Bridge_getClient(sock); FUNC_ENTRY; if (client == NULL) { //TODO: what now? } else MQTTSPacket_send_willMsg(client); MQTTSPacket_free_packet(pack); FUNC_EXIT; return 0; }
int MQTTSProtocol_handleWillMsgReqs(void* pack, int sock, char* clientAddr, Clients* client) { FUNC_ENTRY; //client = Bridge_getClient(sock); Log(LOG_PROTOCOL, 47, NULL, client->socket, client->addr, client->clientID); if (client == NULL) { //TODO: what now? } else MQTTSPacket_send_willMsg(client); MQTTSPacket_free_packet(pack); FUNC_EXIT; return 0; }
int MQTTSProtocol_handlePubrecs(void* pack, int sock, char* clientAddr, Clients* client) { int rc = 0; MQTTS_PubRec* pubrec = (MQTTS_PubRec*)pack; FUNC_ENTRY; Log(LOG_PROTOCOL, 15, NULL, pubrec->msgId, client->clientID); /* look for the message by message id in the records of outbound messages for this client */ client->outboundMsgs->current = NULL; if (ListFindItem(client->outboundMsgs, &(pubrec->msgId), messageIDCompare) == NULL) { /* No Dupe flag in MQTTs if (pubrec->header.dup == 0) */ Log(LOG_WARNING, 50, NULL, "PUBREC", client->clientID, pubrec->msgId); } else { Messages* m = (Messages*)(client->outboundMsgs->current->content); if (m->qos != 2) { /* No Dupe flag in MQTTs if (pubrec->header.dup == 0) */ Log(LOG_WARNING, 51, NULL, "PUBREC", client->clientID, pubrec->msgId, m->qos); } else if (m->nextMessageType != PUBREC) { /* No Dupe flag in MQTTs if (pubrec->header.dup == 0) */ Log(LOG_WARNING, 52, NULL, "PUBREC", client->clientID, pubrec->msgId); } else { rc = MQTTSPacket_send_pubrel(client, pubrec->msgId); m->nextMessageType = PUBCOMP; time(&(m->lastTouch)); } } MQTTSPacket_free_packet(pack); FUNC_EXIT_RC(rc); return rc; }
int MQTTSProtocol_handleWillTopicUpds(void* pack, int sock, char* clientAddr, Clients* client) { int rc = 0; MQTTS_WillTopicUpd* willTopic = (MQTTS_WillTopicUpd*)pack; FUNC_ENTRY; if (willTopic->willTopic != NULL) { MQTTProtocol_setWillTopic(client, willTopic->willTopic, willTopic->flags.retain, willTopic->flags.QoS); willTopic->willTopic = NULL; } else MQTTProtocol_clearWill(client); rc = MQTTSPacket_send_willTopicResp(client); time( &(client->lastContact) ); MQTTSPacket_free_packet(pack); FUNC_EXIT_RC(rc); return rc; }
int MQTTSProtocol_handleWillTopics(void* pack, int sock, char* clientAddr, Clients* client) { MQTTS_WillTopic* willTopic = (MQTTS_WillTopic*)pack; int rc = 0; FUNC_ENTRY; Log(LOG_PROTOCOL, 45, NULL, sock, clientAddr, client->clientID, willTopic->flags.QoS, willTopic->flags.retain, willTopic->willTopic); if (client->connect_state == 1) { MQTTProtocol_setWillTopic(client, willTopic->willTopic, willTopic->flags.retain, willTopic->flags.QoS); willTopic->willTopic = NULL; client->connect_state = 2; rc = MQTTSPacket_send_willMsgReq(client); } MQTTSPacket_free_packet(pack); time( &(client->lastContact) ); FUNC_EXIT_RC(rc); return rc; }
int MQTTSProtocol_handleDisconnects(void* pack, int sock, char* clientAddr, Clients* client) { MQTTS_Disconnect* disc = (MQTTS_Disconnect*)pack; FUNC_ENTRY; Log(LOG_PROTOCOL, 79, NULL, socket, client->addr, client->clientID, disc->duration); client->good = 0; /* don't try and send log message to this client if it is subscribed to $SYS/broker/log */ Log((bstate->connection_messages) ? LOG_INFO : LOG_PROTOCOL, 38, NULL, client->clientID); // Remove all registrations if duration is zero. // Otherwise keep it. It is a sleeping client if ( disc->duration == 0 ) { MQTTSProtocol_emptyRegistrationList(client->registrations); } MQTTProtocol_closeSession(client, 0); MQTTSPacket_free_packet(pack); FUNC_EXIT; return 0; }
int MQTTSProtocol_handleWillMsgs(void* pack, int sock, char* clientAddr, Clients* client) { int rc = 0; MQTTS_WillMsg* willMsg = (MQTTS_WillMsg*)pack; FUNC_ENTRY; Log(LOG_PROTOCOL, 49, NULL, sock, clientAddr, client->clientID, willMsg->willMsg); if (client->connect_state == 2) { MQTTProtocol_setWillMsg(client, willMsg->willMsg); willMsg->willMsg = NULL; client->connect_state = 0; client->connected = 1; rc = MQTTSPacket_send_connack(client, 0); /* send response */ } MQTTSPacket_free_packet(pack); time( &(client->lastContact) ); FUNC_EXIT_RC(rc); return rc; }
int MQTTSProtocol_handleUnsubscribes(void* pack, int sock, char* clientAddr, Clients* client) { int rc = 0; MQTTS_Unsubscribe* unsub = (MQTTS_Unsubscribe*)pack; char* topicName = NULL; FUNC_ENTRY; if (unsub->flags.topicIdType == 0x01) topicName=MQTTSProtocol_getRegisteredTopicName(client, unsub->topicId); else topicName = unsub->topicName; if (topicName != NULL) SubscriptionEngines_unsubscribe(bstate->se, client->clientID, topicName); rc = MQTTSPacket_send_unsubAck(client, unsub->msgId); time( &(client->lastContact) ); MQTTSPacket_free_packet(pack); FUNC_EXIT_RC(rc); return rc; }
int main(int argc, char *argv[]) { HeapScan(); MQTTS_Publish* pack = malloc(sizeof(MQTTS_Publish)); pack->header.type = MQTTS_PUBLISH; pack->data = malloc(10); MQTTSPacket_free_packet((MQTTS_Header*)pack); Clients* client = malloc(sizeof(Clients)); client->cleansession = 1; client->clientID = "a"; client->keepAliveInterval = 15; /* MQTTSPacket_send_connect(client); */ /* 7:4:4:1:0:15:97 */ free(client); Heap_terminate(); return 0; }
int MQTTSProtocol_handlePubcomps(void* pack, int sock, char* clientAddr, Clients* client) { int rc = 0; MQTTS_PubComp* pubcomp = (MQTTS_PubComp*)pack; FUNC_ENTRY; Log(LOG_PROTOCOL, 59, NULL, sock, clientAddr, client ? client->clientID : "", pubcomp->msgId); /* look for the message by message id in the records of outbound messages for this client */ if (ListFindItem(client->outboundMsgs, &(pubcomp->msgId), messageIDCompare) == NULL) { /* No Dupe flag in MQTTs if (pubcomp->header.dup == 0) */ Log(LOG_WARNING, 50, NULL, "PUBCOMP", client->clientID, pubcomp->msgId); } else { Messages* m = (Messages*)(client->outboundMsgs->current->content); if (m->qos != 2) Log(LOG_WARNING, 51, NULL, "PUBCOMP", client->clientID, pubcomp->msgId, m->qos); else { if (m->nextMessageType != PUBCOMP) Log(LOG_WARNING, 52, NULL, "PUBCOMP", client->clientID, pubcomp->msgId); else { Log(TRACE_MAX, 5, NULL, client->clientID, pubcomp->msgId); MQTTProtocol_removePublication(m->publish); ListRemove(client->outboundMsgs, m); /* TODO: msgs counts */ /*(++state.msgs_sent); */ } } } MQTTSPacket_free_packet(pack); FUNC_EXIT_RC(rc); return rc; }
int MQTTSProtocol_handleSubacks(void* pack, int sock, char* clientAddr, Clients* client) { int rc = 0; MQTTS_SubAck* suback = (MQTTS_SubAck*)pack; FUNC_ENTRY; Log(LOG_PROTOCOL, 69, NULL, client->socket, client->addr, client->clientID, suback->msgId, suback->topicId, suback->returnCode); if (client->pendingSubscription == NULL || suback->msgId != client->pendingSubscription->msgId) { /* TODO: unexpected suback*/ } else if (suback->returnCode != MQTTS_RC_ACCEPTED) { /* TODO: rejected ack... what do we do now? */ } else { if (suback->topicId > 0) { Registration* reg = malloc(sizeof(Registration)); reg->topicName = client->pendingSubscription->topicName; reg->id = suback->topicId; ListAppend(client->registrations, reg, sizeof(reg) + strlen(reg->topicName)+1); } else free(client->pendingSubscription->topicName); free(client->pendingSubscription); client->pendingSubscription = NULL; /* TODO: could proactively call Bridge_subscribe() */ } time( &(client->lastContact) ); MQTTSPacket_free_packet(pack); FUNC_EXIT_RC(rc); return rc; }
int MQTTSProtocol_handleRegisters(void* pack, int sock, char* clientAddr, Clients* client) { int rc = 0; MQTTS_Register* registerPack = (MQTTS_Register*)pack; ListElement* elem = NULL; int topicId = 0; FUNC_ENTRY; Log(LOG_PROTOCOL, 51, NULL, sock, clientAddr, client ? client->clientID : "", registerPack->msgId, registerPack->topicId, registerPack->topicName); if ((elem = ListFindItem(client->registrations, registerPack->topicName, registeredTopicNameCompare)) == NULL) { topicId = (MQTTSProtocol_registerTopic(client, registerPack->topicName))->id; registerPack->topicName = NULL; } else topicId = ((Registration*)(elem->content))->id; rc = MQTTSPacket_send_regAck(client, registerPack->msgId, topicId, MQTTS_RC_ACCEPTED); time( &(client->lastContact) ); MQTTSPacket_free_packet(pack); FUNC_EXIT_RC(rc); return rc; }
void MQTTSProtocol_timeslice(int sock) { int error; MQTTS_Header* pack = NULL; char *clientAddr = NULL ; Clients* client = NULL; struct sockaddr_in6 from; uint8_t *wirelessNodeId = NULL ; uint8_t wirelessNodeIdLen = 0 ; FUNC_ENTRY; pack = MQTTSPacket_Factory(sock, &clientAddr, (struct sockaddr *)&from, &wirelessNodeId , &wirelessNodeIdLen , &error); if (clientAddr) { // IF FRWDENCAP, append ":[WirelessNodeId in HEX]" to clientAddr if (wirelessNodeId && wirelessNodeIdLen > 0) { char* ptr = &clientAddr[strlen(clientAddr)] ; *(ptr++) = ':' ; *(ptr++) = '[' ; int i ; for (i = 0 ; i < wirelessNodeIdLen ; i++) { ptr += sprintf(ptr, "%02X", wirelessNodeId[i]); } *(ptr++) = ']' ; *ptr = '\0'; } client = Protocol_getclientbyaddr(clientAddr); } #if !defined(NO_BRIDGE) if (client == NULL) client = Protocol_getoutboundclient(sock); #endif if (pack == NULL) { if (error == SOCKET_ERROR || error == UDPSOCKET_INCOMPLETE) { if (client != NULL) { client->good = 0; /* make sure we don't try and send messages to ourselves */ //client->connected = 0; if (error == SOCKET_ERROR) Log(LOG_WARNING, 18, NULL, client->clientID, client->socket, Socket_getpeer(client->socket)); else Log(LOG_WARNING, 19, NULL, client->clientID, client->socket, Socket_getpeer(client->socket)); MQTTProtocol_closeSession(client, 0); } else { if (error == SOCKET_ERROR) Log(LOG_WARNING, 20, NULL, sock, Socket_getpeer(sock)); else Log(LOG_WARNING, 21, NULL, sock, Socket_getpeer(sock)); /*Socket_close(sock);*/ } } } else if (pack->header.type != MQTTS_CONNECT && handle_packets[(int)pack->header.type] == NULL) { Log(LOG_WARNING, 22, NULL, pack->header.type, handle_packets[(int)pack->header.type]); MQTTSPacket_free_packet(pack); } else if (client == NULL && pack->header.type != MQTTS_CONNECT && pack->header.type != MQTTS_ADVERTISE && pack->header.type != MQTTS_SEARCHGW && (pack->header.type != MQTTS_PUBLISH || ((MQTTS_Publish*)pack)->flags.QoS != 3)) { Log(LOG_WARNING, 23, NULL, sock, Socket_getpeer(sock), MQTTSPacket_name(pack->header.type)); MQTTSPacket_free_packet(pack); } else if ( pack->header.type == MQTTS_CONNECT ) { MQTTSProtocol_handleConnects(pack, sock, clientAddr, client, wirelessNodeId , wirelessNodeIdLen) ; } else { (*handle_packets[(int)pack->header.type])(pack, sock, clientAddr, client); /* TODO: * - error handling * - centralise calls to time( &(c->lastContact) ); (currently in each _handle* function */ } FUNC_EXIT; }
int MQTTSProtocol_handleConnacks(void* pack, int sock, char* clientAddr) { MQTTS_Connack* connack = (MQTTS_Connack*)pack; int rc = 0; Clients* client = NULL; BridgeConnections* bc = Bridge_getBridgeConnection(sock); FUNC_ENTRY; if (bc == NULL) { rc = SOCKET_ERROR; goto exit; } if (bc->primary && bc->primary->socket == sock) client = bc->primary; else client = bc->backup; if (connack->returnCode != MQTTS_RC_ACCEPTED) { if (client) { if (client->noLocal == 1) client->noLocal = 0; else Log(LOG_WARNING, 132, NULL, connack->returnCode, client->clientID); MQTTProtocol_closeSession(client, 0); } else Socket_close(sock); } else if (client) { ListElement* addr = bc->cur_address; if (client == bc->primary && bc->round_robin == 0) addr = bc->addresses->first; Log(LOG_INFO, 133, NULL, bc->name, (char*)(addr->content)); client->connect_state = 3; //should have been 2 before bc->last_connect_result = connack->returnCode; (bc->no_successful_connections)++; client->connected = 1; client->good = 1; client->ping_outstanding = 0; time(&(client->lastContact)); if (client->will) { Publish pub; Messages* m = NULL; MQTTProtocol_sys_publish(client->will->topic, "1"); pub.payload = "1"; pub.payloadlen = 1; pub.topic = client->will->topic; MQTTProtocol_startOrQueuePublish(client, &pub, 0, client->will->retained, &m); } if (client == bc->primary && (bc->backup && (bc->backup->connected == 1 || bc->backup->connect_state != 0))) { Log(LOG_INFO, 134, NULL, (char*)(bc->cur_address->content)); MQTTProtocol_closeSession(bc->backup, 0); } //if (bc->addresses->count > 1 || bc->no_successful_connections == 1) Bridge_subscribe(bc, client); } //Clients* client = Protocol_getclientbyaddr(clientAddr); MQTTSPacket_free_packet(pack); exit: FUNC_EXIT_RC(rc); return rc; }
int MQTTSProtocol_startPublishCommon(Clients* client, Publish* mqttPublish, int dup, int qos, int retained) { int rc = 0; Registration* registration = NULL; MQTTS_Publish* pub = NULL; FUNC_ENTRY; pub = malloc(sizeof(MQTTS_Publish)); memset(pub, '\0', sizeof(MQTTS_Publish)); if (strlen(mqttPublish->topic) > 2 && (registration = MQTTSProtocol_getRegisteredTopicId(client, mqttPublish->topic)) == 0 && (qos != 3)) { /* TODO: Logic elsewhere _should_ mean this case never happens... */ /*printf("I want to send a msg to %s on topic %s but it isn't registered\n",client->clientID,mqttPublish->topic); */ } else { pub->header.type = MQTTS_PUBLISH; pub->flags.QoS = qos; pub->flags.retain = retained; pub->flags.dup = dup; pub->msgId = mqttPublish->msgId; pub->data = mqttPublish->payload; pub->shortTopic = NULL; if (strlen(mqttPublish->topic) > 2 && qos == 3) { pub->topicId = strlen(mqttPublish->topic); pub->dataLen = mqttPublish->payloadlen + strlen(mqttPublish->topic); pub->data = malloc(pub->dataLen); memcpy(pub->data, mqttPublish->topic, pub->topicId); memcpy(&pub->data[pub->topicId], mqttPublish->payload, mqttPublish->payloadlen); pub->flags.topicIdType = MQTTS_TOPIC_TYPE_NORMAL; } else if (mqttPublish->payloadlen > 65535) { /* TODO: add a message for truncated payload */ /* printf("Truncating a %d byte message sent to %s on topic %s\n",mqttPublish->payloadlen, client->clientID, mqttPublish->topic);*/ pub->dataLen = 65535; } else pub->dataLen = mqttPublish->payloadlen; pub->header.len = 7 + pub->dataLen; if (strlen(mqttPublish->topic) < 3) { pub->flags.topicIdType = MQTTS_TOPIC_TYPE_SHORT; pub->shortTopic = mqttPublish->topic; } else if (qos != 3) { pub->topicId = registration->id; pub->flags.topicIdType = registration->topicIdType; } rc = MQTTSPacket_send_publish(client, pub); if (pub->data == mqttPublish->payload) pub->data = NULL; pub->shortTopic = NULL; } MQTTSPacket_free_packet((MQTTS_Header*)pub); FUNC_EXIT_RC(rc); return rc; }
int MQTTSProtocol_handlePublishes(void* pack, int sock, char* clientAddr, Clients* client) { int rc = 0; char* topicName = NULL, *expandedPreDefinedTopicName = NULL; MQTTS_Publish* pub = NULL; FUNC_ENTRY; pub = (MQTTS_Publish*)pack; Log(LOG_PROTOCOL, 55, NULL, sock, clientAddr, client ? client->clientID : "", pub->msgId, pub->flags.QoS, pub->flags.retain); // Normal - registered topic if (pub->flags.topicIdType == MQTTS_TOPIC_TYPE_NORMAL && client != NULL && pub->topicId != 0) { /* copy the topic name as it will be freed later */ char* name = MQTTSProtocol_getRegisteredTopicName(client, pub->topicId); if (name) { topicName = malloc(strlen(name) + 1); strcpy(topicName, name); } } // Pre-defined topics else if (pub->flags.topicIdType == MQTTS_TOPIC_TYPE_PREDEFINED && client != NULL && pub->topicId != 0) { /* copy the topic name as it will be freed later */ char *origPreDefinedTopicName = MQTTSProtocol_getPreDefinedTopicName(client, pub->topicId) ; if (origPreDefinedTopicName) { expandedPreDefinedTopicName = MQTTSProtocol_replaceTopicNamePlaceholders(client, origPreDefinedTopicName) ; } // If original and expanded predef topic names are same, use expanded // while it is already a copy of orig name if (strcmp(origPreDefinedTopicName, expandedPreDefinedTopicName) == 0) { topicName = expandedPreDefinedTopicName ; } else { topicName = malloc(strlen(origPreDefinedTopicName)+1); strcpy(topicName, origPreDefinedTopicName); } } // Short topic names else if (pub->flags.topicIdType == MQTTS_TOPIC_TYPE_SHORT && pub->shortTopic != NULL) { topicName = pub->shortTopic; pub->shortTopic = NULL; /* will be freed in Protocol_handlePublishes */ } // If topic name not found send PubAck with Rejected - Invalid topic ID if (topicName == NULL) { rc = MQTTSPacket_send_puback(client, pub->topicId , pub->msgId, MQTTS_RC_REJECTED_INVALID_TOPIC_ID); } else { Publish* publish = malloc(sizeof(Publish)); publish->header.bits.type = PUBLISH; publish->header.bits.qos = pub->flags.QoS; publish->header.bits.retain = pub->flags.retain; publish->header.bits.dup = pub->flags.dup; publish->msgId = pub->msgId; publish->payload = pub->data; publish->payloadlen = pub->dataLen; publish->topic = topicName; rc = Protocol_handlePublishes(publish, sock, client, client ? client->clientID : clientAddr, pub->topicId); // If predefined topic Id and predefined topic name contains [ClientId] // publish message to expanded topic name too. if ( pub->flags.topicIdType == MQTTS_TOPIC_TYPE_PREDEFINED && topicName != expandedPreDefinedTopicName) { publish = malloc(sizeof(Publish)); publish->header.bits.type = PUBLISH; publish->header.bits.qos = pub->flags.QoS; publish->header.bits.retain = pub->flags.retain; publish->header.bits.dup = pub->flags.dup; publish->msgId = pub->msgId; publish->payload = pub->data; publish->payloadlen = pub->dataLen; publish->topic = expandedPreDefinedTopicName; rc = Protocol_handlePublishes(publish, sock, client, client ? client->clientID : clientAddr, pub->topicId); } } if (client != NULL) time( &(client->lastContact) ); MQTTSPacket_free_packet(pack); FUNC_EXIT_RC(rc); return rc; }
int MQTTSProtocol_handleConnects(void* pack, int sock, char* clientAddr, Clients* client, uint8_t* wirelessNodeId , uint8_t wirelessNodeIdLen) { MQTTS_Connect* connect = (MQTTS_Connect*)pack; Listener* list = NULL; int terminate = 0; Node* elem = NULL; int rc = 0; int existingClient = 0; FUNC_ENTRY; Log(LOG_PROTOCOL, 39, NULL, sock, clientAddr, client ? client->clientID : "", connect->flags.cleanSession); if (bstate->clientid_prefixes->count > 0 && !ListFindItem(bstate->clientid_prefixes, connect->clientID, clientPrefixCompare)) { Log(LOG_WARNING, 31, NULL, connect->clientID); terminate = 1; } else { list = Socket_getParentListener(sock); if (list->max_connections > -1 && list->connections->count > list->max_connections) { /* TODO: why is this commented out? delete if not needed //MQTTPacket_send_connack(3, sock); */ Log(LOG_WARNING, 141, NULL, connect->clientID, list->max_connections, list->port); terminate = 1; } else if (connect->protocolID != 1) { Log(LOG_WARNING, 32, NULL, "MQTT-S", connect->protocolID); /* TODO: why is this commented out? delete if not needed //MQTTPacket_send_connack(1, sock); */ terminate = 1; } } if (terminate) { /*TODO: process the terminate*/ MQTTSPacket_free_packet(pack); goto exit; } if (client != NULL && !strcmp(client->clientID, connect->clientID)) { /* Connect for a new client id on a used addr * TODO: clean out 'old' Client (that may be 'connected') */ } elem = TreeFindIndex(bstate->mqtts_clients, connect->clientID, 1); if (elem == NULL) { client = TreeRemoveKey(bstate->disconnected_mqtts_clients, connect->clientID); if (client == NULL) /* this is a totally new connection */ { /* Brand new client connection */ int i; client = malloc(sizeof(Clients)); memset(client, '\0', sizeof(Clients)); client->protocol = PROTOCOL_MQTTS; client->outboundMsgs = ListInitialize(); client->inboundMsgs = ListInitialize(); for (i = 0; i < PRIORITY_MAX; ++i) client->queuedMsgs[i] = ListInitialize(); client->registrations = ListInitialize(); client->noLocal = 0; /* (connect->version == PRIVATE_PROTOCOL_VERSION) ? 1 : 0; */ client->clientID = connect->clientID; connect->clientID = NULL; /* don't want to free this space as it is being used in the clients tree below */ // Set Wireless Node ID if exists if ( wirelessNodeId == NULL) { client->wirelessNodeId = NULL ; client->wirelessNodeIdLen = 0 ; } else { client->wirelessNodeId = malloc((sizeof(uint8_t) * wirelessNodeIdLen)) ; memcpy( client->wirelessNodeId , wirelessNodeId , sizeof(uint8_t) * wirelessNodeIdLen) ; client->wirelessNodeIdLen = wirelessNodeIdLen ; } } // // client == NULL else /* there is an existing disconnected client */ { /* Reconnect of a disconnected client */ free(client->addr); client->connect_state = 0; client->connected = 0; /* Do not connect until we know the connack has been sent */ // Delete Wireless Node ID if exists in existing client if ( wirelessNodeId == NULL) { if ( client->wirelessNodeId != NULL) free( client->wirelessNodeId ) ; client->wirelessNodeId = NULL ; client->wirelessNodeIdLen = 0 ; } else // Replace existing Wireless Node ID with value from current connect packet { if ( client->wirelessNodeId != NULL) free ( client->wirelessNodeId ) ; client->wirelessNodeId = malloc((sizeof(uint8_t) * wirelessNodeIdLen)) ; memcpy( client->wirelessNodeId , wirelessNodeId , sizeof(uint8_t) * wirelessNodeIdLen) ; client->wirelessNodeIdLen = wirelessNodeIdLen ; } } // client != NULL client->good = 1; /* good is set to 0 in disconnect, so we need to reset it here */ client->keepAliveInterval = connect->keepAlive; client->cleansession = connect->flags.cleanSession; client->socket = sock; client->addr = malloc(strlen(clientAddr)+1); strcpy(client->addr, clientAddr); TreeAdd(bstate->mqtts_clients, client, sizeof(Clients) + strlen(client->clientID)+1 + 3*sizeof(List)); if (client->cleansession) MQTTProtocol_removeAllSubscriptions(client->clientID); /* clear any persistent subscriptions */ if (connect->flags.will) { client->connect_state = 1; rc = MQTTSPacket_send_willTopicReq(client); } else { client->connected = 1; rc = MQTTSPacket_send_connack(client, 0); /* send response */ } } else { /* Reconnect of a connected client */ client = (Clients*)(elem->content); if (client->connected) { Log(LOG_INFO, 34, NULL, connect->clientID, clientAddr); if (client->socket != sock) Socket_close(client->socket); } client->socket = sock; client->connected = 0; /* Do not connect until we know the connack has been sent */ client->connect_state = 0; // Delete Wireless Node ID if exists in existing client if ( wirelessNodeId == NULL) { if ( client->wirelessNodeId != NULL) free( client->wirelessNodeId ) ; client->wirelessNodeId = NULL ; client->wirelessNodeIdLen = 0 ; } else // Replace existing Wireless Node ID with value from current connect packet { if ( client->wirelessNodeId != NULL) free ( client->wirelessNodeId ) ; client->wirelessNodeId = malloc((sizeof(uint8_t) * wirelessNodeIdLen)) ; memcpy( client->wirelessNodeId , wirelessNodeId , sizeof(uint8_t) * wirelessNodeIdLen) ; client->wirelessNodeIdLen = wirelessNodeIdLen ; } client->good = 1; if (client->addr != NULL) free(client->addr); client->addr = malloc(strlen(clientAddr)+1); strcpy(client->addr, clientAddr); client->cleansession = connect->flags.cleanSession; if (client->cleansession) { int i; MQTTProtocol_removeAllSubscriptions(client->clientID); /* empty pending message lists */ MQTTProtocol_emptyMessageList(client->outboundMsgs); MQTTProtocol_emptyMessageList(client->inboundMsgs); for (i = 0; i < PRIORITY_MAX; ++i) MQTTProtocol_emptyMessageList(client->queuedMsgs[i]); MQTTProtocol_clearWill(client); } /* registrations are always cleared */ MQTTSProtocol_emptyRegistrationList(client->registrations); /* have to remove and re-add client so it is in the right order for new socket */ if (client->socket != sock) { TreeRemoveNodeIndex(bstate->mqtts_clients, elem, 1); TreeRemoveKeyIndex(bstate->mqtts_clients, &client->socket, 0); client->socket = sock; TreeAdd(bstate->mqtts_clients, client, sizeof(Clients) + strlen(client->clientID)+1 + 3*sizeof(List)); } client->keepAliveInterval = connect->keepAlive; client->pendingRegistration = NULL; #if !defined(NO_BRIDGE) client->pendingSubscription = NULL; #endif if (connect->flags.will) { client->connect_state = 1; rc = MQTTSPacket_send_willTopicReq(client); } else { client->connected = 1; rc = MQTTSPacket_send_connack(client,0); /* send response */ } } if (existingClient) MQTTProtocol_processQueued(client); Log(LOG_INFO, 0, "Client connected to udp port %d from %s (%s)", list->port, client->clientID, clientAddr); MQTTSPacket_free_packet(pack); time( &(client->lastContact) ); exit: FUNC_EXIT_RC(rc); return rc; }