Azure C SDK Port Library
Overview

This library implements the port layer for the Azure SDK for Embedded C to work on PSoC™ 6 MCU connectivity-enabled platforms. This library automatically pulls the Azure SDK for Embedded C library; the port layer functions implemented by this library are used by the Azure SDK for Embedded C library.

Features

API Flow for HTTP Request

The Azure C SDK library provides various C APIs to connect with Azure Cloud and use the services offered. The Azure C SDK library also provide APIs to form and send an HTTP request to the server. This section provides the API call sequence to issue a secure or non-secure HTTP request to the server.

HTTP Client send request

          +-----------------------+
          | cy_http_client_init() |
          +-----------------------+
                     |
                     v
        +----------------------------+
        |    cy_http_client_create() |
        +----------------------------+
                     |
                     v
         +--------------------------+
         | cy_http_client_connect() |
         +--------------------------+
                     |
                     v
          +------------------------+
          | az_http_response_init()|
          +------------------------+
                     |
                     v
       +-------------------------------+
       | az_http_client_send_request() |
       +-------------------------------+
                     |
                     v
        +-----------------------------+
        | cy_http_client_disconnect() |
        +-----------------------------+
                     |
                     v
          +-------------------------+
          | cy_http_client_delete() |
          +-------------------------+
                     |
                     v
          +-------------------------+
          | cy_http_client_deinit() |
          +-------------------------+

Supported Platform

Supported Frameworks

This middleware library is supported on the ModusToolbox™ environment:

  • This environment uses the abstraction-rtos library for RTOS abstraction APIs, the http-client library for sending HTTP client requests and receiving server responses, and the mqtt library for Azure-supported IoT hub services.

Dependencies

Azure C SDK Port library depends on the following libraries:

Quick Start

This library is supported only on the ModusToolbox™ environment. The following section provides steps to build the library on the ModusToolbox™.

  • Review and make the required changes to the pre-defined configuration files.
    • The configuration files are bundled with the wifi-mw-core library for FreeRTOS, lwIP, and Mbed TLS. See README.md for more details.
    • If the application is using bundle library then the configuration files are in the bundle library. For example if the application is using Wi-Fi core freertos lwip mbedtls bundle library, the configuration files are in wifi-core-freertos-lwip-mbedtls/configs folder. Similarly if the application is using Ethernet Core FreeRTOS lwIP mbedtls library, the configuration files are in ethernet-core-freertos-lwip-mbedtls/configs folder.
  • Define the following COMPONENTS in the application's Makefile for the HTTP client library. For additional information, see the "Quick Start" section in README.md.
    COMPONENTS=FREERTOS MBEDTLS LWIP SECURE_SOCKETS
  • The Azure C SDK Port library disables all the debug log messages by default. To enable log messages, the application must perform the following:
    • Add the ENABLE_AZ_PORT_LOGS macro to the DEFINES in the code example's Makefile. The Makefile entry would look as follows:
      DEFINES+=ENABLE_AZ_PORT_LOGS
    • Call the cy_log_init() function provided by the cy-log module. cy-log is part of the connectivity-utilities library. See connectivity-utilities library API documentation for cy-log details.
  • Define the following macro in the application's Makefile for HTTP client configuration:
    • This is an optional configuration to change the HTTP response header maximum length to 'N'. By default, this value will be set to 2048:
      DEFINES+=HTTP_MAX_RESPONSE_HEADERS_SIZE_BYTES=<N>
    • To configure the user agent name in all HTTP request headers. By default, this component will be added to the request header. Update this for user-defined agent values:
      DEFINES += HTTP_USER_AGENT_VALUE="\"anycloud-http-client\""
    • Define the following macros in the application's Makefile to mandatorily disable custom configuration header files that are not needed for the build:
      DEFINES += HTTP_DO_NOT_USE_CUSTOM_CONFIG
      DEFINES += MQTT_DO_NOT_USE_CUSTOM_CONFIG
    • If the user application doesn't use MQTT client features, add the following path in the .cyignore file of the application to exclude the coreMQTT source files from the build:
      $(SEARCH_aws-iot-device-sdk-embedded-C)/libraries/standard/coreMQTT
      libs/aws-iot-device-sdk-embedded-C/libraries/standard/coreMQTT
  • Sample applications for Azure IoT hub, and Azure DPS features are located in folder ./sample_app/. For running the sample applications on PSoC™ 6 MCU connectivity-enabled platforms, Refer README.md located in *./sample_app/README.md*.

Addtional Information

Code Snippets

This section provides code snippets for this library on the ModusToolbox™ environment. The code snippets given under this section uses C APIs. In general, the library features are tested on ModusToolbox™ using C APIs.

The code snippets given in this section demonstrates how Azure APIs can be used for issuing a secure and non-secure HTTP request to the server.

Code Snippet 1: Send a non-secure HTTP GET request to the server

Send a HTTP GET request (header + body) to the server and receive response

/* HTTP Server configuration macros */
#define MAKE_IPV4_ADDRESS(a, b, c, d) ((((uint32_t) d) << 24) | \
(((uint32_t) c) << 16) | \
(((uint32_t) b) << 8) |\
((uint32_t) a))
#define SERVER_IP_ADDRESS MAKE_IPV4_ADDRESS(192, 168, 18, 9)
#define SERVER_HOST "httpbin.org"
#define SERVER_PORT 80
/* HTTP socket send and receive timeout */
#define TRANSPORT_SEND_RECV_TIMEOUT_MS ( 5000 )
/* URL to read the data */
#define GET_PATH "/get"
/* User buffer for HTTP request and response */
#define USER_BUFFER_LENGTH ( 2048 )
/* Request body in the HTTP header */
#define REQUEST_BODY "Hello, world!"
#define REQUEST_BODY_LENGTH ( sizeof( REQUEST_BODY ) - 1 )
/* Application buffer to hold the HTTP request and response */
static uint8_t userBuffer[ USER_BUFFER_LENGTH ];
/* SSL credentials information */
static cy_awsport_server_info_t server_info;
/* HTTP client object used to send and recevie the requests */
static cy_http_client_t handle;
/* Azure SDK structure containing HTTP client request */
static az_http_request az_request;
/* Azure SDK structure containing HTTP client header */
static _az_http_request_header az_header;
/* Azure SDK structure containing HTTP server response */
static az_http_response az_response;
void snippet_non_secure_http_client_send(void)
{
/* Status variables for various operations */
cy_rslt_t result = CY_RSLT_SUCCESS;
az_result returnStatus;
/* User callback on disconnect */
cy_http_disconnect_callback_t http_cb;
( void ) memset( &server_info, 0, sizeof( server_info ) );
/* HTTP server information for connection */
server_info.host_name = SERVER_HOST;
server_info.port = SERVER_PORT;
/* Initialize the HTTP Client Library */
result = cy_http_client_init();
if( result != CY_RSLT_SUCCESS )
{
/* Failure path */
}
/* HTTP client disconnect callback */
http_cb = disconnect_callback;
/* Create an instance of the HTTP client */
result = cy_http_client_create( NULL, &server_info, http_cb, NULL, &handle );
if( result != CY_RSLT_SUCCESS )
{
/* Failure path */
}
/* Connect the HTTP client to the server */
result = cy_http_client_connect( handle, TRANSPORT_SEND_RECV_TIMEOUT_MS, TRANSPORT_SEND_RECV_TIMEOUT_MS );
if( result != CY_RSLT_SUCCESS )
{
/* Failure path */
}
/* Copy user buffer to Azure buffer structure for HTTP request handling */
az_span az_buffer = az_span_create( ( uint8_t* )userBuffer, ( int32_t )USER_BUFFER_LENGTH );
/* Initialize the response structure to recevie the HTTP server response */
returnStatus = az_http_response_init( &az_response, az_buffer );
if( returnStatus != AZ_OK )
{
/* Failure path */
}
/* HTTP Client handle for HTTP request send */
az_request._internal.context = handle;
az_request._internal.method = az_http_method_get();
az_request._internal.url._internal.ptr = ( uint8_t * )GET_PATH;
az_request._internal.url_length = strlen( GET_PATH );
/* Update the header */
az_request._internal.headers_length = 1;
az_header.name._internal.ptr = ( uint8_t * )"Connection";
az_header.name._internal.size = sizeof( "Connection" ) - 1;
az_header.value._internal.ptr = ( uint8_t * )"keep-alive";
az_header.value._internal.size = sizeof( "keep-alive" ) - 1;
az_request._internal.headers._internal.ptr = ( uint8_t * )&az_header;
az_request._internal.headers._internal.size = sizeof ( az_header ) * az_request._internal.headers_length;
az_request._internal.body._internal.ptr = ( uint8_t * )REQUEST_BODY;
az_request._internal.body._internal.size = REQUEST_BODY_LENGTH;
/* Azure SDK api to send HTTP client request and receive HTTP response */
returnStatus = az_http_client_send_request( &az_request, &az_response );
if( returnStatus != AZ_OK )
{
/* Failure path */
}
/* Disconnect the HTTP client from the server. */
result = cy_http_client_disconnect(handle);
if( result != CY_RSLT_SUCCESS )
{
/* Failure path */
}
/* Delete the instance of the HTTP client. */
result = cy_http_client_delete(handle);
if( result != CY_RSLT_SUCCESS )
{
/* Failure path */
}
/* Deinit the HTTP library. */
result = cy_http_client_deinit();
if( result != CY_RSLT_SUCCESS )
{
/* Failure path */
}
}

Code Snippet 2: Send a secure HTTP GET request to the server

Send a HTTP GET request (header + body) to the server and receive the response

/* HTTP Server configuration macros */
#define MAKE_IPV4_ADDRESS(a, b, c, d) ((((uint32_t) d) << 24) | \
(((uint32_t) c) << 16) | \
(((uint32_t) b) << 8) |\
((uint32_t) a))
#define SERVER_IP_ADDRESS MAKE_IPV4_ADDRESS(192, 168, 18, 9)
#define SERVER_HOST "httpbin.org"
#define SERVER_PORT 80
/* HTTP socket send and receive timeout */
#define TRANSPORT_SEND_RECV_TIMEOUT_MS ( 5000 )
/* URL to read the data */
#define GET_PATH "/get"
/* User buffer for HTTP request and response */
#define USER_BUFFER_LENGTH ( 2048 )
/* Request body in the HTTP header */
#define REQUEST_BODY "Hello, world!"
#define REQUEST_BODY_LENGTH ( sizeof( REQUEST_BODY ) - 1 )
/* Application buffer to hold the HTTP request and response */
static uint8_t userBuffer[ USER_BUFFER_LENGTH ];
/* SSL credentials information */
static cy_awsport_ssl_credentials_t credentials;
/* Information about the HTTP server */
static cy_awsport_server_info_t server_info;
/* HTTP client object used to send and recevie the requests */
static cy_http_client_t handle;
/* Azure SDK structure containing HTTP client request */
static az_http_request az_request;
/* Azure SDK structure containing HTTP client header */
static _az_http_request_header az_header;
/* Azure SDK structure containing HTTP client response */
static az_http_response az_response;
/* Configure the following credentials for a secure HTTP connection */
/* SSL server certificate */
#define SSL_SERVERCERT_PEM \
"-----BEGIN CERTIFICATE-----\n" \
"........base64 data........\n" \
"-----END CERTIFICATE-----"
/* SSL server private key */
#define SSL_SERVERKEY_PEM \
"-----BEGIN RSA PRIVATE KEY-----\n" \
"..........base64 data..........\n" \
"-----END RSA PRIVATE KEY-----"
#define SSL_ROOTCA_PEM \
"-----BEGIN CERTIFICATE-----\n" \
"........base64 data........\n" \
"-----END CERTIFICATE-----"
void snippet_secure_http_client_send(void)
{
/* Status variables for various operations */
cy_rslt_t result = CY_RSLT_SUCCESS;
az_result returnStatus;
/* User callback on disconnect */
cy_http_disconnect_callback_t http_cb;
( void ) memset( &credentials, 0, sizeof( credentials ) );
( void ) memset( &server_info, 0, sizeof( server_info ) );
/* Set the credential information */
credentials.client_cert = ( const char * ) &SSL_SERVERCERT_PEM;
credentials.client_cert_size = sizeof( SSL_SERVERCERT_PEM );
credentials.private_key = ( const char * ) &SSL_SERVERKEY_PEM;
credentials.private_key_size = sizeof( SSL_SERVERKEY_PEM );
credentials.root_ca = ( const char * ) &SSL_ROOTCA_PEM;
credentials.root_ca_size = sizeof( SSL_ROOTCA_PEM );
server_info.host_name = SERVER_HOST;
server_info.port = SERVER_PORT;
/* Initialize the HTTP client library */
result = cy_http_client_init();
if( result != CY_RSLT_SUCCESS )
{
/* Failure path */
}
/* HTTP disconnect callback */
http_cb = disconnect_callback;
/* Create an instance of the HTTP client */
result = cy_http_client_create( &credentials, &server_info, http_cb, NULL, &handle );
if( result != CY_RSLT_SUCCESS )
{
/* Failure path */
}
/* Connect the HTTP client to the server */
result = cy_http_client_connect( handle, TRANSPORT_SEND_RECV_TIMEOUT_MS, TRANSPORT_SEND_RECV_TIMEOUT_MS );
if( result != CY_RSLT_SUCCESS )
{
/* Failure path. */
}
/* Copy user buffer to Azure buffer structure for HTTP request handling */
az_span az_buffer = az_span_create( ( uint8_t* )userBuffer, ( int32_t )USER_BUFFER_LENGTH );
/* Initialize the response structure to recevie the HTTP server response */
returnStatus = az_http_response_init( &az_response, az_buffer );
if( returnStatus != AZ_OK )
{
/* Failure path */
}
/* HTTP Client handle for HTTP request send */
az_request._internal.context = handle;
az_request._internal.method = az_http_method_get();
az_request._internal.url._internal.ptr = ( uint8_t * )GET_PATH;
az_request._internal.url_length = strlen( GET_PATH );
/* Update the header */
az_request._internal.headers_length = 1;
az_header.name._internal.ptr = ( uint8_t * )"Connection";
az_header.name._internal.size = sizeof( "Connection" ) - 1;
az_header.value._internal.ptr = ( uint8_t * )"keep-alive";
az_header.value._internal.size = sizeof( "keep-alive" ) - 1;
az_request._internal.headers._internal.ptr = ( uint8_t * )&az_header;
az_request._internal.headers._internal.size = sizeof ( az_header ) * az_request._internal.headers_length;
az_request._internal.body._internal.ptr = ( uint8_t * )REQUEST_BODY;
az_request._internal.body._internal.size = REQUEST_BODY_LENGTH;
/* Azure SDK api to send HTTP client request and receive HTTP response */
returnStatus = az_http_client_send_request( &az_request, &az_response );
if( returnStatus != AZ_OK )
{
/* Failure path */
}
/* Disconnect the HTTP client from the server */
result = cy_http_client_disconnect(handle);
if( result != CY_RSLT_SUCCESS )
{
/* Failure path */
}
/* Delete the instance of the HTTP client */
result = cy_http_client_delete(handle);
if( result != CY_RSLT_SUCCESS )
{
/* Failure path */
}
/* Deinit the HTTP library */
result = cy_http_client_deinit();
if( result != CY_RSLT_SUCCESS )
{
/* Failure path */
}
}