Skip to content

Commit

Permalink
Merge pull request aws#9 from aws/test/setup-foundry-integration-test
Browse files Browse the repository at this point in the history
Add infrastructure for running CI-based integration tests, and add demo application
  • Loading branch information
aggarw13 committed Nov 14, 2019
2 parents 87ff2e8 + a21864d commit f1db49a
Show file tree
Hide file tree
Showing 10 changed files with 263 additions and 113 deletions.
86 changes: 58 additions & 28 deletions demos/src/aws_iot_demo_onboarding.c
Original file line number Diff line number Diff line change
Expand Up @@ -71,12 +71,34 @@
*
* An MQTT ping request will be sent periodically at this interval.
*/
#define KEEP_ALIVE_SECONDS ( 60 )
#define KEEP_ALIVE_SECONDS ( 60 )

/**
* @brief The timeout for Onboarding and MQTT operations in this demo.
*/
#define TIMEOUT_MS ( 5000 )
#define TIMEOUT_MS ( 5000 )

/**
* @brief The name for the provisioning template that will be used for provisioning the demo app.
*/
#define PROVISIONING_TEMPLATE_NAME "CI_TEST_TEMPLATE"

/**
* @brief The parameter that will be used for provisioning the demo application.
*/
#define PROVISIONING_PARAMETER_NAME "DeviceLocation"
#define PROVISIONING_PARAMETER_VALUE "Seattle"
#define NUM_OF_PROVISIONING_PARAMS 1u

/**
* @brief Type for the callback context for the #AwsIotOnboarding_GetDeviceCredentials API.
* It will be used for storing the received Certificate ID string that will be provided in the callback.
*/
typedef struct _demoProvisionDeviceCallbackContext
{
char * pCertificateIdBuffer;
size_t certificateIdLength;
} _demoProvisionDeviceCallbackContext_t;

/*-----------------------------------------------------------*/

Expand All @@ -94,7 +116,7 @@ int RunOnboardingDemo( bool awsIotMqttMode,
*/
static void _printRejectedResponse( const AwsIotOnboardingRejectedResponse_t * pResponseInfo )
{
IotLogError( "StatusCode={%d}\n ErrorCode={%.*s}\n ErrorMessage={%.*s}\n",
IotLogError( "ErrorCode={%.*s}\n ErrorMessage={%.*s}\n",
pResponseInfo->errorCodeLength, pResponseInfo->pErrorCode,
pResponseInfo->errorMessageLength, pResponseInfo->pErrorMessage );
}
Expand All @@ -112,21 +134,26 @@ static void _printRejectedResponse( const AwsIotOnboardingRejectedResponse_t * p
static void _demoDeviceCredentialsCallback( void * contextParam,
const AwsIotOnboardingGetDeviceCredentialsResponse_t * pResponseInfo )
{
char ** certificateId = ( char ** ) contextParam;
_demoProvisionDeviceCallbackContext_t * certificateIdContext = ( _demoProvisionDeviceCallbackContext_t * ) contextParam;

IotLogInfo( "Received StatusCode={%d}", pResponseInfo->statusCode );

if( pResponseInfo->statusCode == AWS_IOT_ONBOARDING_SERVER_STATUS_ACCEPTED )
{
/* Allocate buffer space for storing the certificate ID obtained from the server. */
*certificateId = malloc( pResponseInfo->u.acceptedResponse.certificateIdLength + 1 );
certificateIdContext->pCertificateIdBuffer = Iot_DefaultMalloc( pResponseInfo->u.acceptedResponse.certificateIdLength + 1 );

/* Copy the certificate ID into the buffer. */
if( *certificateId != NULL )
if( certificateIdContext->pCertificateIdBuffer != NULL )
{
memcpy( *certificateId, pResponseInfo->u.acceptedResponse.pCertificateId, pResponseInfo->u.acceptedResponse.certificateIdLength );
/* Copy the size of the Certificate ID string. */
certificateIdContext->certificateIdLength = pResponseInfo->u.acceptedResponse.certificateIdLength;

memcpy( certificateIdContext->pCertificateIdBuffer,
pResponseInfo->u.acceptedResponse.pCertificateId,
pResponseInfo->u.acceptedResponse.certificateIdLength );
/* Add a NULL terminator to the buffer (to treat the buffer as a string!) */
*certificateId[ pResponseInfo->u.acceptedResponse.certificateIdLength ] = '\0';
*( certificateIdContext->pCertificateIdBuffer + pResponseInfo->u.acceptedResponse.certificateIdLength ) = '\0';
}

/* Print the certificate Pem and private key data received. This is ONLY for the demo purpose, STORE THE
Expand Down Expand Up @@ -178,7 +205,7 @@ static void _demoOnboardDeviceCallback( void * contextParam,
for( size_t configIndex = 0;
configIndex < pResponseInfo->u.acceptedResponse.numOfConfigurationEntries; configIndex++ )
{
IotLogInfo( "Device Configuration no. %d:ConfigName = %.*s, ConfigData = %.*s ",
IotLogInfo( "Device Configuration no. %d\nConfigName = %.*s, ConfigData = %.*s ",
configIndex,
pConfigurationList[ configIndex ].keyLength,
pConfigurationList[ configIndex ].pKey,
Expand Down Expand Up @@ -352,7 +379,10 @@ int RunOnboardingDemo( bool awsIotMqttMode,

/* Represents memory that will be allocated to store the Certificate ID that will be provided by the credential
* requesting API through the callback. */
char * pCertificateIdBuffer = NULL;
_demoProvisionDeviceCallbackContext_t newCertificateIdDataContext;

newCertificateIdDataContext.pCertificateIdBuffer = NULL;
newCertificateIdDataContext.certificateIdLength = 0;

/* Request data for onboarding the demo application. */
AwsIotOnboardingOnboardDeviceRequestInfo_t requestInfo;
Expand All @@ -364,16 +394,19 @@ int RunOnboardingDemo( bool awsIotMqttMode,
* to AWS IoT, so this value is hardcoded to true whenever needed. */
( void ) awsIotMqttMode;

size_t clientIdentifierLength = 0;

/* This will be used for tracking the return code from the Provisioning APIs. */
AwsIotOnboardingError_t requestStatus = AWS_IOT_ONBOARDING_SUCCESS;

AwsIotOnboardingRequestParameterEntry_t provisioningParameters;
provisioningParameters.pParameterKey = PROVISIONING_PARAMETER_NAME;
provisioningParameters.parameterKeyLength = ( size_t ) ( sizeof( PROVISIONING_PARAMETER_NAME ) - 1 );
provisioningParameters.pParameterValue = PROVISIONING_PARAMETER_VALUE;
provisioningParameters.parameterValueLength = ( size_t ) ( sizeof( PROVISIONING_PARAMETER_VALUE ) - 1 );

/* Determine the length of the client ID Name. */
if( pIdentifier != NULL )
{
clientIdentifierLength = strlen( pIdentifier );

if( clientIdentifierLength == 0 )
if( strlen( pIdentifier ) == 0 )
{
IotLogError( "The length of the MQTT client identifier must be nonzero." );

Expand Down Expand Up @@ -412,7 +445,7 @@ int RunOnboardingDemo( bool awsIotMqttMode,
connectionEstablished = true;

/* Set the certificate ID pointer as context parameter to the credentials response processing callback. */
deviceCredentialsCallback.userParam = &pCertificateIdBuffer;
deviceCredentialsCallback.userParam = &newCertificateIdDataContext;

/* Set the callback function for handling device credentials that the server will send. */
deviceCredentialsCallback.function = _demoDeviceCredentialsCallback;
Expand All @@ -430,7 +463,7 @@ int RunOnboardingDemo( bool awsIotMqttMode,
IotLogError( "Request to get new credentials failed, error %s ",
AwsIotOnboarding_strerror( requestStatus ) );
}
else if( pCertificateIdBuffer == NULL )
else if( newCertificateIdDataContext.pCertificateIdBuffer == NULL )
{
IotLogInfo( "Don 't have the Certificate ID to proceed for onboarding. So exiting...!" );
}
Expand All @@ -443,15 +476,12 @@ int RunOnboardingDemo( bool awsIotMqttMode,
if( status == EXIT_SUCCESS )
{
/* Set the parameters for requesting onboarding. */
requestInfo.pDeviceCertificateId = pCertificateIdBuffer;
requestInfo.deviceCertificateIdLength = ( sizeof( pCertificateIdBuffer ) - 1 );
requestInfo.pTemplateIdentifier = AWS_IOT_DEMO_ONBOARDING_TEMPLATE_NAME;
requestInfo.templateIdentifierLength = sizeof( AWS_IOT_DEMO_ONBOARDING_TEMPLATE_NAME ) - 1;
requestInfo.pParametersStart = NULL;
requestInfo.numOfParameters = 0;

/* Set the certificate ID pointer as context parameter to the credentials response processing callback. */
onboardDeviceResponseCallback.userParam = &pCertificateIdBuffer;
requestInfo.pDeviceCertificateId = newCertificateIdDataContext.pCertificateIdBuffer;
requestInfo.deviceCertificateIdLength = newCertificateIdDataContext.certificateIdLength;
requestInfo.pTemplateName = PROVISIONING_TEMPLATE_NAME;
requestInfo.templateNameLength = sizeof( PROVISIONING_TEMPLATE_NAME ) - 1;
requestInfo.pParametersStart = &provisioningParameters;
requestInfo.numOfParameters = NUM_OF_PROVISIONING_PARAMS;

/* Set the callback function for handling device credentials that the server will send. */
onboardDeviceResponseCallback.function = _demoOnboardDeviceCallback;
Expand Down Expand Up @@ -488,9 +518,9 @@ int RunOnboardingDemo( bool awsIotMqttMode,
}

/* Release the Certificate ID buffer, if memory was allocated for it. */
if( pCertificateIdBuffer != NULL )
if( newCertificateIdDataContext.pCertificateIdBuffer != NULL )
{
free( pCertificateIdBuffer );
Iot_DefaultFree( newCertificateIdDataContext.pCertificateIdBuffer );
}

return status;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -216,14 +216,14 @@ typedef struct AwsIotOnboardingResponseDeviceConfigurationEntry
typedef struct AwsIotOnboardingOnboardDeviceRequestInfo
{
/**
* @brief The identifier of the template on the AWS IoT account used for onboarding the device.
* @brief The name of the template on the AWS IoT account to be used for onboarding the device.
*/
const char * pTemplateIdentifier;
const char * pTemplateName;

/**
* @brief The length of the template identifier.
* @brief The length of the template name text.
*/
size_t templateIdentifierLength;
size_t templateNameLength;

/**
* @brief The certificate ID string (of the certificate issued by AWS IoT) to onboard the device with.
Expand Down
24 changes: 16 additions & 8 deletions libraries/aws/onboarding/src/aws_iot_onboarding_api.c
Original file line number Diff line number Diff line change
Expand Up @@ -612,6 +612,7 @@ AwsIotOnboardingError_t AwsIotOnboarding_OnboardDevice( IotMqttConnection_t onbo
/* Use the same buffer for storing the request and response MQTT topic strings (for space efficiency) as both kinds
* of topics share the same filter. */
char requestResponseTopicsBuffer[ ONBOARDING_ONBOARD_DEVICE_RESPONSE_MAX_TOPIC_LENGTH ] = { 0 };
size_t generatedTopicFilterSize = 0;
AwsIotOnboarding_Assert( ONBOARDING_ONBOARD_DEVICE_RESPONSE_MAX_TOPIC_LENGTH >
ONBOARDING_ONBOARD_DEVICE_REQUEST_TOPIC_LENGTH );

Expand Down Expand Up @@ -660,11 +661,12 @@ AwsIotOnboardingError_t AwsIotOnboarding_OnboardDevice( IotMqttConnection_t onbo
IOT_SET_AND_GOTO_CLEANUP( AWS_IOT_ONBOARDING_BAD_PARAMETER );
}

/* Check that the provided template ID has the length of the text representation of UUID */
if( ( pRequestData->pTemplateIdentifier == NULL ) || ( pRequestData->templateIdentifierLength ==
0 ) )
/* Check that the provided template name is valid. */
if( ( pRequestData->pTemplateName == NULL ) ||
( pRequestData->templateNameLength == 0 ) ||
( pRequestData->templateNameLength > ONBOARDING_MAX_TEMPLATE_NAME_LENGTH ) )
{
IotLogError( "Invalid template ID information passed for device onboarding request." );
IotLogError( "Invalid template name information passed for device onboarding request." );

IOT_SET_AND_GOTO_CLEANUP( AWS_IOT_ONBOARDING_BAD_PARAMETER );
}
Expand All @@ -690,17 +692,23 @@ AwsIotOnboardingError_t AwsIotOnboarding_OnboardDevice( IotMqttConnection_t onbo
}

/* Generate the response topic filter using the template ID. */
responseSubscription.topicFilterBaseLength = _AwsIotOnboarding_GenerateOnboardDeviceTopicFilter(
pRequestData->pTemplateIdentifier,
pRequestData->templateIdentifierLength,
generatedTopicFilterSize = _AwsIotOnboarding_GenerateOnboardDeviceTopicFilter(
pRequestData->pTemplateName,
pRequestData->templateNameLength,
requestResponseTopicsBuffer );

/* We should never hit the "insufficient buffer size" case for generating topic filter, but if we do, we need to
* gracefully exit. */
AwsIotOnboarding_Assert( generatedTopicFilterSize != 0 );

if( responseSubscription.topicFilterBaseLength == 0 )
{
/* TODO - Rethink about handling insufficient buffer size error (that is a bit contrived) */
IOT_SET_AND_GOTO_CLEANUP( AWS_IOT_ONBOARDING_INTERNAL_FAILURE );
}

responseSubscription.topicFilterBaseLength = generatedTopicFilterSize;

/* Subscibe to the MQTT response topics. */
mqttOpResult = AwsIot_ModifySubscriptions( IotMqtt_TimedSubscribe, &responseSubscription );

Expand Down Expand Up @@ -779,7 +787,7 @@ AwsIotOnboardingError_t AwsIotOnboarding_OnboardDevice( IotMqttConnection_t onbo
* Note: For memory and performance efficiency, we are using the same buffer as the response topics. We specify the
* length of the buffer that is applicable to the request topic. */
publishInfo.pTopicName = requestResponseTopicsBuffer;
publishInfo.topicNameLength = ONBOARDING_ONBOARD_DEVICE_REQUEST_TOPIC_LENGTH;
publishInfo.topicNameLength = generatedTopicFilterSize;

IotLogDebug( "Onboarding %s message will be published to topic %.*s",
GET_ONBOARD_DEVICE_OPERATION_LOG,
Expand Down
12 changes: 6 additions & 6 deletions libraries/aws/onboarding/src/aws_iot_onboarding_serializer.c
Original file line number Diff line number Diff line change
Expand Up @@ -275,11 +275,11 @@ AwsIotOnboardingError_t _AwsIotOnboarding_SerializeOnboardDeviceRequestPayload(

/*------------------------------------------------------------------*/

size_t _AwsIotOnboarding_GenerateOnboardDeviceTopicFilter( const char * pTemplateIdentifier,
size_t templateIdentifierLength,
size_t _AwsIotOnboarding_GenerateOnboardDeviceTopicFilter( const char * pTemplateName,
size_t templateNameLength,
char * pTopicFilterBuffer )
{
AwsIotOnboarding_Assert( pTemplateIdentifier != NULL );
AwsIotOnboarding_Assert( pTemplateName != NULL );
AwsIotOnboarding_Assert( pTopicFilterBuffer != NULL );

size_t filledBufferSize = 0;
Expand All @@ -288,9 +288,9 @@ size_t _AwsIotOnboarding_GenerateOnboardDeviceTopicFilter( const char * pTemplat
( void ) memcpy( pTopicFilterBuffer, ONBOARDING_ONBOARD_DEVICE_TOPICS_COMMON_PREFIX,
ONBOARDING_ONBOARD_DEVICE_TOPICS_COMMON_PREFIX_LENGTH );
filledBufferSize += ONBOARDING_ONBOARD_DEVICE_TOPICS_COMMON_PREFIX_LENGTH;
( void ) memcpy( pTopicFilterBuffer + filledBufferSize, pTemplateIdentifier,
templateIdentifierLength );
filledBufferSize += templateIdentifierLength;
( void ) memcpy( pTopicFilterBuffer + filledBufferSize, pTemplateName,
templateNameLength );
filledBufferSize += templateNameLength;
( void ) memcpy( pTopicFilterBuffer + filledBufferSize,
ONBOARDING_ONBOARD_DEVICE_TOPICS_COMMON_SUFFIX,
ONBOARDING_ONBOARD_DEVICE_TOPICS_COMMON_SUFFIX_LENGTH );
Expand Down
37 changes: 17 additions & 20 deletions libraries/aws/onboarding/src/private/aws_iot_onboarding_internal.h
Original file line number Diff line number Diff line change
Expand Up @@ -188,17 +188,15 @@
#ifdef Iot_DefaultMalloc
#define AwsIotOnboarding_MallocDeviceConfigurationList Iot_DefaultMalloc
#else
#error "No malloc function defined for "
"AwsIotOnboarding_MallocDeviceConfigurationList"
#error "No malloc function defined for AwsIotOnboarding_MallocDeviceConfigurationList"
#endif
#endif

#ifndef AwsIotOnboarding_FreeDeviceConfigurationList
#ifdef Iot_DefaultFree
#define AwsIotOnboarding_FreeDeviceConfigurationList Iot_DefaultFree
#else
#error "No Free function defined for "
"AwsIotOnboarding_FreeDeviceConfigurationList"
#error "No Free function defined for AwsIotOnboarding_FreeDeviceConfigurationList"
#endif
#endif

Expand All @@ -222,7 +220,7 @@
* It should be utilized in the @ref onboarding_function_getdevicecredentials API function.
*/
#define ONBOARDING_GET_DEVICE_CREDENTIALS_RESPONSE_TOPIC_FILTER \
"aws/certificates/create/"ONBOARDING_FORMAT
"$aws/certificates/create/"ONBOARDING_FORMAT

/**
* @brief Length of the MQTT response topic filtert for the GetDeviceCredentials service API.
Expand Down Expand Up @@ -272,7 +270,7 @@
* @brief The common path in the request and response MQTT topics of the OnboardDevice service API.
*/
#define ONBOARDING_ONBOARD_DEVICE_TOPICS_COMMON_PREFIX \
"aws/provisioning-templates/"
"$aws/provisioning-templates/"

/**
* @brief The length of the common path in the request and response MQTT topics of the OnboardDevice service API.
Expand All @@ -281,16 +279,15 @@
( ( uint16_t ) ( sizeof( ONBOARDING_ONBOARD_DEVICE_TOPICS_COMMON_PREFIX ) - 1 ) )

/**
* @brief The length of the Template ID text in the MQTT topics of the OnboardDevice service API.
*
* @note The Template ID follows the UUID (Universally Unique Identifier) format.
* @brief The maximum length of the Template name that can be used for provisioning the device.
* @note The template name is part of the MQTT topics of the OnboardDevice service API.
*/
#define ONBOARDING_TEMPLATE_ID_LENGTH ( 36 )
#define ONBOARDING_MAX_TEMPLATE_NAME_LENGTH ( 36 )

/**
* @brief The common suffix in the request and response MQTT topics of the OnboardDevice service API.
*/
#define ONBOARDING_ONBOARD_DEVICE_TOPICS_COMMON_SUFFIX "/register/"ONBOARDING_FORMAT
#define ONBOARDING_ONBOARD_DEVICE_TOPICS_COMMON_SUFFIX "/provision/"ONBOARDING_FORMAT

/**
* @brief The length of the common suffix in the MQTT topics of the OnboardDevice service API.
Expand All @@ -302,8 +299,8 @@
/**
* @brief The length of the complete MQTT request topic of the OnboardDevice service API.
*/
#define ONBOARDING_ONBOARD_DEVICE_REQUEST_TOPIC_LENGTH \
( ONBOARDING_ONBOARD_DEVICE_TOPICS_COMMON_PREFIX_LENGTH + ONBOARDING_TEMPLATE_ID_LENGTH + \
#define ONBOARDING_ONBOARD_DEVICE_REQUEST_TOPIC_LENGTH \
( ONBOARDING_ONBOARD_DEVICE_TOPICS_COMMON_PREFIX_LENGTH + ONBOARDING_MAX_TEMPLATE_NAME_LENGTH + \
ONBOARDING_ONBOARD_DEVICE_TOPICS_COMMON_SUFFIX_LENGTH )

/**
Expand All @@ -321,13 +318,13 @@
* @note This should be used in serializing the request payload for sending to the server, only if the calling
* application provides valid device context data.
*/
#define ONBOARDING_ONBOARD_DEVICE_REQUEST_PAYLOAD_PARAMETERS_STRING "parameters"
#define ONBOARDING_ONBOARD_DEVICE_REQUEST_PAYLOAD_PARAMETERS_STRING "deviceContext"

/**
* @brief The length of the MQTT request topic filter of the OnboardDevice service API.
*/
#define ONBOARDING_ONBOARD_DEVICE_RESPONSE_TOPIC_FILTER_LENGTH \
( ONBOARDING_ONBOARD_DEVICE_TOPICS_COMMON_PREFIX_LENGTH + ONBOARDING_TEMPLATE_ID_LENGTH + \
#define ONBOARDING_ONBOARD_DEVICE_RESPONSE_TOPIC_FILTER_LENGTH \
( ONBOARDING_ONBOARD_DEVICE_TOPICS_COMMON_PREFIX_LENGTH + ONBOARDING_MAX_TEMPLATE_NAME_LENGTH + \
ONBOARDING_ONBOARD_DEVICE_TOPICS_COMMON_SUFFIX_LENGTH )

/**
Expand Down Expand Up @@ -461,15 +458,15 @@ extern const IotSerializerDecodeInterface_t * _pAwsIotOnboardingDecoder;
/**
* @brief Utility for generating the request/response MQTT topic filter string for the OnboardingDevice service API.
*
* @param[in] pTemplateIdentifier The template ID string for inserting in the topic filter string.
* @param[in] templateIdentifierLength The length of the template ID string.
* @param[in] pTemplateName The template ID string for inserting in the topic filter string.
* @param[in] templateNameLength The length of the template ID string.
* @param[out] pTopicFilterBuffer The pre-allocated buffer for storing the generated topic filter.
* The buffer should have the required minimum size for storing the MQTT topic filter for the OnboardDevice API.
*
* @return Returns the size of the generated topic filter.
*/
size_t _AwsIotOnboarding_GenerateOnboardDeviceTopicFilter( const char * pTemplateIdentifier,
size_t templateIdentifierLength,
size_t _AwsIotOnboarding_GenerateOnboardDeviceTopicFilter( const char * pTemplateName,
size_t templateNameLength,
char * pTopicFilterBuffer );

/**
Expand Down

0 comments on commit f1db49a

Please sign in to comment.