/*
 * Copyright (c) 2015, 2016, Oracle and/or its affiliates. All rights reserved.
 *
 * This software is dual-licensed to you under the MIT License (MIT) and
 * the Universal Permissive License (UPL). See the LICENSE file in the root
 * directory for license terms. You may choose either license, or both.
 */


/**
 * @brief Common private header
 */

#ifndef UTIL_BUFFER_H
#define UTIL_BUFFER_H

#ifdef __cplusplus
extern "C" {
#endif

    /*
     * 2560 bytes
     */
#define UTIL_GET_TOKEN_HEADER_LENGTH 128
    /* {
     * "\"iss\":\"%s\"" (s of length IOTCS_CLIENT_ID_BUFFER_LENGTH)
     * ", \"sub\":\"%s\"" (s of length IOTCS_CLIENT_ID_BUFFER_LENGTH)
     * ", \"aud\":\"oracle/iot/oauth2/token\""
     * ", \"exp\":%ld" (Timestamp value of length 10)
     * "}"*/
#define UTIL_GET_TOKEN_CLAIMS_LENGTH (67 + (2 * IOTCS_CLIENT_ID_BUFFER_LENGTH))
#define UTIL_GET_TOKEN_SIGNATURE_LENGTH (512 + (2 * IOTCS_CLIENT_ID_BUFFER_LENGTH))
#define UTIL_GET_TOKEN_B64_STRING_LENGTH (256 + (2 * IOTCS_CLIENT_ID_BUFFER_LENGTH))
#define UTIL_GET_TOKEN_SIGNATURE_STRING_LENGTH (512 + (2 * IOTCS_CLIENT_ID_BUFFER_LENGTH))
#define UTIL_GET_TOKEN_ASSERTION_LENGTH (1024 + (2 * IOTCS_CLIENT_ID_BUFFER_LENGTH))

    /*
     * 3840 bytes
     */
#define UTIL_ACTIVATION_SIGNATURE_LENGTH 512
#define UTIL_ACTIVATION_SIGNATURE_STRING_LENGTH 512
#define UTIL_ACTIVATION_CONTENT_LENGTH 256
#define UTIL_ACTIVATION_HASH_CODE_LENGTH 512
#define UTIL_ACTIVATION_PUBLIC_KEY_STR_LENGTH 512
#define UTIL_ACTIVATION_DIGEST_LENGTH 512
#define UTIL_ACTIVATION_DM_STR_LENGTH 1024

    /*
     Uses for storing messages payload.
     */
#ifndef IOTCS_PAYLOAD_BUFFER_SIZE
#define IOTCS_PAYLOAD_BUFFER_SIZE 4096
#endif


    /*
     * Buffer is used for MQTT frames. NOTE: Publish frames doesn't contain a payload,
     * the payload is written to socket from payload buffer directly.
     * 700 bytes is enough for all typical MQTT frames among which the longest one
     * is "Connect" that takes about 520 bytes.
     */
#ifndef IOTCS_MQTT_SEND_BUFFER_SIZE
#define IOTCS_MQTT_SEND_BUFFER_SIZE 700
#endif

#define UTIL_HTTP_HEADER_BUFFER_SIZE (sizeof(((util_shared_buffers_t*)0)->messaging.http_header_union))
#define UTIL_PAYLOAD_BUFFER_SIZE (sizeof(((util_shared_buffers_t*)0)->messaging.payload_union))

#ifdef IOTCS_LONG_POLLING 
#ifndef IOTCS_LONG_POLLING_BUFFER_SIZE
#define IOTCS_LONG_POLLING_BUFFER_SIZE 4700
#endif
#endif

#define UTIL_RESPONSE_BUFFER_LENGTH (sizeof(util_shared_buffers_t))
#define UTIL_READ_TAS_BUFFER_LENGTH (UTIL_RESPONSE_BUFFER_LENGTH/2)
#define UTIL_LP_RESPONSE_SIZE (sizeof(util_long_polling_buffers_t))

#define UTIL_REST_API_URL_MAX_LENGTH 256
#define UTIL_INDIRECT_ACTIVATION_DM_STR_LENGTH 1024
#define UTIL_INDIRECT_ACTIVATION_BODY_LENGTH 1024

#define UTIL_TOKEN_MAX_LENGTH 33 //currently uses MD5 (16 bytes encoded as hex) for token => 32 + "/0"
    /*
     strlen("Bearer ") = 7
     */
#define UTIL_BEARER_LENGTH 7
#define UTIL_TOKEN_STRING_MAX_LENGTH (UTIL_BEARER_LENGTH + UTIL_TOKEN_MAX_LENGTH)

    typedef union {
        char http_response_buffer[0]; /* the exact available size is defined by the rest of the union */

        /*
         * Uses for sending messages to server. If something was stored in messaging_buffers.messaging then
         * you shouldn't use other parts of union until message will be sent.
         */
        struct {
            char url_buffer[UTIL_REST_API_URL_MAX_LENGTH];
#ifndef IOTCS_DISABLE_MQTT
            char paho_send_buffer[IOTCS_MQTT_SEND_BUFFER_SIZE];
#endif

            union {
                char http_header_buffer[0];
                char get_token_assertion[UTIL_GET_TOKEN_ASSERTION_LENGTH];

                struct {
                    char signature_string[UTIL_ACTIVATION_SIGNATURE_STRING_LENGTH];
                    char public_key_string[UTIL_ACTIVATION_PUBLIC_KEY_STR_LENGTH];
                    char device_models_str[UTIL_ACTIVATION_DM_STR_LENGTH];
                } activation;

                struct {
                    char device_models_str[UTIL_INDIRECT_ACTIVATION_DM_STR_LENGTH];
                    char signature_string[UTIL_ACTIVATION_SIGNATURE_STRING_LENGTH];
                    char signature[UTIL_ACTIVATION_SIGNATURE_STRING_LENGTH];

                } indirect_activation;
            } http_header_union;

            union {
                char payload_buffer[IOTCS_PAYLOAD_BUFFER_SIZE];

                /*
                 * Uses for generation of the get_token request.
                 */
                struct {
                    char header[UTIL_GET_TOKEN_HEADER_LENGTH];
                    char claims[UTIL_GET_TOKEN_CLAIMS_LENGTH];
                    char signature[UTIL_GET_TOKEN_SIGNATURE_LENGTH];
                    char base64_string[UTIL_GET_TOKEN_B64_STRING_LENGTH];
                    char signature_string[UTIL_GET_TOKEN_SIGNATURE_STRING_LENGTH];
                } get_token;

                /*
                 * Uses for generation of the activation request.
                 */
                struct {
                    char signature[UTIL_ACTIVATION_SIGNATURE_LENGTH];
                    char content[UTIL_ACTIVATION_CONTENT_LENGTH];
                    char hash_code[UTIL_ACTIVATION_HASH_CODE_LENGTH];
                    char digest[UTIL_ACTIVATION_DIGEST_LENGTH];
                } activation;
            } payload_union;
        } messaging;
    } util_shared_buffers_t;

#ifdef IOTCS_LONG_POLLING 

typedef union {
        char response_buffer[0]; /* the exact available size is defined by the rest of the union */

        /*
         * Uses for sending messages to server during long polling receive.
         */
        struct lp_messaging {
            char payload_buffer[IOTCS_LONG_POLLING_BUFFER_SIZE];
            char url_buffer[UTIL_REST_API_URL_MAX_LENGTH];
        } lp_messaging;
    } util_long_polling_buffers_t;
#endif

    /*messaging*/
    char* util_get_payload_buffer(void);
    char* util_get_response_buffer(void);
    char* util_get_url_buffer(void);
#ifndef IOTCS_DISABLE_HTTP
    char* util_get_http_header_buffer(void);
#endif
#ifndef IOTCS_DISABLE_MQTT
    char* util_get_mqtt_send_buffer(void);
    char* util_get_mqtt_receive_buffer(void);
#endif

    /*indirect activation*/
    char* util_get_indirect_activation_device_models_buffer(void);
    char* util_get_indirect_activation_signature_buffer(void);
    char* util_get_indirect_activation_signature_string_buffer(void);

    /*get token*/
    char* util_get_token_header_buffer(void);
    char* util_get_token_claims_buffer(void);
    char* util_get_token_signature_buffer(void);
    char* util_get_token_base64_string_buffer(void);
    char* util_get_token_signature_string_buffer(void);
    char* util_get_token_assertion_buffer(void);

    /*activation*/
    char* util_get_activation_signature_buffer(void);
    char* util_get_activation_signature_string_buffer(void);
    char* util_get_activation_content_buffer(void);
    char* util_get_activation_device_models_str_buffer(void);
    char* util_get_activation_hash_code_buffer(void);
    char* util_get_activation_public_key_string_buffer(void);
    char* util_get_activation_digest_buffer(void);

    /*load tam*/
    unsigned char* util_get_load_tam_decrypted_buffer(void);
    unsigned char* util_get_load_tam_encrypted_buffer(void);

#ifdef IOTCS_LONG_POLLING 
    char* util_get_payload_buffer_lp(void);
    char* util_get_url_buffer_lp(void);
    char* util_get_response_buffer_lp(void);
#endif

#ifdef __cplusplus
}
#endif

#endif /* UTIL_BUFFER_H */

