static void setup_dev_auth_emulator_generate_credentials_mocks(const char* token_scope)
 {
     STRICT_EXPECTED_CALL(STRING_new());
     STRICT_EXPECTED_CALL(get_time(IGNORED_PTR_ARG));
     STRICT_EXPECTED_CALL(STRING_construct(token_scope));
     STRICT_EXPECTED_CALL(STRING_construct(IGNORED_PTR_ARG))
         .IgnoreArgument_psz();
     STRICT_EXPECTED_CALL(SASToken_Create(IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_PTR_ARG, IGNORED_NUM_ARG))
         .IgnoreArgument_scope()
         .IgnoreArgument_keyName()
         .IgnoreArgument_expiry()
         .IgnoreArgument_key();
     STRICT_EXPECTED_CALL(STRING_c_str(IGNORED_PTR_ARG))
         .IgnoreArgument_handle();
     STRICT_EXPECTED_CALL(mallocAndStrcpy_s(IGNORED_PTR_ARG, IGNORED_PTR_ARG))
         .IgnoreArgument_destination()
         .IgnoreArgument_source();
     STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG))
         .IgnoreArgument_handle();
     STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG))
         .IgnoreArgument_handle();
     STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG))
         .IgnoreArgument_handle();
     STRICT_EXPECTED_CALL(STRING_delete(IGNORED_PTR_ARG))
         .IgnoreArgument_handle();
 }
static int InitializeConnection(PMQTTTRANSPORT_HANDLE_DATA transportState, bool initialConnection)
{
    int result = 0;
    if (!transportState->connected && !transportState->destroyCalled)
    {
        // Construct SAS token
        size_t secSinceEpoch = (size_t)(difftime(get_time(NULL), EPOCH_TIME_T_VALUE) + 0);
        size_t expiryTime = secSinceEpoch + SAS_TOKEN_DEFAULT_LIFETIME;

        // Not checking the success of this variable, if fail it will fail in the SASToken creation and return false;
        STRING_HANDLE emptyKeyName = STRING_new();
        STRING_HANDLE sasToken = SASToken_Create(transportState->device_key, transportState->sasTokenSr, emptyKeyName, expiryTime);
        if (sasToken == NULL)
        {
            result = __LINE__;
        }
        else
        {
            MQTT_CLIENT_OPTIONS options = { 0 };
            options.clientId = (char*)STRING_c_str(transportState->device_id);
            options.willMessage = NULL;
            options.username = (char*)STRING_c_str(transportState->configPassedThroughUsername);
            options.password = (char*)STRING_c_str(sasToken);
            options.keepAliveInterval = DEFAULT_MQTT_KEEPALIVE;
            options.useCleanSession = false;
            options.qualityOfServiceValue = DELIVER_AT_LEAST_ONCE;

            // construct address
            const char* hostAddress = STRING_c_str(transportState->hostAddress);
            const char* hostName = strstr(hostAddress, "//");
            if (hostName == NULL)
            {
                hostName = hostAddress;
            }
            else
            {
                // Increment beyond the double backslash
                hostName += 2;
            }

            transportState->xioTransport = getIoTransportProvider(hostName, transportState->portNum);
            if (mqtt_client_connect(transportState->mqttClient, transportState->xioTransport, &options) != 0)
            {
                LogError("failure connecting to address %s:%d.\r\n", STRING_c_str(transportState->hostAddress), transportState->portNum);
                result = __LINE__;
            }
            else
            {
                transportState->connected = true;
                result = 0;
            }
            STRING_delete(emptyKeyName);
            STRING_delete(sasToken);
        }
    }
    return result;
}
Exemple #3
0
const char* IoTHubAccount_GetSharedAccessSignature(IOTHUB_ACCOUNT_INFO_HANDLE acctHandle)
{
    const char* result = NULL;
    IOTHUB_ACCOUNT_INFO* acctInfo = (IOTHUB_ACCOUNT_INFO*)acctHandle;
    if (acctInfo != NULL)
    {
        if (acctInfo->sharedAccessToken != NULL)
        {
            // Reuse the sharedAccessToken if it's been created already
            result = acctInfo->sharedAccessToken;
        }
        else
        {
        time_t currentTime = time(NULL);
        size_t expiry_time = (size_t)(currentTime + 3600);

        STRING_HANDLE accessKey = STRING_construct(acctInfo->sharedAccessKey);
        STRING_HANDLE iotName = STRING_construct(acctInfo->hostname);
        STRING_HANDLE keyName = STRING_construct(acctInfo->keyName);
        if (accessKey != NULL && iotName != NULL && keyName != NULL)
        {
            STRING_HANDLE sasHandle = SASToken_Create(accessKey, iotName, keyName, expiry_time);
            if (sasHandle == NULL)
            {

                result = NULL;
            }
            else
            {
                if (mallocAndStrcpy_s(&acctInfo->sharedAccessToken, STRING_c_str(sasHandle)) != 0)
                {
                    result = NULL;
                }
                else
                {
                    result = acctInfo->sharedAccessToken;
                }
                STRING_delete(sasHandle);
            }
        }
        STRING_delete(accessKey);
        STRING_delete(iotName);
        STRING_delete(keyName);
    }
    }
    else
    {
        result = NULL;
    }
    return result; 
}
HTTPAPIEX_RESULT HTTPAPIEX_SAS_ExecuteRequest(HTTPAPIEX_SAS_HANDLE sasHandle, HTTPAPIEX_HANDLE handle, HTTPAPI_REQUEST_TYPE requestType, const char* relativePath, HTTP_HEADERS_HANDLE requestHttpHeadersHandle, BUFFER_HANDLE requestContent, unsigned int* statusCode, HTTP_HEADERS_HANDLE responseHeadersHandle, BUFFER_HANDLE responseContent)
{
    /*Codes_SRS_HTTPAPIEXSAS_06_007: [If the parameter sasHandle is NULL then HTTPAPIEX_SAS_ExecuteRequest shall simply invoke HTTPAPIEX_ExecuteRequest with the remaining parameters (following sasHandle) as its arguments and shall return immediately with the result of that call as the result of HTTPAPIEX_SAS_ExecuteRequest.]*/
    if (sasHandle != NULL)
    {
        /*Codes_SRS_HTTPAPIEXSAS_06_008: [if the parameter requestHttpHeadersHandle is NULL then fallthrough.]*/
        if (requestHttpHeadersHandle != NULL)
        {
            /*Codes_SRS_HTTPAPIEXSAS_06_009: [HTTPHeaders_FindHeaderValue shall be invoked with the requestHttpHeadersHandle as its first argument and the string "Authorization" as its second argument.]*/
            /*Codes_SRS_HTTPAPIEXSAS_06_010: [If the return result of the invocation of HTTPHeaders_FindHeaderValue is NULL then fallthrough.]*/
            if (HTTPHeaders_FindHeaderValue(requestHttpHeadersHandle, "Authorization") != NULL)
            {
                HTTPAPIEX_SAS_STATE* state = (HTTPAPIEX_SAS_STATE*)sasHandle;
                /*Codes_SRS_HTTPAPIEXSAS_06_018: [A value of type time_t that shall be known as currentTime is obtained from calling get_time.]*/
                time_t currentTime = get_time(NULL);
                /*Codes_SRS_HTTPAPIEXSAS_06_019: [If the value of currentTime is (time_t)-1 is then fallthrough.]*/
                if (currentTime == (time_t)-1)
                {
                    LogError("Time does not appear to be working.\r\n");
                }
                else
                {
                    /*Codes_SRS_HTTPAPIEXSAS_06_011: [SASToken_Create shall be invoked.]*/
                    /*Codes_SRS_HTTPAPIEXSAS_06_012: [If the return result of SASToken_Create is NULL then fallthrough.]*/
                    size_t expiry = (size_t)(difftime(currentTime, 0) + 3600);
                    STRING_HANDLE newSASToken = SASToken_Create(state->key, state->uriResource, state->keyName, expiry);
                    if (newSASToken != NULL)
                    {
                        /*Codes_SRS_HTTPAPIEXSAS_06_013: [HTTPHeaders_ReplaceHeaderNameValuePair shall be invoked with "Authorization" as its second argument and STRING_c_str (newSASToken) as its third argument.]*/
                        if (HTTPHeaders_ReplaceHeaderNameValuePair(requestHttpHeadersHandle, "Authorization", STRING_c_str(newSASToken)) != HTTP_HEADERS_OK)
                        {
                            /*Codes_SRS_HTTPAPIEXSAS_06_014: [If the result of the invocation of HTTPHeaders_ReplaceHeaderNameValuePair is NOT HTTP_HEADERS_OK then fallthrough.]*/
                            LogError("Unable to replace the old SAS Token.\r\n");
                        }
                        /*Codes_SRS_HTTPAPIEXSAS_06_015: [STRING_delete(newSASToken) will be invoked.]*/
                        STRING_delete(newSASToken);
                    }
                    else
                    {
                        LogError("Unable to create a new SAS token.\r\n");
                    }
                }
            }
        }
    }
    /*Codes_SRS_HTTPAPIEXSAS_06_016: [HTTPAPIEX_ExecuteRequest with the remaining parameters (following sasHandle) as its arguments will be invoked and the result of that call is the result of HTTPAPIEX_SAS_ExecuteRequest.]*/
    return HTTPAPIEX_ExecuteRequest(handle,requestType,relativePath,requestHttpHeadersHandle,requestContent,statusCode,responseHeadersHandle,responseContent);
}
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;
}
Exemple #6
0
int main(int argc, char** argv)
{
    int result;

    (void)argc;
    (void)argv;

    if (platform_init() != 0)
    {
        result = -1;
    }
    else
    {
        XIO_HANDLE sasl_io;
        CONNECTION_HANDLE connection;
        SESSION_HANDLE session;
        LINK_HANDLE link;
        MESSAGE_SENDER_HANDLE message_sender;
        MESSAGE_HANDLE message;

        size_t last_memory_used = 0;

        /* create SASL PLAIN handler */
        SASL_MECHANISM_HANDLE sasl_mechanism_handle = saslmechanism_create(saslmssbcbs_get_interface(), NULL);
        XIO_HANDLE tls_io;
        STRING_HANDLE sas_key_name;
        STRING_HANDLE sas_key_value;
        STRING_HANDLE resource_uri;
        STRING_HANDLE encoded_resource_uri;
        STRING_HANDLE sas_token;
        BUFFER_HANDLE buffer;
        TLSIO_CONFIG tls_io_config = { EH_HOST, 5671 };
        const IO_INTERFACE_DESCRIPTION* tlsio_interface;
        SASLCLIENTIO_CONFIG sasl_io_config;
        time_t currentTime;
        size_t expiry_time;
        CBS_HANDLE cbs;
        AMQP_VALUE source;
        AMQP_VALUE target;
        unsigned char hello[] = { 'H', 'e', 'l', 'l', 'o' };
        BINARY_DATA binary_data;

        gballoc_init();

        /* create the TLS IO */
        tlsio_interface = platform_get_default_tlsio();
        tls_io = xio_create(tlsio_interface, &tls_io_config);

        /* create the SASL client IO using the TLS IO */
        sasl_io_config.underlying_io = tls_io;
        sasl_io_config.sasl_mechanism = sasl_mechanism_handle;
        sasl_io = xio_create(saslclientio_get_interface_description(), &sasl_io_config);

        /* create the connection, session and link */
        connection = connection_create(sasl_io, EH_HOST, "some", NULL, NULL);
        session = session_create(connection, NULL, NULL);
        session_set_incoming_window(session, 2147483647);
        session_set_outgoing_window(session, 65536);

        /* Construct a SAS token */
        sas_key_name = STRING_construct(EH_KEY_NAME);

        /* unfortunately SASToken wants an encoded key - this should be fixed at a later time */
        buffer = BUFFER_create((unsigned char*)EH_KEY, strlen(EH_KEY));
        sas_key_value = Base64_Encoder(buffer);
        BUFFER_delete(buffer);
        resource_uri = STRING_construct("sb://" EH_HOST "/" EH_NAME "/publishers/" EH_PUBLISHER);
        encoded_resource_uri = URL_EncodeString(STRING_c_str(resource_uri));

        /* Make a token that expires in one hour */
        currentTime = time(NULL);
        expiry_time = (size_t)(difftime(currentTime, 0) + 3600);

        sas_token = SASToken_Create(sas_key_value, encoded_resource_uri, sas_key_name, expiry_time);

        cbs = cbs_create(session);
        if (cbs_open_async(cbs, on_cbs_open_complete, cbs, on_cbs_error, cbs) == 0)
        {
            (void)cbs_put_token_async(cbs, "servicebus.windows.net:sastoken", "sb://" EH_HOST "/" EH_NAME "/publishers/" EH_PUBLISHER, STRING_c_str(sas_token), on_cbs_put_token_complete, cbs);

            while (!auth)
            {
                size_t current_memory_used;
                size_t maximum_memory_used;
                connection_dowork(connection);

                current_memory_used = gballoc_getCurrentMemoryUsed();
                maximum_memory_used = gballoc_getMaximumMemoryUsed();

                if (current_memory_used != last_memory_used)
                {
                    (void)printf("Current memory usage:%lu (max:%lu)\r\n", (unsigned long)current_memory_used, (unsigned long)maximum_memory_used);
                    last_memory_used = current_memory_used;
                }
            }
        }

        STRING_delete(sas_token);
        STRING_delete(sas_key_name);
        STRING_delete(sas_key_value);
        STRING_delete(resource_uri);
        STRING_delete(encoded_resource_uri);

        source = messaging_create_source("ingress");
        target = messaging_create_target("amqps://" EH_HOST "/" EH_NAME);
        link = link_create(session, "sender-link", role_sender, source, target);
        link_set_snd_settle_mode(link, sender_settle_mode_settled);
        (void)link_set_max_message_size(link, 65536);

        amqpvalue_destroy(source);
        amqpvalue_destroy(target);

        message = message_create();

        binary_data.bytes = hello;
        binary_data.length = sizeof(hello);
        message_add_body_amqp_data(message, binary_data);

        /* create a message sender */
        message_sender = messagesender_create(link, NULL, NULL);
        if (messagesender_open(message_sender) == 0)
        {
            uint32_t i;
            bool keep_running = true;
            tickcounter_ms_t start_time;
            TICK_COUNTER_HANDLE tick_counter = tickcounter_create();

            if (tickcounter_get_current_ms(tick_counter, &start_time) != 0)
            {
                (void)printf("Error getting start time\r\n");
            }
            else
            {
                for (i = 0; i < msg_count; i++)
                {
                    (void)messagesender_send(message_sender, message, on_message_send_complete, message);
                }

                message_destroy(message);

                while (keep_running)
                {
                    size_t current_memory_used;
                    size_t maximum_memory_used;
                    connection_dowork(connection);

                    current_memory_used = gballoc_getCurrentMemoryUsed();
                    maximum_memory_used = gballoc_getMaximumMemoryUsed();

                    if (current_memory_used != last_memory_used)
                    {
                        (void)printf("Current memory usage:%lu (max:%lu)\r\n", (unsigned long)current_memory_used, (unsigned long)maximum_memory_used);
                        last_memory_used = current_memory_used;
                    }

                    if (sent_messages == msg_count)
                    {
                        break;
                    }
                }

                {
                    tickcounter_ms_t end_time;
                    if (tickcounter_get_current_ms(tick_counter, &end_time) != 0)
                    {
                        (void)printf("Error getting end time\r\n");
                    }
                    else
                    {
                        (void)printf("Send %u messages in %lu ms: %.02f msgs/sec\r\n", (unsigned int)msg_count, (unsigned long)(end_time - start_time), (float)msg_count / ((float)(end_time - start_time) / 1000));
                    }
                }
            }
        }

        messagesender_destroy(message_sender);
        link_destroy(link);
        session_destroy(session);
        connection_destroy(connection);
        xio_destroy(sasl_io);
        xio_destroy(tls_io);
        saslmechanism_destroy(sasl_mechanism_handle);
        platform_deinit();

        (void)printf("Max memory usage:%lu\r\n", (unsigned long)gballoc_getCurrentMemoryUsed());
        (void)printf("Current memory usage:%lu\r\n", (unsigned long)gballoc_getMaximumMemoryUsed());

        gballoc_deinit();

        result = 0;
    }

    return result;
}