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;
}
Esempio n. 6
0
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;
}