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);
}