/**
@mainpage
@anchor Fleet Provisioning
@brief Library for the fleet provisioning feature of AWS IoT.

> When you use AWS IoT fleet provisioning, AWS IoT can generate and securely deliver device certificates and private keys to your devices when they connect to AWS IoT for the first time.

<span style="float:right;margin-right:4em"> &mdash; <i>Description of the fleet provisioning feature from [AWS IoT documentation](https://docs.aws.amazon.com/iot/latest/developerguide/provision-wo-cert.html)</i></span><br>

This library provides an API based on the [Fleet Provisioning APIs available over MQTT](https://docs.aws.amazon.com/iot/latest/developerguide/provision-wo-cert.html#fleet-provision-api). Features of this library include:
- Synchronous API functions.
- User-defined callbacks for handling responses.

@dependencies{provisioning,Provisioning library}
@dot "Provisioning direct dependencies"
digraph provisioning_dependencies
{
    node[shape=box, fontname=Helvetica, fontsize=10, style=filled];
    edge[fontname=Helvetica, fontsize=10];
    subgraph
    {
        provisioning[label="Provisioning", fillcolor="#cc00ccff"];
        mqtt[label="MQTT", fillcolor="#cc00ccff", URL="@ref mqtt"];
    }
    subgraph
    {
        node[fillcolor="#aed8a9ff"];
        rank = same;
        static_memory[label="Static memory", URL="@ref static_memory"];
        logging[label="Logging", URL="@ref logging"];
    }
    provisioning -> mqtt;
    provisioning -> logging [label=" if logging enabled", style="dashed"];
    provisioning -> static_memory [label=" if static memory only", style="dashed"];
}
@enddot

Currently, the Provisioning library has the following dependencies:
- The MQTT library used to communicate with the AWS IoT Core service. See [this page](@ref mqtt) for more information on the MQTT library (and [its dependencies](@ref mqtt_dependencies))
- The static memory library will be used if the library is built with `IOT_STATIC_MEMORY_ONLY` flag set to `1`
- The logging library may be used if @ref AWS_IOT_LOG_LEVEL_PROVISIONING is not #IOT_LOG_NONE.

In addition to the components above, the Provisioning library also depends on C standard libraries.

@section provisioning_memory Memory requirements
@brief Memory requirements of the Provisioning library.

@subsection provisioning_memory_code Code size
@brief Code size of the Provisioning library.

The following measurements were taken with arm-none-eabi-gcc v9.2.1 (November 2019) with the [Provisioning library from April 2020](https://github.com/aws/aws-iot-device-sdk-embedded-C/commit/148d3fabcdc783885207b98da7a879aa7fedd30d). These values are rough estimates not tuned for any specific ARM processor.

(Also, refer to the [MQTT memory requirements](@ref mqtt_memory), which is a dependency of the Provisioning library.)

<b>Minimal Size Build</b> <br>
No logging, asserts, or diagnostic information. Compiled using the ARM Thumb instruction set (`-mthumb`) and optimized for size (`-Os`). Values are in <i>bytes</i>.

<table>
    <tr>
        <td><b>object</b></td>
        <td><b>text</b></td>
        <td><b>data</b></td>
        <td><b>bss</b></td>
    </tr>
    <tr>
        <td>aws_iot_provisioning_api</td>
        <td>1744</td>
        <td>4</td>
        <td>72</td>
    </tr>
    <tr>
        <td>aws_iot_provisioning_parser</td>
        <td>1542</td>
        <td>0</td>
        <td>0</td>
    </tr>
    <tr>
        <td>aws_iot_provisioning_serializer</td>
        <td>1278</td>
        <td>0</td>
        <td>0</td>
    </tr>
    <tr>
        <td><b>total</b></td>
        <td><b>4564</b></td>
        <td><b>4</b></td>
        <td><b>72</b></td>
    </tr>
</table>

<b>Debug Build</b> <br>
All logging, asserts, and diagnostic information enabled. Debugging symbols available (Compiled with `-Og -g` flags). Compiled using the ARM Thumb instruction set (`-mthumb`). Values are in <i>bytes</i>.

<table>
    <tr>
        <td><b>object</b></td>
        <td><b>text</b></td>
        <td><b>data</b></td>
        <td><b>bss</b></td>
    </tr>
    <tr>
        <td>aws_iot_provisioning_api</td>
        <td>5748</td>
        <td>4</td>
        <td>72</td>
    </tr>
    <tr>
        <td>aws_iot_provisioning_parser</td>
        <td>5431</td>
        <td>0</td>
        <td>0</td>
    </tr>
    <tr>
        <td>aws_iot_provisioning_serializer</td>
        <td>2692</td>
        <td>0</td>
        <td>0</td>
    </tr>
    <tr>
        <td><b>total</b></td>
        <td><b>13871</b></td>
        <td><b>4</b></td>
        <td><b>72</b></td>
    </tr>
</table>

*/

/**
@page provisioning_design Design
@brief Provisioning library architecture.

The Provisioning library uses MQTT publish/subscribe to interact with the AWS IoT Core service for the Fleet Provisioning feature. Each library operation ("CreateKeysAndCertificate", "CreateCertificateFromCsr", "RegisterThing") uses two MQTT subscriptions, one for the "accepted" topic and one for the "rejected" topic, to obtain the responses from AWS IoT Core, and publishes to the MQTT request topic of the operation. Each operation also requires a user-callback for handling the server response. The callbacks will run in the system taskpool context.

@section HighLevelOperation_Design High Level Design of a Provisioning Operation
@brief The following shows a high-level workflow of each library operation. The library uses the MQTT stack for communicating with AWS IoT and the serializer stack for serializing and de-serializing request and responses, respectively, from the server.  
@image html provisioning_operation_highlevel_design.png width=100%

@section DetailedOperation_Design Detailed Workflow Diagram of a Provisioning Operation
@brief The following shows the detailed workflow of each Provisioning operation. The Provisioning library architecture consists of 3 layers: API, serializer and parser, all of which are used for each Provisioning operation. The library uses an internal global state memory, separate for each operation type, that is shared between the Provisioning API and MQTT subscription callback layers. The global state represents the state of the operation and provides a synchronization mechanism between the Provisioning API and MQTT subscription callback layers.
@image html provisioning_operation_detailed_design.png width=100%

*/

/**
@page provisioning_demo Demo
@brief The demos demonstrate the usage of the Provisioning library for 2 different Provisioning workflows:
<ul>
<li> Provisioning when both keys and certificate are requested from AWS IoT. </li>
<li> Provisioning when device provides a Certificate-Signing Request to AWS IoT for certificate creation. </li>
</ul>
These demos represent simple examples of using the Provisioning library for provisioning devices with the AWS IoT Fleet Provisioning feature.

Both the demos establish an MQTT connection and make two API calls to the Fleet Provisioning feature of the AWS IoT Core service for illustrating their specific Provisioning workflow.
 
@section Demo_KeysAndCert Provisioning Demo with AWS IoT created Keys and certificate
@image html provisioning_demo_with_keys_and_cert.png "Provisioning Demo Workflow when keys are generated by AWS IoT" width=80%

@section Demo_Csr Provisioning Demo with Certificate-Signing Request
@image html provisioning_demo_with_csr.png "Provisioning Demo Workflow with Certificate-Signing Request" width=80%

@section provisioning_demo_setup Demo Setup
@brief How to set up a fleet provisioning template for the Provisioning demo.

The demo assumes a fleet provisioning template which takes parameters (including one for "SerialNumber") from the device has been created in the account that will be used for connecting to AWS IoT Core. 
To create a template, you can use the AWS IoT Console or AWS CLI. (For more information on fleet provisioning templates, refer [here](https://docs.aws.amazon.com/iot/latest/developerguide/provision-template.html). )

1. Create an IAM user for AWS CLI. See steps 1 @ref guide_developer_automated_tests_jobs_and_provisioning for more information.
2. Create an IAM role and attach a policy to the role. The role is required to create the provisioning template. (The provisioning template assumes the role for its runtime behavior.) See steps 2 and 3 in @ref provisioning_system_tests_setup for more information
3. Create a provisioning template for the demo. See step 4 in @ref provisioning_system_tests_setup for more information.
4. Build and run the demo as described [here](@ref building).

See @subpage provisioning_demo_config for configuration settings that change the behavior of the demo.

*/

/**
@configpage{provisioning_demo,Provisioning demo,Demo,demos}

@section AWS_IOT_DEMO_PROVISIONING_CSR_PEM
@brief The provisioning demo uses this Certificate-Signing Request data to demonstrate the CSR based provisioning use-case of fleet provisioning.

@configpossible The Certificate-Signing Request string in PEM format <br>
@configdefault `""` (empty string)

@section AWS_IOT_DEMO_PROVISIONING_TEMPLATE_NAME
@brief The provisioning demo uses this template to demonstrate the fleet provisioning feature.

@configpossible Any string <br>
@configdefault `""` (empty string)

@section AWS_IOT_DEMO_PROVISIONING_PARAMETER_SERIAL_NUMBER_NAME
@brief The name of the serial number parameter sent in the provisioning request.

The fleet provisioning template, `AWS_IOT_DEMO_PROVISIONING_TEMPLATE_NAME`, should be configured to accept the parameter. (The default template generated by AWS IoT Console uses "SerialNumber" to generate Thing resource name on provisioning device.)
It is recommended to use serial number (or an equivalent unique device identifier) to provide as parameter to the AWS IoT Core service for provisioning of the device.

@configpossible Any string that can be accepted by the template.<br>
@configdefault `"SerialNumber"`

@section AWS_IOT_DEMO_PROVISIONING_PARAMETER_SERIAL_NUMBER_NAME_LENGTH
@brief The length of the parameter associated with `AWS_IOT_DEMO_PROVISIONING_PARAMETER_SERIAL_NUMBER_NAME`.

@configdefault `sizeof( AWS_IOT_DEMO_PROVISIONING_PARAMETER_SERIAL_NUMBER_NAME ) - 1`<br>
@configrecommended Don't change the default value unless there is a need to use a different length.

@section AWS_IOT_DEMO_PROVISIONING_PARAMETER_SERIAL_NUMBER_VALUE
@brief The value of the parameter associated with `AWS_IOT_DEMO_PROVISIONING_PARAMETER_SERIAL_NUMBER_VALUE`.

@configpossible Any string value<br>
@configdefault `""` (empty string)

@section AWS_IOT_DEMO_PROVISIONING_PARAMETER_SERIAL_NUMBER_VALUE_LENGTH
@brief The length of the parameter associated with `AWS_IOT_DEMO_PROVISIONING_PARAMETER_SERIAL_NUMBER_NAME`.

@configdefault `sizeof( AWS_IOT_DEMO_PROVISIONING_PARAMETER_SERIAL_NUMBER_VALUE_LENGTH ) - 1`<br>
@configrecommended Don't change the default value unless there is a need to use a different length.

@section AWS_IOT_DEMO_PROVISIONING_PARAMETER_2_NAME
@brief The name of the additional parameter sent in the provisioning request.

An additional parameter can be sent to the AWS IoT Core service to utilize for _evaluating_ and sending back device configuration in the response. In that case, make sure that the fleet provisioning template is configured to accept the parameter.

@configpossible Any string that can be accepted by the template. <br>
@configdefault `""`

@section AWS_IOT_DEMO_PROVISIONING_PARAMETER_2_NAME_LENGTH
@brief The length of the parameter associated with `AWS_IOT_DEMO_PROVISIONING_PARAMETER_2_NAME_LENGTH_NAME`.

@configdefault `sizeof( AWS_IOT_DEMO_PROVISIONING_PARAMETER_2_NAME_LENGTH ) - 1`<br>
@configrecommended Don't change the default value unless there is a need to use a different length.

@section AWS_IOT_DEMO_PROVISIONING_PARAMETER_2_VALUE
@brief The value of the parameter associated with `AWS_IOT_DEMO_PROVISIONING_PARAMETER_2_NAME`.

@configpossible Any string value<br>
@configdefault `""` (empty string)

@section AWS_IOT_DEMO_PROVISIONING_PARAMETER_2_VALUE_LENGTH
@brief The length of the parameter associated with `AWS_IOT_DEMO_PROVISIONING_PARAMETER_2_NAME_LENGTH_VALUE`.

@configdefault `sizeof( AWS_IOT_DEMO_PROVISIONING_PARAMETER_2_VALUE_LENGTH ) - 1`<br>
@configrecommended Don't change the default value unless there is a need to use a different length.

*/

/**
@page provisioning_tests Tests
@brief Tests written for the Provisioning library.

The Provisioning tests reside in the `provisioning/test` directory. They are divided into the following subdirectories:
- `system`: Provisioning system tests. These tests require a network connection and AWS IoT credentials. They also need an AWS account and a registered Provisioning Template in the account; see @ref provisioning_system_tests_setup for instructions to configure an AWS account to run these tests. The command line option `-n` may be passed to the test executable to disable these tests.
- `unit`: Provisioning unit tests. These tests do not require a network connection or credentials. These tests use the [MQTT mocks.](@ref mqtt_tests)

See @subpage provisioning_tests_config for configuration settings that change the behavior of the Provisioning system tests. The Provisioning unit tests require no special configuration.

The current Provisioning tests use the [Unity test framework](http://www.throwtheswitch.org/unity/). See @ref building_tests for a guide on running the tests.

@section provisioning_system_tests_setup Setting up Provisioning system tests
@brief How to set up the Provisioning system tests.

@pre The steps below assume basic familiarity with AWS and AWS CLI.

The Provisioning system tests require a Provisioning Template to be created with an AWS account. AWS does not provide the functionality to create a fleet provisioning template using the Device API; therefore, a fleet provisioning template will have to be created using another method.

See @ref guide_developer_automated_tests_jobs_and_provisioning for additional setup for running the Provisioning tests on Travis CI.

1. Create an IAM user for the tests. This needs to be done only once. <br>
Follow [this guide](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_users_create.html) to create an IAM user for the Provisioning tests.
    - Only <b>programmatic access</b> is required.
    - Save the <b>access key</b> and <b>secret access key</b> for this user.
    - The following policy grants the necessary permissions for this user. Replace `<region>` and `<account>` with your AWS region and account number, respectively; replace `<TemplateName>` with the name of the Provisioning Template that will be created in the next step (step 2).<br>
@code
{
    "Version": "2012-10-17",
    "Statement": {
        "Effect": "Allow",
        "Action": [
            "iot:CreateProvisioningTemplate",
            "iot:UpdateProvisioningTemplate",
            "iot:DescribeProvisioningTemplate",
            "iot:DeleteProvisioningTemplate",
            "iot:ListProvisioningTemplates"
        ],
        "Resource": [
            "arn:aws:iot:<region>:<account>:provisioningtemplate/*",
            "arn:aws:iot:<region>:<account>:service-role/*"
        ]
    }
}
@endcode

2. Create an IAM role that will be needed by a fleet provisioning template. Replace `RoleName` with a name of the role you want to create.
@code{sh}
aws iam create-role \
    --role-name <RoleName> \
    --assume-role-policy-document '{"Version":"2012-10-17","Statement":[{"Action":"sts:AssumeRole","Effect":"Allow","Principal":{"Service":"iot.amazonaws.com"}}]}'
@endcode

3. Attach a policy to the role created in step2. Replace `RoleName` with the name of the role you created in Step 2. 
@code{sh}
aws iam attach-role-policy \
        --role-name <RoleName> \
        --policy-arn arn:aws:iam::aws:policy/service-role/AWSIoTThingsRegistration
@endcode

4. Create the template resource which will be used for provisioning the demo application. This needs to be done only once. <br>
To create a template, the following AWS CLI command may be used. Replace `TemplateName` with the name of the fleet provisioning template you want to create. Replace `RoleName` with the name of the role you created in Step 2. Replace `TemplateJSON` with the template body as a JSON string (containing escape characters). Replace `account` with your AWS account number.
@code{sh}
aws iot create-provisioning-template \
        --template-name <TemplateName> \
        --provisioning-role-arn arn:aws:iam::<account>:service-role/<RoleName> \
        --template-body "<TemplateJSON>" \
        --enabled 
@endcode
For more information on fleet provisioning template, refer to [this guide](https://docs.aws.amazon.com/iot/latest/developerguide/provision-template.html#fleet-provision-template)
Following is an example template JSON string (that uses "SerialNumber" for Thing resource name and accepts an additional "DeviceLocation" parameter) which can be viewed on AWS IoT Console after the AWS CLI command using it is executed <br>
```
{\"Parameters\":{\"DeviceLocation\":{\"Type\":\"String\"},\"AWS::IoT::Certificate::Id\":{\"Type\":\"String\"},\"SerialNumber\":{\"Type\":\"String\"}},\"Mappings\":{\"LocationTable\":{\"Seattle\":{\"LocationUrl\":\"https://example.aws\"}}},\"Resources\":{\"thing\":{\"Type\":\"AWS::IoT::Thing\",\"Properties\":{\"ThingName\":{\"Fn::Join\":[\"\",[\"ThingPrefix_\",{\"Ref\":\"SerialNumber\"}]]},\"AttributePayload\":{\"version\":\"v1\",\"serialNumber\":\"serialNumber\"}},\"OverrideSettings\":{\"AttributePayload\":\"MERGE\",\"ThingTypeName\":\"REPLACE\",\"ThingGroups\":\"DO_NOTHING\"}},\"certificate\":{\"Type\":\"AWS::IoT::Certificate\",\"Properties\":{\"CertificateId\":{\"Ref\":\"AWS::IoT::Certificate::Id\"},\"Status\":\"Active\"},\"OverrideSettings\":{\"Status\":\"REPLACE\"}},\"policy\":{\"Type\":\"AWS::IoT::Policy\",\"Properties\":{\"PolicyDocument\":{\"Version\":\"2012-10-17\",\"Statement\":[{\"Effect\":\"Allow\",\"Action\":[\"iot:Connect\",\"iot:Subscribe\",\"iot:Publish\",\"iot:Receive\"],\"Resource\":\"*\"}]}}}},\"DeviceConfiguration\":{\"FallbackUrl\":\"https://www.example.com/test-site\",\"LocationUrl\":{\"Fn::FindInMap\":[\"LocationTable\",{\"Ref\":\"DeviceLocation\"},\"LocationUrl\"]}}}
```
You can query the created template using the following CLI command. Replace the `TemplateName` with the fleet provisioning template you created.
@code{sh}
aws iot describe-provisioning-template --template-name <TemplateName>
@endcode

5. Set the name of provisioning template, created in step 4, in the config file for the `AWS_IOT_TEST_PROVISIONING_TEMPLATE_NAME` macro. Build the tests for the `aws_iot_tests_provisioning` target.<br>

6. When the Provisioning tests are complete, the provisioning template it used is no longer needed. Provisioning templates can be deleted with the following command, where `TemplateName` is the name of the template that is to be deleted. Replace the `<TemplateName>` with the name of the provisioning template created in Step 4.
@code{sh}
aws iot delete-provisioning-template --template-name <TemplateName> 
@endcode
*/

/**
@configpage{provisioning_tests,Provisioning system tests,Test,tests}

@section AWS_IOT_TEST_PROVISIONING_TEMPLATE_NAME
@brief The Template name to use in the Provisioning system tests.

Provisioning Templates are used to facilitate provisioning of devices with AWS IoT Core. <b>No default value is provided for Template Names, so this constant must be defined.</b> In addition to the Template Name, AWS IoT credentials ([root CA certificate](@ref IOT_TEST_ROOT_CA), [client certificate](@ref IOT_TEST_CLIENT_CERT), and [client certificate private key](@ref IOT_TEST_PRIVATE_KEY)) must be provided to run the system tests. The [AWS IoT policy](https://docs.aws.amazon.com/iot/latest/developerguide/iot-policies.html) must also be properly configured.

@configpossible A string representing an AWS IoT Fleet Provisioning Template Name.

@section AWS_IOT_TEST_PROVISIONING_TEMPLATE_PARAMETERS
@brief The list of parameters to pass as device context in the Provisioning system tests.

Template parameters are used to provide context of the device requesting provisioning. 

@configpossible A C-style list initialization of parameters.<br>
@configrecommended A "SerialNumber" parameter is required by the default Provisioning Template, that is created by the AWS IoT Console, to create a Thing resource. It should also include other parameter name-value pairs that are needed by the Provisioning Template.<br>
@configdefault A "SerialNumber" parameter name without the value. The parameter value should to be specified.
@code{c}
    {                                                           \
        {                                                       \
            .pParameterKey = "SerialNumber",                    \
            .parameterKeyLength = sizeof( "SerialNumber" ) - 1, \
            .pParameterValue = "",                              \
            .parameterValueLength = 0                           \
        }                                                       \
    }
@endcode

*/

/**
@configpage{provisioning,Provisioning library}

@section AWS_IOT_PROVISIONING_ENABLE_ASSERTS
@brief Set this to `1` to perform sanity checks when using the Provisioning library.

Asserts are useful for debugging, but should be disabled in production code. If this is set to `1`, @ref AwsIotProvisioning_Assert can be defined to set the assertion function; otherwise, the @ref Iot_DefaultAssert will be used.

@configpossible `0` (asserts disabled) or `1` (asserts enabled)<br>
@configrecommended `1` when debugging; `0` in production code.<br>
@configdefault `0`

@section AWS_IOT_PROVISIONING_DEFAULT_MQTT_TIMEOUT_MS
@brief Set the default timeout (in milliseconds) for [MQTT library](@ref mqtt_functions) called by the Provisioning library.

If the `mqttTimeout` argument of @ref provisioning_function_init is `0`, the Provisioning library uses this setting for MQTT timeouts. This timeout is passed to functions such as @ref mqtt_function_subscribesync, and @ref mqtt_function_publishsync to limit amount of time an MQTT function may block.

@configpossible Any positive integer.<br>
@configrecommended This setting must be at least the network round-trip time, as an MQTT packet must be sent to the AWS IoT server and a response must be received. The recommended minimum value is `500`.<br>
@configdefault `5000`

@section AWS_IOT_LOG_LEVEL_PROVISIONING
@brief Set the log level of the Provisioning library.

Log messages from the Provisioning library at or below this setting will be printed.

@configpossible One of the @ref logging_constants_levels.<br>
@configdefault @ref IOT_LOG_LEVEL_GLOBAL; if that is undefined, then #IOT_LOG_NONE.

@section AwsIotProvisioning_Assert
@brief Assertion function used when @ref AWS_IOT_PROVISIONING_ENABLE_ASSERTS is `1`.

@configpossible Any function with the same signature as the standard library's [assert](http://pubs.opengroup.org/onlinepubs/9699919799/functions/assert.html) function.<br>
@configdefault @ref Iot_DefaultAssert if @ref AWS_IOT_PROVISIONING_ENABLE_ASSERTS is `1`; otherwise, nothing. If @ref Iot_DefaultAssert is not defined when asserts are enabled, the Provisioning library will fail to build.

@section provisioning_config_memory Memory allocation
@brief The following functions may be re-implemented for the Provisioning library.
- #AwsIotProvisioning_MallocPayload <br>
  @copybrief AwsIotProvisioning_MallocPayload
- #AwsIotProvisioning_FreePayload <br>
  @copybrief AwsIotProvisioning_FreePayload
- #AwsIotProvisioning_MallocString <br>
  @copybrief AwsIotProvisioning_MallocString
- #AwsIotProvisioning_FreeString <br>
  @copybrief AwsIotProvisioning_FreeString
- #AwsIotProvisioning_MallocDeviceConfigurationList <br>
  @copybrief AwsIotProvisioning_MallocDeviceConfigurationList
- #AwsIotProvisioning_FreeDeviceConfigurationList <br>
  @copybrief AwsIotProvisioning_FreeDeviceConfigurationList

If a custom implementation is not set for a Provisioning memory allocation function, @ref Iot_DefaultMalloc will be used. If @ref Iot_DefaultMalloc are not set, the Provisioning library will fail to build.
*/
