IOTHUB_CLIENT_RESULT IoTHubTransportMqtt_GetSendStatus(TRANSPORT_HANDLE handle, IOTHUB_CLIENT_STATUS *iotHubClientStatus) { IOTHUB_CLIENT_RESULT result; if (handle == NULL || iotHubClientStatus == NULL) { /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_023: [IoTHubTransportMqtt_GetSendStatus shall return IOTHUB_CLIENT_INVALID_ARG if called with NULL parameter.] */ LogError("invalid arument. \r\n"); result = IOTHUB_CLIENT_INVALID_ARG; } else { MQTTTRANSPORT_HANDLE_DATA* handleData = (MQTTTRANSPORT_HANDLE_DATA*)handle; if (!DList_IsListEmpty(handleData->waitingToSend) || !DList_IsListEmpty(&(handleData->waitingForAck))) { /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_025: [IoTHubTransportMqtt_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_BUSY if there are currently event items to be sent or being sent.] */ *iotHubClientStatus = IOTHUB_CLIENT_SEND_STATUS_BUSY; } else { /* Codes_SRS_IOTHUB_MQTT_TRANSPORT_07_024: [IoTHubTransportMqtt_GetSendStatus shall return IOTHUB_CLIENT_OK and status IOTHUB_CLIENT_SEND_STATUS_IDLE if there are currently no event items to be sent or being sent.] */ *iotHubClientStatus = IOTHUB_CLIENT_SEND_STATUS_IDLE; } result = IOTHUB_CLIENT_OK; } return result; }
MESSAGE_HANDLE MESSAGE_QUEUE_front(MESSAGE_QUEUE_HANDLE handle) { MESSAGE_HANDLE result; if (handle == NULL) { /*Codes_SRS_MESSAGE_QUEUE_17_019: [ MESSAGE_QUEUE_front shall return NULL if handle is NULL. ]*/ LogError("invalid argument handle (NULL)."); result = NULL; } else { /*Codes_SRS_MESSAGE_QUEUE_17_020: [ MESSAGE_QUEUE_front shall return NULL if the message queue is empty. ]*/ if (DList_IsListEmpty((PDLIST_ENTRY)&(handle->queue_head))) { result = NULL; } else { /*Codes_SRS_MESSAGE_QUEUE_17_021: [ On a non-empty queue, MESSAGE_QUEUE_front shall return the first remaining element that was pushed onto the message queue. ]*/ MESSAGE_QUEUE_STORAGE* entry = (MESSAGE_QUEUE_STORAGE*)DList_RemoveHeadList((PDLIST_ENTRY)&(handle->queue_head)); result = entry->message; /*Codes_SRS_MESSAGE_QUEUE_17_022: [ The content of the message queue shall not be changed after calling MESSAGE_QUEUE_front. ]*/ DList_InsertHeadList((PDLIST_ENTRY)&(handle->queue_head), (PDLIST_ENTRY)entry); } } return result; }
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); } }
/* access */ bool MESSAGE_QUEUE_is_empty(MESSAGE_QUEUE_HANDLE handle) { bool result; if (handle == NULL) { /*Codes_SRS_MESSAGE_QUEUE_17_016: [ MESSAGE_QUEUE_is_empty shall return true if handle is NULL. ]*/ LogError("invalid argument handle (NULL)."); result = true; } else { /*Codes_SRS_MESSAGE_QUEUE_17_017: [ MESSAGE_QUEUE_is_empty shall return true if there are no messages on the queue. ]*/ /*Codes_SRS_MESSAGE_QUEUE_17_018: [ MESSAGE_QUEUE_is_empty shall return false if one or more messages have been pushed on the queue. ]*/ result = (DList_IsListEmpty((PDLIST_ENTRY)&(handle->queue_head))); } return result; }
static MESSAGE_HANDLE message_pop(MESSAGE_QUEUE_HANDLE_DATA* handle) { MESSAGE_HANDLE result; if (DList_IsListEmpty((PDLIST_ENTRY)&(handle->queue_head))) { /*Codes_SRS_MESSAGE_QUEUE_17_013: [ MESSAGE_QUEUE_pop shall return NULL on an empty message queue. ]*/ result = NULL; } else { /*Codes_SRS_MESSAGE_QUEUE_17_014: [ MESSAGE_QUEUE_pop shall remove messages from the queue in a first-in-first-out order. ]*/ /*Codes_SRS_MESSAGE_QUEUE_17_015: [ A successful call to MESSAGE_QUEUE_pop on a queue with one message will cause the message queue to be empty. ]*/ MESSAGE_QUEUE_STORAGE* entry = (MESSAGE_QUEUE_STORAGE*)DList_RemoveHeadList( (PDLIST_ENTRY)&(handle->queue_head)); result = ((MESSAGE_QUEUE_STORAGE*)entry)->message; /*Codes_SRS_MESSAGE_QUEUE_17_006: [ MESSAGE_QUEUE_destroy shall free all allocated resources. ]*/ free(entry); } return result; }
static bool checkAndTryToConnect(PMQTTTAPI_HANDLE_DATA mqttApiState) { bool result; if (mqttApiState != NULL) { if (!mqttApiState->connected) { /* Codes_SRS_MQTTAPI_04_062: [MQTTAPI_create shall generate SAS Token with an expiring time of 1 hour.] */ size_t secondsSinceEpoch = (size_t)(difftime(get_time(NULL), EPOCH_TIME_T_VALUE) + 0); size_t possibleNewExpiry = secondsSinceEpoch + mqttApiState->sasTokenLifetime; STRING_HANDLE zeroLengthString; if ((zeroLengthString = STRING_new()) == NULL) { LogError("Could not generate zeroLenghtString for skn. \r\n"); result = false; } else { STRING_HANDLE newSASToken = SASToken_Create(mqttApiState->device_key, mqttApiState->sasTokenSr, zeroLengthString, possibleNewExpiry); if (newSASToken == NULL) { LogError("Could not generate a SAS Token\r\n"); result = false; } else { /* Codes_SRS_MQTTAPI_04_024: [MQTTAPI_Create shall call underlying library connection functions to establish connection with the server.] */ if (!connectToMQTTServer(mqttApiState->client, STRING_c_str(mqttApiState->device_id), STRING_c_str(newSASToken))) { /* Tests_SRS_MQTTAPI_04_025: [If connection fails MQTTAPI_Create shall return NULL. */ result = false; } else { mqttApiState->connected = true; mqttApiState->lastExpiryUsed = possibleNewExpiry; result = true; } STRING_delete(newSASToken); } STRING_delete(zeroLengthString); } } else { //Here is the point that we need to check if we need to disconnect, generate a new SAS Token and Connect Again. size_t secondsSinceEpoch; int differenceWithLastExpiry; secondsSinceEpoch = (size_t)(difftime(get_time(NULL), EPOCH_TIME_T_VALUE) + 0); differenceWithLastExpiry = mqttApiState->lastExpiryUsed - secondsSinceEpoch; /* Codes_SRS_MQTTAPI_04_063: [DoWork shall check the SAS Token Expiration time for the current connection. If the token is near to expire and there is no pending item, it shall disconnect, generate a new SAS Token with 1 hour expiration and connect again.] */ if ((differenceWithLastExpiry <= 0) || (((size_t)differenceWithLastExpiry) < mqttApiState->sasRefreshLine && DList_IsListEmpty(&(mqttApiState->messagesSent)) ) ) // Within refresh minutes (or past if negative) of the expiration { /* First Disconnect */ /* Codes_SRS_MQTTAPI_04_064: [If the token is expired we shall disconnect, signal that all pending message are failed due to Token Expired.] */ if (MQTTClient_disconnect(mqttApiState->client, 0) != MQTTCLIENT_SUCCESS) { LogError("Token is Expired or about to be expired and Disconnect Failed. \r\n"); } else { size_t possibleNewExpiry = secondsSinceEpoch + mqttApiState->sasTokenLifetime; STRING_HANDLE zeroLengthString; if ((zeroLengthString = STRING_new()) == NULL) { LogError("Could not generate zeroLenghtString for skn. \r\n"); result = false; } else { STRING_HANDLE newSASToken = SASToken_Create(mqttApiState->device_key, mqttApiState->sasTokenSr, zeroLengthString, possibleNewExpiry); mqttApiState->connected = false; if (newSASToken == NULL) { LogError("Could not generate a SAS Token\r\n"); result = false; } else { /* Codes_SRS_MQTTAPI_04_024: [MQTTAPI_Create shall call underlying library connection functions to establish connection with the server.] */ if (!connectToMQTTServer(mqttApiState->client, STRING_c_str(mqttApiState->device_id), STRING_c_str(newSASToken))) { /* Tests_SRS_MQTTAPI_04_025: [If connection fails MQTTAPI_Create shall return NULL. */ result = false; } else { mqttApiState->connected = true; mqttApiState->lastExpiryUsed = possibleNewExpiry; if (mqttApiState->subscribed) { int rc; LogInfo("Trying to Subscribe after reconnect.\r\n"); if ((rc = MQTTClient_subscribe(mqttApiState->client, STRING_c_str(mqttApiState->subscribedTopicHandleData->topicName), SUBSCRIBEQOS)) != MQTTCLIENT_SUCCESS) { LogError("Could not subscribe again. Won't be able to receive messages. Error Code: %d.\r\n", rc); } else { LogInfo("Subscribed succesfully after reconnect..\r\n"); } } result = true; } STRING_delete(newSASToken); } STRING_delete(zeroLengthString); } } } result = true; } } else { LogError("Invalid Arg. Handle is NULL. \r\n"); result = false; } return result; }