static void AckStatusCallback(AWS_IoT_Client *pClient, char *topicName, uint16_t topicNameLen,
							  IoT_Publish_Message_Params *params, void *pData) {
	int32_t tokenCount;
	uint8_t i;
	void *pJsonHandler = NULL;
	char temporaryClientToken[MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE];

	IOT_UNUSED(pClient);
	IOT_UNUSED(topicNameLen);
	IOT_UNUSED(pData);

	if(params->payloadLen > SHADOW_MAX_SIZE_OF_RX_BUFFER) {
		IOT_WARN("Payload larger than RX Buffer");
		return;
	}

	memcpy(shadowRxBuf, params->payload, params->payloadLen);
	shadowRxBuf[params->payloadLen] = '\0';    // jsmn_parse relies on a string

	if(!isJsonValidAndParse(shadowRxBuf, pJsonHandler, &tokenCount)) {
		IOT_WARN("Received JSON is not valid");
		return;
	}

	if(isAckForMyThingName(topicName)) {
		uint32_t tempVersionNumber = 0;
		if(extractVersionNumber(shadowRxBuf, pJsonHandler, tokenCount, &tempVersionNumber)) {
			if(tempVersionNumber > shadowJsonVersionNum) {
				shadowJsonVersionNum = tempVersionNumber;
			}
		}
	}

	if(extractClientToken(shadowRxBuf, temporaryClientToken)) {
		for(i = 0; i < MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME; i++) {
			if(!AckWaitList[i].isFree) {
				if(strcmp(AckWaitList[i].clientTokenID, temporaryClientToken) == 0) {
					Shadow_Ack_Status_t status;
					if(strstr(topicName, "accepted") != NULL) {
						status = SHADOW_ACK_ACCEPTED;
					} else if(strstr(topicName, "rejected") != NULL) {
						status = SHADOW_ACK_REJECTED;
					} else {
						continue;
					}
					/* status == SHADOW_ACK_ACCEPTED || status == SHADOW_ACK_REJECTED */
					if(AckWaitList[i].callback != NULL) {
						AckWaitList[i].callback(AckWaitList[i].thingName, AckWaitList[i].action, status,
												shadowRxBuf, AckWaitList[i].pCallbackContext);
					}
					unsubscribeFromAcceptedAndRejected(i);
					AckWaitList[i].isFree = true;
					return;
				}
			}
		}
	}
}
static int AckStatusCallback(MQTTCallbackParams params) {
	int32_t tokenCount;
	int32_t i;
	void *pJsonHandler;
	char temporaryClientToken[MAX_SIZE_CLIENT_TOKEN_CLIENT_SEQUENCE];

	if (params.MessageParams.PayloadLen > SHADOW_MAX_SIZE_OF_RX_BUFFER) {
		return GENERIC_ERROR;
	}

	memcpy(shadowRxBuf, params.MessageParams.pPayload, params.MessageParams.PayloadLen);
	shadowRxBuf[params.MessageParams.PayloadLen] = '\0';	// jsmn_parse relies on a string

	if (!isJsonValidAndParse(shadowRxBuf, pJsonHandler, &tokenCount)) {
		WARN("Received JSON is not valid");
		return GENERIC_ERROR;
	}

	if (isAckForMyThingName(params.pTopicName)) {
		uint32_t tempVersionNumber = 0;
		if (extractVersionNumber(shadowRxBuf, pJsonHandler, tokenCount, &tempVersionNumber)) {
			if (tempVersionNumber > shadowJsonVersionNum) {
				shadowJsonVersionNum = tempVersionNumber;
			}
		}
	}

	if (extractClientToken(shadowRxBuf, temporaryClientToken)) {
		for (i = 0; i < MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME; i++) {
			if (!AckWaitList[i].isFree) {
				if (strcmp(AckWaitList[i].clientTokenID, temporaryClientToken) == 0) {
					Shadow_Ack_Status_t status;
					if (strstr(params.pTopicName, "accepted") != NULL) {
						status = SHADOW_ACK_ACCEPTED;
					} else if (strstr(params.pTopicName, "rejected") != NULL) {
						status = SHADOW_ACK_REJECTED;
					}
					if (status == SHADOW_ACK_ACCEPTED || status == SHADOW_ACK_REJECTED) {
						if (AckWaitList[i].callback != NULL) {
							AckWaitList[i].callback(AckWaitList[i].thingName, AckWaitList[i].action, status,
									shadowRxBuf, AckWaitList[i].pCallbackContext);
						}
						unsubscribeFromAcceptedAndRejected(i);
						AckWaitList[i].isFree = true;
						return NONE_ERROR;
					}
				}
			}
		}
	}

	return GENERIC_ERROR;
}
void HandleExpiredResponseCallbacks(void) {
	uint8_t i;
	for(i = 0; i < MAX_ACKS_TO_COMEIN_AT_ANY_GIVEN_TIME; i++) {
		if(!AckWaitList[i].isFree) {
			if(has_timer_expired(&(AckWaitList[i].timer))) {
				if(AckWaitList[i].callback != NULL) {
					AckWaitList[i].callback(AckWaitList[i].thingName, AckWaitList[i].action, SHADOW_ACK_TIMEOUT,
											shadowRxBuf, AckWaitList[i].pCallbackContext);
				}
				AckWaitList[i].isFree = true;
				unsubscribeFromAcceptedAndRejected(i);
			}
		}
	}
}