MESSAGE_HANDLE message_clone()

in src/message.c [133:349]


MESSAGE_HANDLE message_clone(MESSAGE_HANDLE source_message)
{
    MESSAGE_HANDLE result;

    if (source_message == NULL)
    {
        /* Codes_SRS_MESSAGE_01_062: [If `source_message` is NULL, `message_clone` shall fail and return NULL.] */
        LogError("NULL source_message");
        result = NULL;
    }
    else
    {
        /* Codes_SRS_MESSAGE_01_003: [`message_clone` shall clone a message entirely and on success return a non-NULL handle to the cloned message.] */
        result = (MESSAGE_HANDLE)message_create();
        if (result == NULL)
        {
            /* Codes_SRS_MESSAGE_01_004: [If allocating memory for the new cloned message fails, `message_clone` shall fail and return NULL.] */
            LogError("Cannot clone message");
        }
        else
        {
            result->message_format = source_message->message_format;

            if (source_message->header != NULL)
            {
                /* Codes_SRS_MESSAGE_01_005: [If a header exists on the source message it shall be cloned by using `header_clone`.] */
                result->header = header_clone(source_message->header);
                if (result->header == NULL)
                {
                    /* Codes_SRS_MESSAGE_01_012: [ If any cloning operation for the members of the source message fails, then `message_clone` shall fail and return NULL. ]*/
                    LogError("Cannot clone message header");
                    message_destroy(result);
                    result = NULL;
                }
            }

            if ((result != NULL) && (source_message->delivery_annotations != NULL))
            {
                /* Codes_SRS_MESSAGE_01_006: [If delivery annotations exist on the source message they shall be cloned by using `annotations_clone`.] */
                result->delivery_annotations = annotations_clone(source_message->delivery_annotations);
                if (result->delivery_annotations == NULL)
                {
                    /* Codes_SRS_MESSAGE_01_012: [ If any cloning operation for the members of the source message fails, then `message_clone` shall fail and return NULL. ]*/
                    LogError("Cannot clone delivery annotations");
                    message_destroy(result);
                    result = NULL;
                }
            }

            if ((result != NULL) && (source_message->message_annotations != NULL))
            {
                /* Codes_SRS_MESSAGE_01_007: [If message annotations exist on the source message they shall be cloned by using `annotations_clone`.] */
                result->message_annotations = annotations_clone(source_message->message_annotations);
                if (result->message_annotations == NULL)
                {
                    /* Codes_SRS_MESSAGE_01_012: [ If any cloning operation for the members of the source message fails, then `message_clone` shall fail and return NULL. ]*/
                    LogError("Cannot clone message annotations");
                    message_destroy(result);
                    result = NULL;
                }
            }

            if ((result != NULL) && (source_message->properties != NULL))
            {
                /* Codes_SRS_MESSAGE_01_008: [If message properties exist on the source message they shall be cloned by using `properties_clone`.] */
                result->properties = properties_clone(source_message->properties);
                if (result->properties == NULL)
                {
                    /* Codes_SRS_MESSAGE_01_012: [ If any cloning operation for the members of the source message fails, then `message_clone` shall fail and return NULL. ]*/
                    LogError("Cannot clone message properties");
                    message_destroy(result);
                    result = NULL;
                }
            }

            if ((result != NULL) && (source_message->application_properties != NULL))
            {
                /* Codes_SRS_MESSAGE_01_009: [If application properties exist on the source message they shall be cloned by using `amqpvalue_clone`.] */
                result->application_properties = amqpvalue_clone(source_message->application_properties);
                if (result->application_properties == NULL)
                {
                    /* Codes_SRS_MESSAGE_01_012: [ If any cloning operation for the members of the source message fails, then `message_clone` shall fail and return NULL. ]*/
                    LogError("Cannot clone application annotations");
                    message_destroy(result);
                    result = NULL;
                }
            }

            if ((result != NULL) && (source_message->footer != NULL))
            {
                /* Codes_SRS_MESSAGE_01_010: [If a footer exists on the source message it shall be cloned by using `annotations_clone`.] */
                result->footer = amqpvalue_clone(source_message->footer);
                if (result->footer == NULL)
                {
                    /* Codes_SRS_MESSAGE_01_012: [ If any cloning operation for the members of the source message fails, then `message_clone` shall fail and return NULL. ]*/
                    LogError("Cannot clone message footer");
                    message_destroy(result);
                    result = NULL;
                }
            }

            if ((result != NULL) && (source_message->body_amqp_data_count > 0))
            {
                size_t calloc_size = safe_multiply_size_t(source_message->body_amqp_data_count, sizeof(BODY_AMQP_DATA));

                if (calloc_size == SIZE_MAX)
                {
                    LogError("Invalid size for body_amqp_data_items");
                    message_destroy(result);
                    result = NULL;
                }
                else
                {
                    result->body_amqp_data_items = (BODY_AMQP_DATA*)calloc(1, calloc_size);

                    if (result->body_amqp_data_items == NULL)
                    {
                        /* Codes_SRS_MESSAGE_01_012: [ If any cloning operation for the members of the source message fails, then `message_clone` shall fail and return NULL. ]*/
                        LogError("Cannot allocate memory for body data sections");
                        message_destroy(result);
                        result = NULL;
                    }
                    else
                    {
                        size_t i;

                        for (i = 0; i < source_message->body_amqp_data_count; i++)
                        {
                            result->body_amqp_data_items[i].body_data_section_length = source_message->body_amqp_data_items[i].body_data_section_length;

                            /* Codes_SRS_MESSAGE_01_011: [If an AMQP data has been set as message body on the source message it shall be cloned by allocating memory for the binary payload.] */
                            result->body_amqp_data_items[i].body_data_section_bytes = (unsigned char*)malloc(source_message->body_amqp_data_items[i].body_data_section_length);
                            if (result->body_amqp_data_items[i].body_data_section_bytes == NULL)
                            {
                                LogError("Cannot allocate memory for body data section %u", (unsigned int)i);
                                break;
                            }
                            else
                            {
                                (void)memcpy(result->body_amqp_data_items[i].body_data_section_bytes, source_message->body_amqp_data_items[i].body_data_section_bytes, result->body_amqp_data_items[i].body_data_section_length);
                            }
                        }

                        result->body_amqp_data_count = i;
                        if (i < source_message->body_amqp_data_count)
                        {
                            /* Codes_SRS_MESSAGE_01_012: [ If any cloning operation for the members of the source message fails, then `message_clone` shall fail and return NULL. ]*/
                            message_destroy(result);
                            result = NULL;
                        }
                    }
                }
            }

            if ((result != NULL) && (source_message->body_amqp_sequence_count > 0))
            {
                size_t calloc_size = safe_multiply_size_t(source_message->body_amqp_sequence_count, sizeof(AMQP_VALUE));

                if (calloc_size == SIZE_MAX)
                {
                    LogError("Invalid size for body_amqp_sequence_items");
                    message_destroy(result);
                    result = NULL;
                }
                else
                {
                    result->body_amqp_sequence_items = (AMQP_VALUE*)calloc(1, calloc_size);
                    if (result->body_amqp_sequence_items == NULL)
                    {
                        /* Codes_SRS_MESSAGE_01_012: [ If any cloning operation for the members of the source message fails, then `message_clone` shall fail and return NULL. ]*/
                        LogError("Cannot allocate memory for body AMQP sequences");
                        message_destroy(result);
                        result = NULL;
                    }
                    else
                    {
                        size_t i;

                        for (i = 0; i < source_message->body_amqp_sequence_count; i++)
                        {
                            /* Codes_SRS_MESSAGE_01_160: [ If AMQP sequences are set as AMQP body they shall be cloned by calling `amqpvalue_clone`. ] */
                            result->body_amqp_sequence_items[i] = amqpvalue_clone(source_message->body_amqp_sequence_items[i]);
                            if (result->body_amqp_sequence_items[i] == NULL)
                            {
                                LogError("Cannot clone AMQP sequence %u", (unsigned int)i);
                                break;
                            }
                        }

                        result->body_amqp_sequence_count = i;
                        if (i < source_message->body_amqp_sequence_count)
                        {
                            /* Codes_SRS_MESSAGE_01_012: [ If any cloning operation for the members of the source message fails, then `message_clone` shall fail and return NULL. ]*/
                            message_destroy(result);
                            result = NULL;
                        }
                    }
				}
            }

            if ((result != NULL) && (source_message->body_amqp_value != NULL))
            {
                /* Codes_SRS_MESSAGE_01_159: [If an AMQP value has been set as message body on the source message it shall be cloned by calling `amqpvalue_clone`. ]*/
                result->body_amqp_value = amqpvalue_clone(source_message->body_amqp_value);
                if (result->body_amqp_value == NULL)
                {
                    /* Codes_SRS_MESSAGE_01_012: [ If any cloning operation for the members of the source message fails, then `message_clone` shall fail and return NULL. ]*/
                    LogError("Cannot clone body AMQP value");
                    message_destroy(result);
                    result = NULL;
                }
            }
        }
    }

    return result;
}