/* * Copyright (C) 2018 Amazon.com, Inc. or its affiliates. All Rights Reserved. * * Permission is hereby granted, free of charge, to any person obtaining a copy of * this software and associated documentation files (the "Software"), to deal in * the Software without restriction, including without limitation the rights to * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of * the Software, and to permit persons to whom the Software is furnished to do so, * subject to the following conditions: * * The above copyright notice and this permission notice shall be included in all * copies or substantial portions of the Software. * * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS * FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR * COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER * IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. * * http://aws.amazon.com/freertos * http://www.FreeRTOS.org */ /* Demo configuration includes. */ #include "iot_config.h" /* Standard includes. */ #include #include /* Demo logging include. */ #include "iot_demo_logging.h" /* Platform includes for demo. */ #include "platform/iot_clock.h" #include "platform/iot_network.h" /* Defender includes. */ #include "aws_iot_defender.h" /* Includes for initialization. */ #include "iot_mqtt.h" #include "platform/iot_metrics.h" /** * @brief The keep-alive interval used for this demo. * * An MQTT ping request will be sent periodically at this interval. */ #define KEEP_ALIVE_SECONDS ( ( uint16_t ) 60 ) /** * @brief The timeout for Defender and MQTT operations in this demo. */ #define TIMEOUT_MS ( ( uint32_t ) 5000 ) /** * @brief Defender metrics publish interval, 5 minutes (300 seconds) is minumum. */ #define DEFENDER_PUBLISH_INTERVAL ( ( uint32_t ) 300 ) /*-----------------------------------------------------------*/ /** * @brief Callback used to get notification of defender's events. * * @param[in] pCallbackContext context pointer passed by the application * when callback is regiested in AwsIotDefender_Start() * * @param[im] pointer to AwsIotDefenderCallbackInfo_t containing status of * publish */ static void _defenderCallback( void * pCallbackContext, AwsIotDefenderCallbackInfo_t * const pCallbackInfo ) { ( void ) pCallbackContext; IotLogInfo( "User's callback is invoked on event: %s.", AwsIotDefender_EventType( pCallbackInfo->eventType ) ); if( pCallbackInfo != NULL ) { /* Callback info processing example . */ if( pCallbackInfo->pMetricsReport != NULL ) { IotLogInfo( "Published metrics report." ); } else { IotLogError( "No metrics report was generated." ); } if( pCallbackInfo->pPayload != NULL ) { IotLogInfo( "Received MQTT message." ); } else { IotLogError( "No message has been returned from subscribed topic." ); } } } /*-----------------------------------------------------------*/ /** * @brief Establish a new connection to the MQTT server for the Defender demo. * * @param[in] pIdentifier NULL-terminated MQTT client identifier. The Defender * demo will use the Thing Name as the client identifier. * @param[in] pNetworkServerInfo Passed to the MQTT connect function when * establishing the MQTT connection. * @param[in] pNetworkCredentialInfo Passed to the MQTT connect function when * establishing the MQTT connection. * @param[in] pNetworkInterface The network interface to use for this demo. * @param[out] pMqttConnection Set to the handle to the new MQTT connection. * * @return `EXIT_SUCCESS` if the connection is successfully established; `EXIT_FAILURE` * otherwise. */ static int _establishMqttConnection( const char * pIdentifier, void * pNetworkServerInfo, void * pNetworkCredentialInfo, const IotNetworkInterface_t * pNetworkInterface, IotMqttConnection_t * pMqttConnection ) { int status = EXIT_SUCCESS; IotMqttError_t connectStatus = IOT_MQTT_STATUS_PENDING; IotMqttNetworkInfo_t networkInfo = IOT_MQTT_NETWORK_INFO_INITIALIZER; IotMqttConnectInfo_t connectInfo = IOT_MQTT_CONNECT_INFO_INITIALIZER; if( pIdentifier == NULL ) { IotLogError( "Defender Thing Name must be provided." ); status = EXIT_FAILURE; } if( status == EXIT_SUCCESS ) { /* Set the members of the network info not set by the initializer. This * struct provided information on the transport layer to the MQTT connection. */ networkInfo.createNetworkConnection = true; networkInfo.u.setup.pNetworkServerInfo = pNetworkServerInfo; networkInfo.u.setup.pNetworkCredentialInfo = pNetworkCredentialInfo; networkInfo.pNetworkInterface = pNetworkInterface; /* Set the members of the connection info not set by the initializer. */ connectInfo.awsIotMqttMode = true; connectInfo.cleanSession = true; connectInfo.keepAliveSeconds = KEEP_ALIVE_SECONDS; /* AWS IoT recommends the use of the Thing Name as the MQTT client ID. */ connectInfo.pClientIdentifier = pIdentifier; connectInfo.clientIdentifierLength = ( uint16_t ) strlen( pIdentifier ); IotLogInfo( "Defender Thing Name is %.*s (length %hu).", connectInfo.clientIdentifierLength, connectInfo.pClientIdentifier, connectInfo.clientIdentifierLength ); /* Establish the MQTT connection. */ connectStatus = IotMqtt_Connect( &networkInfo, &connectInfo, TIMEOUT_MS, pMqttConnection ); if( connectStatus != IOT_MQTT_SUCCESS ) { IotLogError( "MQTT CONNECT returned error %s.", IotMqtt_strerror( connectStatus ) ); status = EXIT_FAILURE; } } return status; } /*-----------------------------------------------------------*/ /** * @brief The function that runs the Defender demo, called by the demo runner. * * @param[in] awsIotMqttMode Ignored for the Defender demo. * @param[in] pIdentifier NULL-terminated Defender Thing Name. * @param[in] pNetworkServerInfo Passed to the MQTT connect function when * establishing the MQTT connection for Defender. * @param[in] pNetworkCredentialInfo Passed to the MQTT connect function when * establishing the MQTT connection for Defender. * @param[in] pNetworkInterface The network interface to use for this demo. * * @return `EXIT_SUCCESS` if the demo completes successfully; `EXIT_FAILURE` otherwise. */ int RunDefenderDemo( bool awsIotMqttMode, const char * pIdentifier, void * pNetworkServerInfo, void * pNetworkCredentialInfo, const IotNetworkInterface_t * pNetworkInterface ) { int status = EXIT_SUCCESS; bool metricsInitStatus = false; IotMqttError_t mqttStatus = IOT_MQTT_INIT_FAILED; AwsIotDefenderError_t defenderResult = AWS_IOT_DEFENDER_INTERNAL_FAILURE; AwsIotDefenderStartInfo_t startInfo = AWS_IOT_DEFENDER_START_INFO_INITIALIZER; const AwsIotDefenderCallback_t callback = { .function = _defenderCallback, .pCallbackContext = NULL }; IotMqttConnection_t mqttConnection = IOT_MQTT_CONNECTION_INITIALIZER; /* Unused parameters. */ ( void ) awsIotMqttMode; IotLogInfo( "----Device Defender Demo Start----" ); /* Check parameter(s). */ if( ( pIdentifier == NULL ) || ( pIdentifier[ 0 ] == '\0' ) ) { IotLogError( "The length of the Thing Name (identifier) must be nonzero." ); status = EXIT_FAILURE; } if( status == EXIT_SUCCESS ) { /* Initialize the MQTT library. */ mqttStatus = IotMqtt_Init(); if( mqttStatus != IOT_MQTT_SUCCESS ) { IotLogError( "MQTT Initialization Failed." ); status = EXIT_FAILURE; } } if( status == EXIT_SUCCESS ) { /* Initialize Metrics. */ metricsInitStatus = IotMetrics_Init(); if( !metricsInitStatus ) { IotLogError( "IOT Metrics Initialization Failed." ); status = EXIT_FAILURE; } } if( status == EXIT_SUCCESS ) { /* Specify all metrics in "tcp connections" group */ defenderResult = AwsIotDefender_SetMetrics( AWS_IOT_DEFENDER_METRICS_TCP_CONNECTIONS, AWS_IOT_DEFENDER_METRICS_ALL ); if( defenderResult != AWS_IOT_DEFENDER_SUCCESS ) { status = EXIT_FAILURE; } } if( status == EXIT_SUCCESS ) { /* Set metrics report period */ defenderResult = AwsIotDefender_SetPeriod( DEFENDER_PUBLISH_INTERVAL ); if( defenderResult != AWS_IOT_DEFENDER_SUCCESS ) { status = EXIT_FAILURE; } } if( status == EXIT_SUCCESS ) { /* Create MQTT Connection */ mqttStatus = _establishMqttConnection( pIdentifier, pNetworkServerInfo, pNetworkCredentialInfo, pNetworkInterface, &mqttConnection ); if( mqttStatus != IOT_MQTT_SUCCESS ) { IotLogError( "Failed to Create MQTT Connection:%d", IotMqtt_strerror( mqttStatus ) ); IotMqtt_Cleanup(); defenderResult = AWS_IOT_DEFENDER_INTERNAL_FAILURE; } else { /* Initialize start info and call defender Start API */ startInfo.pClientIdentifier = pIdentifier; startInfo.clientIdentifierLength = ( uint16_t ) strlen( pIdentifier ); startInfo.callback = callback; startInfo.mqttConnection = mqttConnection; defenderResult = AwsIotDefender_Start( &startInfo ); } if( defenderResult == AWS_IOT_DEFENDER_SUCCESS ) { /* Let it run for 3 seconds */ IotClock_SleepMs( 3000 ); /* Stop the defender agent. */ AwsIotDefender_Stop(); /* Disconnect MQTT */ IotMqtt_Disconnect( mqttConnection, false ); } } /* Cleanup. */ if( metricsInitStatus ) { IotMetrics_Cleanup(); } if( mqttStatus == IOT_MQTT_SUCCESS ) { IotMqtt_Cleanup(); } IotLogInfo( "----Device Defender Demo End. Status: %s----.", AwsIotDefender_strerror( defenderResult ) ); return status; } /*-----------------------------------------------------------*/