Diff between coreHTTP example

Created Diff never expires
52 removals
Lines
Total
Removed
Words
Total
Removed
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
416 lines
52 additions
Lines
Total
Added
Words
Total
Added
To continue using this feature, upgrade to
Diffchecker logo
Diffchecker Pro
414 lines
/*
/*
* AWS IoT Device SDK for Embedded C 202103.00
* AWS IoT Device SDK for Embedded C 202103.00
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
* Copyright (C) 2020 Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
*
* Permission is hereby granted, free of charge, to any person obtaining a copy of
* 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
* this software and associated documentation files (the "Software"), to deal in
* the Software without restriction, including without limitation the rights to
* the Software without restriction, including without limitation the rights to
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of
* 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,
* the Software, and to permit persons to whom the Software is furnished to do so,
* subject to the following conditions:
* subject to the following conditions:
*
*
* The above copyright notice and this permission notice shall be included in all
* The above copyright notice and this permission notice shall be included in all
* copies or substantial portions of the Software.
* copies or substantial portions of the Software.
*
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR
* 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
* 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
* 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.
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
*/


/* Standard includes. */
/* Standard includes. */
#include <assert.h>
#include <assert.h>
#include <stdlib.h>
#include <stdlib.h>
#include <string.h>
#include <string.h>


/* POSIX includes. */
/* POSIX includes. */
#include <unistd.h>
#include <unistd.h>


/* Include Demo Config as the first non-system header. */
/* Include Demo Config as the first non-system header. */
#include "demo_config.h"
#include "demo_config.h"


/* Common HTTP demo utilities. */
/* Common HTTP demo utilities. */
#include "http_demo_utils.h"
#include "http_demo_utils.h"


/* HTTP API header. */
/* HTTP API header. */
#include "core_http_client.h"
#include "core_http_client.h"


/* OpenSSL transport header. */
/* OpenSSL transport header. */
#include "openssl_posix.h"
#include "tls_freertos.h"

#include "demo_header.h"


/* Check that AWS IoT Core endpoint is defined. */
/* Check that AWS IoT Core endpoint is defined. */
#ifndef AWS_IOT_ENDPOINT
#define AWS_IOT_ENDPOINT CONFIG_AWS_IOT_ENDPOINT
#error "AWS_IOT_ENDPOINT must be defined to your AWS IoT Core endpoint."
#ifndef ROOT_CA_PEM
#endif
#if CONFIG_BROKER_CERTIFICATE_OVERRIDDEN == 1

static const uint8_t root_cert_auth_pem_start[] = "-----BEGIN CERTIFICATE-----\n" CONFIG_BROKER_CERTIFICATE_OVERRIDE "\n-----END CERTIFICATE-----";
/* Check that TLS port used for AWS IoT Core is defined. */
#else
#ifndef AWS_HTTPS_PORT
extern const uint8_t root_cert_auth_pem_start[] asm("_binary_root_cert_auth_pem_start");
#error "Please define a AWS_HTTPS_PORT."
#endif
extern const uint8_t root_cert_auth_pem_end[] asm("_binary_root_cert_auth_pem_end");
#endif
#endif


/* Check that a path for HTTP Method POST is defined. */
/* Check that a path for HTTP Method POST is defined. */
#ifndef POST_PATH
#ifndef POST_PATH
#error "Please define a POST_PATH."
#error "Please define a POST_PATH."
#endif
#endif


/* Check that a path for Root CA certificate is defined. */
/* Check that a path for Root CA certificate is defined. */
#ifndef ROOT_CA_CERT_PATH

#error "Please define a ROOT_CA_CERT_PATH."
#endif


/* Check that a path for the client certificate is defined. */
/* Check that a path for the client certificate is defined. */
#ifndef CLIENT_CERT_PATH
#ifndef CLIENT_CERTIFICATE_PEM
#error "Please define a CLIENT_CERT_PATH."
extern const uint8_t client_cert_pem_start[] asm("_binary_client_crt_start");
extern const uint8_t client_cert_pem_end[] asm("_binary_client_crt_end");
#endif
#endif

#ifndef CLIENT_PRIVATE_KEY_PEM
/* Check that a path for the client's private key is defined. */
extern const uint8_t client_key_pem_start[] asm("_binary_client_key_start");
#ifndef CLIENT_PRIVATE_KEY_PATH
extern const uint8_t client_key_pem_end[] asm("_binary_client_key_end");
#error "Please define a CLIENT_PRIVATE_KEY_PATH."
#endif
#endif


/**
/**
* @brief ALPN protocol name to be sent as part of the ClientHello message.
* @brief ALPN protocol name to be sent as part of the ClientHello message.
*
*
* @note When using ALPN, port 443 must be used to connect to AWS IoT Core.
* @note When using ALPN, port 443 must be used to connect to AWS IoT Core.
*/
*/
#define IOT_CORE_ALPN_PROTOCOL_NAME "\x0ex-amzn-http-ca"
#define IOT_CORE_ALPN_PROTOCOL_NAME "x-amzn-http-ca"


/* Check that transport timeout for transport send and receive is defined. */
/* Check that transport timeout for transport send and receive is defined. */
#ifndef TRANSPORT_SEND_RECV_TIMEOUT_MS
#ifndef TRANSPORT_SEND_RECV_TIMEOUT_MS
#define TRANSPORT_SEND_RECV_TIMEOUT_MS ( 1000 )
#define TRANSPORT_SEND_RECV_TIMEOUT_MS ( 1500 )
#endif
#endif


/* Check that size of the user buffer is defined. */
/* Check that size of the user buffer is defined. */
#ifndef USER_BUFFER_LENGTH
#ifndef USER_BUFFER_LENGTH
#define USER_BUFFER_LENGTH ( 2048 )
#define USER_BUFFER_LENGTH ( 2048 )
#endif
#endif


/* Check that a request body to send for the POST request is defined. */
/* Check that a request body to send for the POST request is defined. */
#ifndef REQUEST_BODY
#ifndef REQUEST_BODY
#error "Please define a REQUEST_BODY."
#error "Please define a REQUEST_BODY."
#endif
#endif


/**
/**
* @brief The length of the AWS IoT Endpoint.
* @brief The length of the AWS IoT Endpoint.
*/
*/
#define AWS_IOT_ENDPOINT_LENGTH ( sizeof( AWS_IOT_ENDPOINT ) - 1 )
#define AWS_IOT_ENDPOINT_LENGTH ( sizeof( AWS_IOT_ENDPOINT ) - 1 )


/**
/**
* @brief The length of the HTTP POST method.
* @brief The length of the HTTP POST method.
*/
*/
#define HTTP_METHOD_POST_LENGTH ( sizeof( HTTP_METHOD_POST ) - 1 )
#define HTTP_METHOD_POST_LENGTH ( sizeof( HTTP_METHOD_POST ) - 1 )


/**
/**
* @brief The length of the HTTP POST path.
* @brief The length of the HTTP POST path.
*/
*/
#define POST_PATH_LENGTH ( sizeof( POST_PATH ) - 1 )
#define POST_PATH_LENGTH ( sizeof( POST_PATH ) - 1 )


/**
/**
* @brief Length of the request body.
* @brief Length of the request body.
*/
*/
#define REQUEST_BODY_LENGTH ( sizeof( REQUEST_BODY ) - 1 )
#define REQUEST_BODY_LENGTH ( sizeof( REQUEST_BODY ) - 1 )


/**
/**
* @brief A buffer used in the demo for storing HTTP request headers and
* @brief A buffer used in the demo for storing HTTP request headers and
* HTTP response headers and body.
* HTTP response headers and body.
*
*
* @note This demo shows how the same buffer can be re-used for storing the HTTP
* @note This demo shows how the same buffer can be re-used for storing the HTTP
* response after the HTTP request is sent out. However, the user can also
* response after the HTTP request is sent out. However, the user can also
* decide to use separate buffers for storing the HTTP request and response.
* decide to use separate buffers for storing the HTTP request and response.
*/
*/
static uint8_t userBuffer[ USER_BUFFER_LENGTH ];
static uint8_t userBuffer[ USER_BUFFER_LENGTH ];


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


/* Each compilation unit must define the NetworkContext struct. */
struct NetworkContext
{
OpensslParams_t * pParams;
};

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

/**
/**
* @brief Connect to HTTP server with reconnection retries.
* @brief Connect to HTTP server with reconnection retries.
*
*
* @param[out] pNetworkContext The output parameter to return the created network context.
* @param[out] pNetworkContext The output parameter to return the created network context.
*
*
* @return EXIT_FAILURE on failure; EXIT_SUCCESS on successful connection.
* @return EXIT_FAILURE on failure; EXIT_SUCCESS on successful connection.
*/
*/
static int32_t connectToServer( NetworkContext_t * pNetworkContext );
static int32_t connectToServer( NetworkContext_t * pNetworkContext );


/**
/**
* @brief Send an HTTP request based on a specified method and path, then
* @brief Send an HTTP request based on a specified method and path, then
* print the response received from the server.
* print the response received from the server.
*
*
* @param[in] pTransportInterface The transport interface for making network calls.
* @param[in] pTransportInterface The transport interface for making network calls.
* @param[in] pMethod The HTTP request method.
* @param[in] pMethod The HTTP request method.
* @param[in] methodLen The length of the HTTP request method.
* @param[in] methodLen The length of the HTTP request method.
* @param[in] pPath The Request-URI to the objects of interest.
* @param[in] pPath The Request-URI to the objects of interest.
* @param[in] pathLen The length of the Request-URI.
* @param[in] pathLen The length of the Request-URI.
*
*
* @return EXIT_FAILURE on failure; EXIT_SUCCESS on success.
* @return EXIT_FAILURE on failure; EXIT_SUCCESS on success.
*/
*/
static int32_t sendHttpRequest( const TransportInterface_t * pTransportInterface,
static int32_t sendHttpRequest( const TransportInterface_t * pTransportInterface,
const char * pMethod,
const char * pMethod,
size_t methodLen,
size_t methodLen,
const char * pPath,
const char * pPath,
size_t pathLen );
size_t pathLen );


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


static int32_t connectToServer( NetworkContext_t * pNetworkContext )
static int32_t connectToServer( NetworkContext_t * pNetworkContext )
{
{
int32_t returnStatus = EXIT_FAILURE;
int32_t returnStatus = EXIT_FAILURE;
/* Status returned by OpenSSL transport implementation. */
/* Status returned by OpenSSL transport implementation. */
OpensslStatus_t opensslStatus;
TlsTransportStatus_t opensslStatus;
/* Credentials to establish the TLS connection. */
/* Credentials to establish the TLS connection. */
OpensslCredentials_t opensslCredentials;
NetworkCredentials_t *opensslCredentials = (NetworkCredentials_t*) malloc (sizeof (NetworkCredentials_t));
/* Information about the server to send the HTTP requests. */
/* Information about the server to send the HTTP requests. */
ServerInfo_t serverInfo;
ServerInfo_t serverInfo;


/* Initialize TLS credentials. */
/* Initialize TLS credentials. */
( void ) memset( &opensslCredentials, 0, sizeof( opensslCredentials ) );
opensslCredentials->pClientCert = ( const unsigned char * ) client_cert_pem_start;
opensslCredentials.pClientCertPath = CLIENT_CERT_PATH;
opensslCredentials->clientCertSize = client_cert_pem_end - client_cert_pem_start;
opensslCredentials.pPrivateKeyPath = CLIENT_PRIVATE_KEY_PATH;
opensslCredentials->pPrivateKey = ( const unsigned char * ) client_key_pem_start;
opensslCredentials.pRootCaPath = ROOT_CA_CERT_PATH;
opensslCredentials->privateKeySize = client_key_pem_end - client_key_pem_start;
opensslCredentials.sniHostName = AWS_IOT_ENDPOINT;
opensslCredentials->pRootCa = ( const unsigned char * ) root_cert_auth_pem_start;
opensslCredentials->rootCaSize = root_cert_auth_pem_end - root_cert_auth_pem_start;
opensslCredentials->disableSni = 0;


/* ALPN is required when communicating to AWS IoT Core over port 443 through HTTP. */
/* ALPN is required when communicating to AWS IoT Core over port 443 through HTTP. */
if( AWS_HTTPS_PORT == 443 )
if( AWS_HTTPS_PORT == 443 )
{
{
opensslCredentials.pAlpnProtos = IOT_CORE_ALPN_PROTOCOL_NAME;
static const char * pcAlpnProtocols[] = { NULL, NULL };
opensslCredentials.alpnProtosLen = strlen( IOT_CORE_ALPN_PROTOCOL_NAME );
pcAlpnProtocols[0] = IOT_CORE_ALPN_PROTOCOL_NAME;
opensslCredentials->pAlpnProtos = pcAlpnProtocols;

} else {
opensslCredentials->pAlpnProtos = NULL;
}
}


/* Initialize server information. */
/* Initialize server information. */
serverInfo.pHostName = AWS_IOT_ENDPOINT;
serverInfo.pHostName = AWS_IOT_ENDPOINT;
serverInfo.hostNameLength = AWS_IOT_ENDPOINT_LENGTH;
serverInfo.hostNameLength = AWS_IOT_ENDPOINT_LENGTH;
serverInfo.port = AWS_HTTPS_PORT;
serverInfo.port = AWS_HTTPS_PORT;


/* Establish a TLS session with the HTTP server. This example connects
/* Establish a TLS session with the HTTP server. This example connects
* to the HTTP server as specified in AWS_IOT_ENDPOINT and AWS_HTTPS_PORT
* to the HTTP server as specified in AWS_IOT_ENDPOINT and AWS_HTTPS_PORT
* in demo_config.h. */
* in demo_config.h. */
LogInfo( ( "Establishing a TLS session to %.*s:%d.",
LogInfo( ( "Establishing a TLS session to %.*s:%d.",
( int32_t ) AWS_IOT_ENDPOINT_LENGTH,
( int32_t ) AWS_IOT_ENDPOINT_LENGTH,
AWS_IOT_ENDPOINT,
AWS_IOT_ENDPOINT,
AWS_HTTPS_PORT ) );
AWS_HTTPS_PORT ) );
opensslStatus = Openssl_Connect( pNetworkContext,
opensslStatus = TLS_FreeRTOS_Connect ( pNetworkContext,
&serverInfo,
serverInfo.pHostName,
&opensslCredentials,
serverInfo.port,
TRANSPORT_SEND_RECV_TIMEOUT_MS,
opensslCredentials,
TRANSPORT_SEND_RECV_TIMEOUT_MS );
TRANSPORT_SEND_RECV_TIMEOUT_MS,
TRANSPORT_SEND_RECV_TIMEOUT_MS );


if( opensslStatus == OPENSSL_SUCCESS )
if( opensslStatus == TLS_TRANSPORT_SUCCESS )
{
{
returnStatus = EXIT_SUCCESS;
returnStatus = EXIT_SUCCESS;
}
}
else
else
{
{
returnStatus = EXIT_FAILURE;
returnStatus = EXIT_FAILURE;
}
}


return returnStatus;
return returnStatus;
}
}


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


static int32_t sendHttpRequest( const TransportInterface_t * pTransportInterface,
static int32_t sendHttpRequest( const TransportInterface_t * pTransportInterface,
const char * pMethod,
const char * pMethod,
size_t methodLen,
size_t methodLen,
const char * pPath,
const char * pPath,
size_t pathLen )
size_t pathLen )
{
{
/* Return value of this method. */
/* Return value of this method. */
int32_t returnStatus = EXIT_SUCCESS;
int32_t returnStatus = EXIT_SUCCESS;


/* Configurations of the initial request headers that are passed to
/* Configurations of the initial request headers that are passed to
* #HTTPClient_InitializeRequestHeaders. */
* #HTTPClient_InitializeRequestHeaders. */
HTTPRequestInfo_t requestInfo;
HTTPRequestInfo_t requestInfo;
/* Represents a response returned from an HTTP server. */
/* Represents a response returned from an HTTP server. */
HTTPResponse_t response;
HTTPResponse_t response;
/* Represents header data that will be sent in an HTTP request. */
/* Represents header data that will be sent in an HTTP request. */
HTTPRequestHeaders_t requestHeaders;
HTTPRequestHeaders_t requestHeaders;


/* Return value of all methods from the HTTP Client library API. */
/* Return value of all methods from the HTTP Client library API. */
HTTPStatus_t httpStatus = HTTPSuccess;
HTTPStatus_t httpStatus = HTTPSuccess;


assert( pMethod != NULL );
assert( pMethod != NULL );
assert( pPath != NULL );
assert( pPath != NULL );


/* Initialize all HTTP Client library API structs to 0. */
/* Initialize all HTTP Client library API structs to 0. */
( void ) memset( &requestInfo, 0, sizeof( requestInfo ) );
( void ) memset( &requestInfo, 0, sizeof( requestInfo ) );
( void ) memset( &response, 0, sizeof( response ) );
( void ) memset( &response, 0, sizeof( response ) );
( void ) memset( &requestHeaders, 0, sizeof( requestHeaders ) );
( void ) memset( &requestHeaders, 0, sizeof( requestHeaders ) );


/* Initialize the request object. */
/* Initialize the request object. */
requestInfo.pHost = AWS_IOT_ENDPOINT;
requestInfo.pHost = AWS_IOT_ENDPOINT;
requestInfo.hostLen = AWS_IOT_ENDPOINT_LENGTH;
requestInfo.hostLen = AWS_IOT_ENDPOINT_LENGTH;
requestInfo.pMethod = pMethod;
requestInfo.pMethod = pMethod;
requestInfo.methodLen = methodLen;
requestInfo.methodLen = methodLen;
requestInfo.pPath = pPath;
requestInfo.pPath = pPath;
requestInfo.pathLen = pathLen;
requestInfo.pathLen = pathLen;


/* Set "Connection" HTTP header to "keep-alive" so that multiple requests
/* Set "Connection" HTTP header to "keep-alive" so that multiple requests
* can be sent over the same established TCP connection. */
* can be sent over the same established TCP connection. */
requestInfo.reqFlags = HTTP_REQUEST_KEEP_ALIVE_FLAG;
requestInfo.reqFlags = HTTP_REQUEST_KEEP_ALIVE_FLAG;


/* Set the buffer used for storing request headers. */
/* Set the buffer used for storing request headers. */
requestHeaders.pBuffer = userBuffer;
requestHeaders.pBuffer = userBuffer;
requestHeaders.bufferLen = USER_BUFFER_LENGTH;
requestHeaders.bufferLen = USER_BUFFER_LENGTH;


httpStatus = HTTPClient_InitializeRequestHeaders( &requestHeaders,
httpStatus = HTTPClient_InitializeRequestHeaders( &requestHeaders,
&requestInfo );
&requestInfo );


if( httpStatus == HTTPSuccess )
if( httpStatus == HTTPSuccess )
{
{
/* Initialize the response object. The same buffer used for storing
/* Initialize the response object. The same buffer used for storing
* request headers is reused here. */
* request headers is reused here. */
response.pBuffer = userBuffer;
response.pBuffer = userBuffer;
response.bufferLen = USER_BUFFER_LENGTH;
response.bufferLen = USER_BUFFER_LENGTH;


LogInfo( ( "Sending HTTP %.*s request to %.*s%.*s...",
LogInfo( ( "Sending HTTP %.*s request to %.*s%.*s...",
( int32_t ) requestInfo.methodLen, requestInfo.pMethod,
( int32_t ) requestInfo.methodLen, requestInfo.pMethod,
( int32_t ) AWS_IOT_ENDPOINT_LENGTH, AWS_IOT_ENDPOINT,
( int32_t ) AWS_IOT_ENDPOINT_LENGTH, AWS_IOT_ENDPOINT,
( int32_t ) requestInfo.pathLen, requestInfo.pPath ) );
( int32_t ) requestInfo.pathLen, requestInfo.pPath ) );
LogDebug( ( "Request Headers:\n%.*s\n"
LogDebug( ( "Request Headers:\n%.*s\n"
"Request Body:\n%.*s\n",
"Request Body:\n%.*s\n",
( int32_t ) requestHeaders.headersLen,
( int32_t ) requestHeaders.headersLen,
( char * ) requestHeaders.pBuffer,
( char * ) requestHeaders.pBuffer,
( int32_t ) REQUEST_BODY_LENGTH, REQUEST_BODY ) );
( int32_t ) REQUEST_BODY_LENGTH, REQUEST_BODY ) );


/* Send the request and receive the response. */
/* Send the request and receive the response. */
httpStatus = HTTPClient_Send( pTransportInterface,
httpStatus = HTTPClient_Send( pTransportInterface,
&requestHeaders,
&requestHeaders,
( uint8_t * ) REQUEST_BODY,
( uint8_t * ) REQUEST_BODY,
REQUEST_BODY_LENGTH,
REQUEST_BODY_LENGTH,
&response,
&response,
0 );
0 );
}
}
else
else
{
{
LogError( ( "Failed to initialize HTTP request headers: Error=%s.",
LogError( ( "Failed to initialize HTTP request headers: Error=%s.",
HTTPClient_strerror( httpStatus ) ) );
HTTPClient_strerror( httpStatus ) ) );
}
}


if( httpStatus == HTTPSuccess )
if( httpStatus == HTTPSuccess )
{
{
LogInfo( ( "Received HTTP response from %.*s%.*s...\n"
LogInfo( ( "Received HTTP response from %.*s%.*s...\n"
"Response Headers:\n%.*s\n"
"Response Headers:\n%.*s\n"
"Response Status:\n%u\n"
"Response Status:\n%u\n"
"Response Body:\n%.*s\n",
"Response Body:\n%.*s\n",
( int32_t ) AWS_IOT_ENDPOINT_LENGTH, AWS_IOT_ENDPOINT,
( int32_t ) AWS_IOT_ENDPOINT_LENGTH, AWS_IOT_ENDPOINT,
( int32_t ) requestInfo.pathLen, requestInfo.pPath,
( int32_t ) requestInfo.pathLen, requestInfo.pPath,
( int32_t ) response.headersLen, response.pHeaders,
( int32_t ) response.headersLen, response.pHeaders,
response.statusCode,
response.statusCode,
( int32_t ) response.bodyLen, response.pBody ) );
( int32_t ) response.bodyLen, response.pBody ) );
}
}
else
else
{
{
LogError( ( "Failed to send HTTP %.*s request to %.*s%.*s: Error=%s.",
LogError( ( "Failed to send HTTP %.*s request to %.*s%.*s: Error=%s.",
( int32_t ) requestInfo.methodLen, requestInfo.pMethod,
( int32_t ) requestInfo.methodLen, requestInfo.pMethod,
( int32_t ) AWS_IOT_ENDPOINT_LENGTH, AWS_IOT_ENDPOINT,
( int32_t ) AWS_IOT_ENDPOINT_LENGTH, AWS_IOT_ENDPOINT,
( int32_t ) requestInfo.pathLen, requestInfo.pPath,
( int32_t ) requestInfo.pathLen, requestInfo.pPath,
HTTPClient_strerror( httpStatus ) ) );
HTTPClient_strerror( httpStatus ) ) );
}
}


if( httpStatus != HTTPSuccess )
if( httpStatus != HTTPSuccess )
{
{
returnStatus = EXIT_FAILURE;
returnStatus = EXIT_FAILURE;
}
}


return returnStatus;
return returnStatus;
}
}


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


/**
/**
* @brief Entry point of demo.
* @brief Entry point of demo.
*
*
* This example resolves the AWS IoT Core endpoint, establishes a TCP connection,
* This example resolves the AWS IoT Core endpoint, establishes a TCP connection,
* performs a mutually authenticated TLS handshake occurs such that all further
* performs a mutually authenticated TLS handshake occurs such that all further
* communication is encrypted. After which, HTTP Client Library API is used to
* communication is encrypted. After which, HTTP Client Library API is used to
* make a POST request to AWS IoT Core in order to publish a message to a topic
* make a POST request to AWS IoT Core in order to publish a message to a topic
* named topic with QoS=1 so that all clients subscribed to the topic receive
* named topic with QoS=1 so that all clients subscribed to the topic receive
* the message at least once. Any possible errors are also logged.
* the message at least once. Any possible errors are also logged.
*
*
* @note This example is single-threaded and uses statically allocated memory.
* @note This example is single-threaded and uses statically allocated memory.
*
*
*/
*/
int main( int argc,
int aws_iot_demo_main( int argc,
char ** argv )
char ** argv )
{
{
/* Return value of main. */
/* Return value of main. */
int32_t returnStatus = EXIT_SUCCESS;
int32_t returnStatus = EXIT_SUCCESS;
/* The transport layer interface used by the HTTP Client library. */
/* The transport layer interface used by the HTTP Client library. */
TransportInterface_t transportInterface;
TransportInterface_t transportInterface;
/* The network context for the transport layer interface. */
/* The network context for the transport layer interface. */
NetworkContext_t networkContext;
NetworkContext_t networkContext;
OpensslParams_t opensslParams;


( void ) argc;
( void ) argc;
( void ) argv;
( void ) argv;


/* Set the pParams member of the network context with desired transport. */
/* Set the pParams member of the network context with desired transport. */
networkContext.pParams = &opensslParams;


/**************************** Connect. ******************************/
/**************************** Connect. ******************************/


/* Establish TLS connection on top of TCP connection using OpenSSL. */
/* Establish TLS connection on top of TCP connection using OpenSSL. */
if( returnStatus == EXIT_SUCCESS )
if( returnStatus == EXIT_SUCCESS )
{
{
LogInfo( ( "Performing TLS handshake on top of the TCP connection." ) );
LogInfo( ( "Performing TLS handshake on top of the TCP connection." ) );


/* Attempt to connect to the HTTP server. If connection fails, retry after
/* Attempt to connect to the HTTP server. If connection fails, retry after
* a timeout. Timeout value will be exponentially increased till the maximum
* a timeout. Timeout value will be exponentially increased till the maximum
* attempts are reached or maximum timeout value is reached. The function
* attempts are reached or maximum timeout value is reached. The function
* returns EXIT_FAILURE if the TCP connection cannot be established to
* returns EXIT_FAILURE if the TCP connection cannot be established to
* broker after configured number of attempts. */
* broker after configured number of attempts. */
returnStatus = connectToServerWithBackoffRetries( connectToServer,
returnStatus = connectToServerWithBackoffRetries( connectToServer,
&networkContext );
&networkContext );


if( returnStatus == EXIT_FAILURE )
if( returnStatus == EXIT_FAILURE )
{
{
/* Log error to indicate connection failure after all
/* Log error to indicate connection failure after all
* reconnect attempts are over. */
* reconnect attempts are over. */
LogError( ( "Failed to connect to HTTP server %.*s.",
LogError( ( "Failed to connect to HTTP server %.*s.",
( int32_t ) AWS_IOT_ENDPOINT_LENGTH,
( int32_t ) AWS_IOT_ENDPOINT_LENGTH,
AWS_IOT_ENDPOINT ) );
AWS_IOT_ENDPOINT ) );
}
}
}
}


/* Define the transport interface. */
/* Define the transport interface. */
if( returnStatus == EXIT_SUCCESS )
if( returnStatus == EXIT_SUCCESS )
{
{
( void ) memset( &transportInterface, 0, sizeof( transportInterface ) );
( void ) memset( &transportInterface, 0, sizeof( transportInterface ) );
transportInterface.recv = Openssl_Recv;
transportInterface.recv = TLS_FreeRTOS_recv;
transportInterface.send = Openssl_Send;
transportInterface.send = TLS_FreeRTOS_send;
transportInterface.pNetworkContext = &networkContext;
transportInterface.pNetworkContext = &networkContext;
}
}


/*********************** Send HTTPS request. ************************/
/*********************** Send HTTPS request. ************************/


if( returnStatus == EXIT_SUCCESS )
if( returnStatus == EXIT_SUCCESS )
{
{
returnStatus = sendHttpRequest( &transportInterface,
returnStatus = sendHttpRequest( &transportInterface,
HTTP_METHOD_POST,
HTTP_METHOD_POST,
HTTP_METHOD_POST_LENGTH,
HTTP_METHOD_POST_LENGTH,
POST_PATH,
POST_PATH,
POST_PATH_LENGTH );
POST_PATH_LENGTH );
}
}


if( returnStatus == EXIT_SUCCESS )
if( returnStatus == EXIT_SUCCESS )
{
{
/* Log message indicating an iteration completed successfully. */
/* Log message indicating an iteration completed successfully. */
LogInfo( ( "Demo completed successfully." ) );
LogInfo( ( "Demo completed successfully." ) );
}
}


/************************** Disconnect. *****************************/
/************************** Disconnect. *****************************/


/* End TLS session, then close TCP connection. */
/* End TLS session, then close TCP connection. */
( void ) Openssl_Disconnect( &networkContext );
( void ) TLS_FreeRTOS_Disconnect( &networkContext );


return returnStatus;
return returnStatus;
}
}