int Protocol_handlePublishes(Publish* publish, int sock, Clients* client, char* clientid) { int rc = TCPSOCKET_COMPLETE; #if !defined(SINGLE_LISTENER) Listener* listener = NULL; #endif FUNC_ENTRY; if (Protocol_isClientQuiescing(client)) goto exit; /* don't accept new work */ #if !defined(SINGLE_LISTENER) listener = Socket_getParentListener(sock); if (listener && listener->mount_point) { char* temp = malloc(strlen(publish->topic) + strlen(listener->mount_point) + 1); strcpy(temp, listener->mount_point); strcat(temp, publish->topic); free(publish->topic); publish->topic = temp; } #endif #if !defined(NO_BRIDGE) if (client && client->outbound) Bridge_handleInbound(client, publish); #endif if (publish->header.bits.qos == 0) { if (strlen(publish->topic) < 5 || strncmp(publish->topic, sysprefix, strlen(sysprefix)) != 0) { ++(bstate->msgs_received); bstate->bytes_received += publish->payloadlen; } Protocol_processPublication(publish, clientid); } else if (publish->header.bits.qos == 1) { /* send puback before processing the publications because a lot of return publications could fill up the socket buffer */ #if defined(MQTTS) if (client->protocol == PROTOCOL_MQTTS) rc = MQTTSPacket_send_puback(client, publish->msgId, MQTTS_RC_ACCEPTED); else #endif rc = MQTTPacket_send_puback(publish->msgId, sock, clientid); /* if we get a socket error from sending the puback, should we ignore the publication? */ Protocol_processPublication(publish, clientid); ++(bstate->msgs_received); bstate->bytes_received += publish->payloadlen; } else if (publish->header.bits.qos == 2 && client->inboundMsgs->count < bstate->max_inflight_messages) { /* store publication in inbound list - if list is full, ignore and rely on client retry */ int len; ListElement* listElem = NULL; Messages* m = NULL; Publications* p = MQTTProtocol_storePublication(publish, &len); if ((listElem = ListFindItem(client->inboundMsgs, &publish->msgId, messageIDCompare)) != NULL) { m = (Messages*)(listElem->content); MQTTProtocol_removePublication(m->publish); /* remove old publication data - could be different */ } else m = malloc(sizeof(Messages)); m->publish = p; m->msgid = publish->msgId; m->qos = publish->header.bits.qos; m->retain = publish->header.bits.retain; m->nextMessageType = PUBREL; if (listElem == NULL) ListAppend(client->inboundMsgs, m, sizeof(Messages) + len); #if defined(MQTTS) if (client->protocol == PROTOCOL_MQTTS) rc = MQTTSPacket_send_pubrec(client, publish->msgId); else #endif rc = MQTTPacket_send_pubrec(publish->msgId, sock, clientid); } else if (publish->header.bits.qos == 3) /* only applies to MQTT-S */ { publish->header.bits.qos = 0; Protocol_processPublication(publish, clientid); } exit: if (sock > 0) MQTTPacket_freePublish(publish); 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; }