void IoTHubTransportMqtt_Destroy(TRANSPORT_HANDLE handle) { /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_012: [IoTHubTransportMqtt_Destroy shall do nothing if parameter handle is NULL.] */ PMQTTTRANSPORT_HANDLE_DATA transportState = (PMQTTTRANSPORT_HANDLE_DATA)handle; if (transportState != NULL) { transportState->destroyCalled = true; DisconnectFromClient(transportState); //Empty the Waiting for Ack Messages. while (!DList_IsListEmpty(&transportState->waitingForAck)) { PDLIST_ENTRY currentEntry = DList_RemoveHeadList(&transportState->waitingForAck); MQTT_MESSAGE_DETAILS_LIST* mqttMsgEntry = containingRecord(currentEntry, MQTT_MESSAGE_DETAILS_LIST, entry); sendMsgComplete(mqttMsgEntry->iotHubMessageEntry, transportState, IOTHUB_BATCHSTATE_FAILED); free(mqttMsgEntry); } /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_014: [IoTHubTransportMqtt_Destroy shall free all the resources currently in use.] */ mqtt_client_deinit(transportState->mqttClient); STRING_delete(transportState->mqttEventTopic); STRING_delete(transportState->mqttMessageTopic); STRING_delete(transportState->device_id); STRING_delete(transportState->device_key); STRING_delete(transportState->sasTokenSr); STRING_delete(transportState->hostAddress); STRING_delete(transportState->configPassedThroughUsername); tickcounter_destroy(g_msgTickCounter); free(transportState); } }
extern void IoTHubTransportMqtt_DoWork(TRANSPORT_HANDLE handle, IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle) { /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_026: [IoTHubTransportMqtt_DoWork shall do nothing if parameter handle and/or iotHubClientHandle is NULL.] */ PMQTTTRANSPORT_HANDLE_DATA transportState = (PMQTTTRANSPORT_HANDLE_DATA)handle; if (transportState != NULL && iotHubClientHandle != NULL) { transportState->llClientHandle = iotHubClientHandle; if (InitializeConnection(transportState, true) != 0) { // Don't want to flood the logs with failures here } else { if (transportState->currPacketState == CONNACK_TYPE) { (void)SubscribeToMqttProtocol(transportState); } else if (transportState->currPacketState == SUBACK_TYPE) { // Publish can be called now transportState->currPacketState = PUBLISH_TYPE; } else if (transportState->currPacketState == PUBLISH_TYPE) { PDLIST_ENTRY currentListEntry = transportState->waitingForAck.Flink; while (currentListEntry != &transportState->waitingForAck) { MQTT_MESSAGE_DETAILS_LIST* mqttMsgEntry = containingRecord(currentListEntry, MQTT_MESSAGE_DETAILS_LIST, entry); DLIST_ENTRY nextListEntry; nextListEntry.Flink = currentListEntry->Flink; uint64_t current_ms; (void)tickcounter_get_current_ms(g_msgTickCounter, ¤t_ms); /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_033: [IoTHubTransportMqtt_DoWork shall iterate through the Waiting Acknowledge messages looking for any message that has been waiting longer than 2 min.]*/ if (((current_ms - mqttMsgEntry->msgPublishTime) / 1000) > RESEND_TIMEOUT_VALUE_MIN) { /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_034: [If IoTHubTransportMqtt_DoWork has resent the message two times then it shall fail the message] */ if (mqttMsgEntry->retryCount >= MAX_SEND_RECOUNT_LIMIT) { (void)DList_RemoveEntryList(currentListEntry); sendMsgComplete(mqttMsgEntry->iotHubMessageEntry, transportState, IOTHUB_BATCHSTATE_FAILED); free(mqttMsgEntry); } else { size_t messageLength; const unsigned char* messagePayload = RetrieveMessagePayload(mqttMsgEntry->iotHubMessageEntry->messageHandle, &messageLength); if (messageLength == 0 || messagePayload == NULL) { LogError("Failure from creating Message IoTHubMessage_GetData\r\n"); } else { if (publishMqttMessage(transportState, mqttMsgEntry, messagePayload, messageLength) != 0) { (void)DList_RemoveEntryList(currentListEntry); sendMsgComplete(mqttMsgEntry->iotHubMessageEntry, transportState, IOTHUB_BATCHSTATE_FAILED); free(mqttMsgEntry); } } } } currentListEntry = nextListEntry.Flink; } currentListEntry = transportState->waitingToSend->Flink; /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_027: [IoTHubTransportMqtt_DoWork shall inspect the “waitingToSend” DLIST passed in config structure.] */ while (currentListEntry != transportState->waitingToSend) { IOTHUB_MESSAGE_LIST* iothubMsgList = containingRecord(currentListEntry, IOTHUB_MESSAGE_LIST, entry); DLIST_ENTRY savedFromCurrentListEntry; savedFromCurrentListEntry.Flink = currentListEntry->Flink; /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_027: [IoTHubTransportMqtt_DoWork shall inspect the “waitingToSend” DLIST passed in config structure.] */ size_t messageLength; const unsigned char* messagePayload = RetrieveMessagePayload(iothubMsgList->messageHandle, &messageLength); if (messageLength == 0 || messagePayload == NULL) { LogError("Failure result from IoTHubMessage_GetData\r\n"); } else { /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_029: [IoTHubTransportMqtt_DoWork shall create a MQTT_MESSAGE_HANDLE and pass this to a call to mqtt_client_publish.] */ MQTT_MESSAGE_DETAILS_LIST* mqttMsgEntry = (MQTT_MESSAGE_DETAILS_LIST*)malloc(sizeof(MQTT_MESSAGE_DETAILS_LIST)); if (mqttMsgEntry == NULL) { LogError("Allocation Error: Failure allocating MQTT Message Detail List.\r\n"); } else { mqttMsgEntry->retryCount = 0; mqttMsgEntry->msgPacketId = transportState->packetId; mqttMsgEntry->iotHubMessageEntry = iothubMsgList; if (publishMqttMessage(transportState, mqttMsgEntry, messagePayload, messageLength) != 0) { (void)(DList_RemoveEntryList(currentListEntry)); sendMsgComplete(iothubMsgList, transportState, IOTHUB_BATCHSTATE_FAILED); free(mqttMsgEntry); } else { (void)(DList_RemoveEntryList(currentListEntry)); DList_InsertTailList(&(transportState->waitingForAck), &(mqttMsgEntry->entry)); } } } currentListEntry = savedFromCurrentListEntry.Flink; } } /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_030: [IoTHubTransportMqtt_DoWork shall call mqtt_client_dowork everytime it is called if it is connected.] */ mqtt_client_dowork(transportState->mqttClient); } } }
static void MqttOpCompleteCallback(MQTT_CLIENT_HANDLE handle, MQTT_CLIENT_EVENT_RESULT actionResult, const void* msgInfo, void* callbackCtx) { (void)handle; if (callbackCtx != NULL) { PMQTTTRANSPORT_HANDLE_DATA transportData = (PMQTTTRANSPORT_HANDLE_DATA)callbackCtx; switch (actionResult) { case MQTT_CLIENT_ON_PUBLISH_ACK: case MQTT_CLIENT_ON_PUBLISH_COMP: { const PUBLISH_ACK* puback = (const PUBLISH_ACK*)msgInfo; if (puback != NULL) { PDLIST_ENTRY currentListEntry = transportData->waitingForAck.Flink; while (currentListEntry != &transportData->waitingForAck) { MQTT_MESSAGE_DETAILS_LIST* mqttMsgEntry = containingRecord(currentListEntry, MQTT_MESSAGE_DETAILS_LIST, entry); DLIST_ENTRY saveListEntry; saveListEntry.Flink = currentListEntry->Flink; if (puback->packetId == mqttMsgEntry->msgPacketId) { (void)DList_RemoveEntryList(currentListEntry); //First remove the item from Waiting for Ack List. sendMsgComplete(mqttMsgEntry->iotHubMessageEntry, transportData, IOTHUB_BATCHSTATE_SUCCESS); free(mqttMsgEntry); } currentListEntry = saveListEntry.Flink; } } break; } case MQTT_CLIENT_ON_CONNACK: { const CONNECT_ACK* connack = (const CONNECT_ACK*)msgInfo; if (connack != NULL) { if (connack->returnCode == CONNECTION_ACCEPTED) { // The connect packet has been acked transportData->currPacketState = CONNACK_TYPE; } else { LogError("Connection not accepted, return code: %d.\r\n", connack->returnCode); (void)mqtt_client_disconnect(transportData->mqttClient); transportData->connected = false; transportData->currPacketState = PACKET_TYPE_ERROR; } } else { LogError("MQTT_CLIENT_ON_CONNACK CONNACK parameter is NULL.\r\n"); } break; } case MQTT_CLIENT_ON_SUBSCRIBE_ACK: { const SUBSCRIBE_ACK* suback = (const SUBSCRIBE_ACK*)msgInfo; if (suback != NULL) { if (suback->qosCount == 1) { // The connect packet has been acked transportData->currPacketState = SUBACK_TYPE; } else { LogError("QOS count was not expected: %d.\r\n", (int)suback->qosCount); } } break; } case MQTT_CLIENT_ON_PUBLISH_RECV: case MQTT_CLIENT_ON_PUBLISH_REL: { // Currently not used break; } case MQTT_CLIENT_ON_DISCONNECT: { // Close the client so we can reconnect again transportData->connected = false; transportData->currPacketState = DISCONNECT_TYPE; break; } case MQTT_CLIENT_ON_ERROR: { xio_close(transportData->xioTransport, NULL, NULL); transportData->connected = false; transportData->currPacketState = PACKET_TYPE_ERROR; } } } }