static void dispatch_user_callbacks()

in iothub_client/src/iothub_client_core.c [668:866]


static void dispatch_user_callbacks(IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance, VECTOR_HANDLE call_backs)
{
    size_t callbacks_length = VECTOR_size(call_backs);
    size_t index;

    IOTHUB_CLIENT_DEVICE_TWIN_CALLBACK desired_state_callback = NULL;
    IOTHUB_CLIENT_CONNECTION_STATUS_CALLBACK connection_status_callback = NULL;
    IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC device_method_callback = NULL;
    IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK inbound_device_method_callback = NULL;
    IOTHUB_CLIENT_COMMAND_CALLBACK_ASYNC command_callback = NULL;
    IOTHUB_CLIENT_MESSAGE_CALLBACK_ASYNC message_callback = NULL;
    IOTHUB_CLIENT_CORE_HANDLE message_user_context_handle = NULL;
    IOTHUB_CLIENT_CORE_HANDLE method_user_context_handle = NULL;

    // Make a local copy of these callbacks, as we don't run with a lock held and iotHubClientInstance may change mid-run.
    if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK)
    {
        LogError("failed locking for dispatch_user_callbacks");
    }
    else
    {
        desired_state_callback = iotHubClientInstance->desired_state_callback;
        connection_status_callback = iotHubClientInstance->connection_status_callback;
        device_method_callback = iotHubClientInstance->device_method_callback;
        inbound_device_method_callback = iotHubClientInstance->inbound_device_method_callback;
        command_callback = iotHubClientInstance->command_callback;
        message_callback = iotHubClientInstance->message_callback;
        if (iotHubClientInstance->method_user_context)
        {
            method_user_context_handle = iotHubClientInstance->method_user_context->iotHubClientHandle;
        }
        if (iotHubClientInstance->message_user_context)
        {
            message_user_context_handle = iotHubClientInstance->message_user_context->iotHubClientHandle;
        }

        (void)Unlock(iotHubClientInstance->LockHandle);
    }


    for (index = 0; index < callbacks_length; index++)
    {
        USER_CALLBACK_INFO* queued_cb = (USER_CALLBACK_INFO*)VECTOR_element(call_backs, index);
        if (queued_cb == NULL)
        {
            LogError("VECTOR_element at index %zd is NULL.", index);
        }
        else
        {
            switch (queued_cb->type)
            {
            case CALLBACK_TYPE_DEVICE_TWIN:
            {
                // Callback if for GetTwinAsync
                if (queued_cb->iothub_callback.dev_twin_cb_info.userCallback)
                {
                    queued_cb->iothub_callback.dev_twin_cb_info.userCallback(
                        queued_cb->iothub_callback.dev_twin_cb_info.update_state,
                        queued_cb->iothub_callback.dev_twin_cb_info.payLoad,
                        queued_cb->iothub_callback.dev_twin_cb_info.size,
                        queued_cb->iothub_callback.dev_twin_cb_info.userContext
                    );
                }
                // Callback if for Desired properties.
                else if (desired_state_callback)
                {
                    desired_state_callback(queued_cb->iothub_callback.dev_twin_cb_info.update_state, queued_cb->iothub_callback.dev_twin_cb_info.payLoad, queued_cb->iothub_callback.dev_twin_cb_info.size, queued_cb->userContextCallback);
                }

                if (queued_cb->iothub_callback.dev_twin_cb_info.payLoad)
                {
                    free(queued_cb->iothub_callback.dev_twin_cb_info.payLoad);
                }
                break;
            }
            case CALLBACK_TYPE_EVENT_CONFIRM:
                if (queued_cb->iothub_callback.event_confirm_cb_info.eventConfirmationCallback)
                {
                    queued_cb->iothub_callback.event_confirm_cb_info.eventConfirmationCallback(queued_cb->iothub_callback.event_confirm_cb_info.confirm_result, queued_cb->userContextCallback);
                }
                break;
            case CALLBACK_TYPE_REPORTED_STATE:
                if (queued_cb->iothub_callback.reported_state_cb_info.reportedStateCallback)
                {
                    queued_cb->iothub_callback.reported_state_cb_info.reportedStateCallback(queued_cb->iothub_callback.reported_state_cb_info.status_code, queued_cb->userContextCallback);
                }
                break;
            case CALLBACK_TYPE_CONNECTION_STATUS:
                if (connection_status_callback)
                {
                    connection_status_callback(queued_cb->iothub_callback.connection_status_cb_info.connection_status, queued_cb->iothub_callback.connection_status_cb_info.status_reason, queued_cb->userContextCallback);
                }
                break;
            case CALLBACK_TYPE_DEVICE_METHOD:
                if (device_method_callback)
                {
                    const char* method_name = STRING_c_str(queued_cb->iothub_callback.method_cb_info.method_name);
                    const unsigned char* payload = BUFFER_u_char(queued_cb->iothub_callback.method_cb_info.payload);
                    size_t payload_len = BUFFER_length(queued_cb->iothub_callback.method_cb_info.payload);

                    unsigned char* payload_resp = NULL;
                    size_t response_size = 0;
                    int status = device_method_callback(method_name, payload, payload_len, &payload_resp, &response_size, queued_cb->userContextCallback);

                    if (payload_resp && (response_size > 0))
                    {
                        IOTHUB_CLIENT_RESULT result = IoTHubClientCore_DeviceMethodResponse(method_user_context_handle, queued_cb->iothub_callback.method_cb_info.method_id, (const unsigned char*)payload_resp, response_size, status);
                        if (result != IOTHUB_CLIENT_OK)
                        {
                            LogError("IoTHubClientCore_LL_DeviceMethodResponse failed");
                        }
                    }

                    BUFFER_delete(queued_cb->iothub_callback.method_cb_info.payload);
                    STRING_delete(queued_cb->iothub_callback.method_cb_info.method_name);

                    if (payload_resp)
                    {
                        free(payload_resp);
                    }
                }
                break;

            case CALLBACK_TYPE_COMMAND:
                if (command_callback)
                {
                    invoke_application_command_callback(method_user_context_handle, command_callback, queued_cb);
                }
                break;
                
            case CALLBACK_TYPE_INBOUND_DEVICE_METHOD:
                if (inbound_device_method_callback)
                {
                    const char* method_name = STRING_c_str(queued_cb->iothub_callback.method_cb_info.method_name);
                    const unsigned char* payload = BUFFER_u_char(queued_cb->iothub_callback.method_cb_info.payload);
                    size_t payload_len = BUFFER_length(queued_cb->iothub_callback.method_cb_info.payload);

                    inbound_device_method_callback(method_name, payload, payload_len, queued_cb->iothub_callback.method_cb_info.method_id, queued_cb->userContextCallback);

                    BUFFER_delete(queued_cb->iothub_callback.method_cb_info.payload);
                    STRING_delete(queued_cb->iothub_callback.method_cb_info.method_name);
                }
                break;
            case CALLBACK_TYPE_MESSAGE:
                if (message_callback && message_user_context_handle)
                {
                    IOTHUBMESSAGE_DISPOSITION_RESULT disposition = message_callback(queued_cb->iothub_callback.message_handle, queued_cb->userContextCallback);

                    if (disposition != IOTHUBMESSAGE_ASYNC_ACK)
                    {
                        if (Lock(message_user_context_handle->LockHandle) == LOCK_OK)
                        {
                            IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_SendMessageDisposition(message_user_context_handle->IoTHubClientLLHandle, queued_cb->iothub_callback.message_handle, disposition);
                            (void)Unlock(message_user_context_handle->LockHandle);
                            if (result != IOTHUB_CLIENT_OK)
                            {
                                LogError("IoTHubClientCore_LL_SendMessageDisposition failed");
                            }
                        }
                        else
                        {
                            LogError("Lock failed");
                        }
                    }
                }
                break;

            case CALLBACK_TYPE_INPUTMESSAGE:
                {
                    const INPUTMESSAGE_CALLBACK_INFO *inputmessage_cb_info = &queued_cb->iothub_callback.inputmessage_cb_info;
                    IOTHUBMESSAGE_DISPOSITION_RESULT disposition = inputmessage_cb_info->eventHandlerCallback(inputmessage_cb_info->message_handle, queued_cb->userContextCallback);

                    if (disposition != IOTHUBMESSAGE_ASYNC_ACK)
                    {
                        if (Lock(iotHubClientInstance->LockHandle) == LOCK_OK)
                        {
                            IOTHUB_CLIENT_RESULT result = IoTHubClientCore_LL_SendMessageDisposition(iotHubClientInstance->IoTHubClientLLHandle, inputmessage_cb_info->message_handle, disposition);
                            (void)Unlock(iotHubClientInstance->LockHandle);
                            if (result != IOTHUB_CLIENT_OK)
                            {
                                LogError("IoTHubClient_LL_SendMessageDisposition failed");
                            }
                        }
                        else
                        {
                            LogError("Lock failed");
                        }
                    }
                }
                break;

            default:
                LogError("Invalid callback type '%s'", MU_ENUM_TO_STRING(USER_CALLBACK_TYPE, queued_cb->type));
                break;
            }
        }
    }
    VECTOR_destroy(call_backs);
}