diff --git a/iothub_client/src/iothub_client_core.c b/iothub_client/src/iothub_client_core.c index d40dbf1191..ff8aa98726 100644 --- a/iothub_client/src/iothub_client_core.c +++ b/iothub_client/src/iothub_client_core.c @@ -1991,9 +1991,39 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_GetTwinAsync(IOTHUB_CLIENT_CORE_HANDLE iot return result; } +static void freeDeviceMethodContext(IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance) +{ + if (iotHubClientInstance->method_user_context) + { + free(iotHubClientInstance->method_user_context); + iotHubClientInstance->method_user_context = NULL; + } +} + +static IOTHUB_CLIENT_RESULT allocateQueueContextForMethodCallback(IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance, void* userContextCallback) +{ + IOTHUB_CLIENT_RESULT result; + + iotHubClientInstance->method_user_context = (IOTHUB_QUEUE_CONTEXT*)malloc(sizeof(IOTHUB_QUEUE_CONTEXT)); + if (iotHubClientInstance->method_user_context == NULL) + { + LogError("Failed allocating QUEUE_CONTEXT"); + result = IOTHUB_CLIENT_ERROR; + } + else + { + iotHubClientInstance->method_user_context->iotHubClientHandle = (IOTHUB_CLIENT_CORE_HANDLE)iotHubClientInstance; + iotHubClientInstance->method_user_context->userContextCallback = userContextCallback; + result = IOTHUB_CLIENT_OK; + } + + return result; +} + IOTHUB_CLIENT_RESULT IoTHubClientCore_SetDeviceMethodCallback(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC deviceMethodCallback, void* userContextCallback) { IOTHUB_CLIENT_RESULT result; + IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_CORE_INSTANCE*)iotHubClientHandle; /*Codes_SRS_IOTHUBCLIENT_12_012: [ If iotHubClientHandle is NULL, IoTHubClient_SetDeviceMethodCallback shall return IOTHUB_CLIENT_INVALID_ARG. ]*/ if (iotHubClientHandle == NULL) @@ -2001,82 +2031,55 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_SetDeviceMethodCallback(IOTHUB_CLIENT_CORE result = IOTHUB_CLIENT_INVALID_ARG; LogError("invalid arg (NULL)"); } + /*Codes_SRS_IOTHUBCLIENT_12_014: [ If the transport handle is null and the worker thread is not initialized, the thread shall be started by calling IoTHubTransport_StartWorkerThread. ]*/ + else if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK) + { + /*Codes_SRS_IOTHUBCLIENT_12_015: [ If starting the thread fails, IoTHubClient_SetDeviceMethodCallback shall return IOTHUB_CLIENT_ERROR. ]*/ + result = IOTHUB_CLIENT_ERROR; + LogError("Could not start worker thread"); + } + /*Codes_SRS_IOTHUBCLIENT_12_018: [ IoTHubClient_SetDeviceMethodCallback shall be made thread-safe by using the lock created in IoTHubClient_Create. ]*/ + else if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK) + { + /*Codes_SRS_IOTHUBCLIENT_12_013: [ If acquiring the lock fails, IoTHubClient_SetDeviceMethodCallback shall return IOTHUB_CLIENT_ERROR. ]*/ + result = IOTHUB_CLIENT_ERROR; + LogError("Could not acquire lock"); + } else { - IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_CORE_INSTANCE*)iotHubClientHandle; - - /*Codes_SRS_IOTHUBCLIENT_12_014: [ If the transport handle is null and the worker thread is not initialized, the thread shall be started by calling IoTHubTransport_StartWorkerThread. ]*/ - if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK) + freeDeviceMethodContext(iotHubClientInstance); + if (deviceMethodCallback == NULL) { - /*Codes_SRS_IOTHUBCLIENT_12_015: [ If starting the thread fails, IoTHubClient_SetDeviceMethodCallback shall return IOTHUB_CLIENT_ERROR. ]*/ - result = IOTHUB_CLIENT_ERROR; - LogError("Could not start worker thread"); + result = IoTHubClientCore_LL_SetDeviceMethodCallback_Ex(iotHubClientInstance->IoTHubClientLLHandle, NULL, NULL); } else { - /*Codes_SRS_IOTHUBCLIENT_12_018: [ IoTHubClient_SetDeviceMethodCallback shall be made thread-safe by using the lock created in IoTHubClient_Create. ]*/ - if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK) + if ((result = allocateQueueContextForMethodCallback(iotHubClientInstance, userContextCallback)) != IOTHUB_CLIENT_OK) { - /*Codes_SRS_IOTHUBCLIENT_12_013: [ If acquiring the lock fails, IoTHubClient_SetDeviceMethodCallback shall return IOTHUB_CLIENT_ERROR. ]*/ - result = IOTHUB_CLIENT_ERROR; - LogError("Could not acquire lock"); + ; + } + /*Codes_SRS_IOTHUBCLIENT_12_016: [ IoTHubClient_SetDeviceMethodCallback shall call IoTHubClientCore_LL_SetDeviceMethodCallback, while passing the IoTHubClientCore_LL_handle created by IoTHubClientCore_LL_Create along with the parameters deviceMethodCallback and userContextCallback. ]*/ + /*Codes_SRS_IOTHUBCLIENT_12_017: [ When IoTHubClientCore_LL_SetDeviceMethodCallback is called, IoTHubClient_SetDeviceMethodCallback shall return the result of IoTHubClientCore_LL_SetDeviceMethodCallback. ]*/ + else if ((result = IoTHubClientCore_LL_SetDeviceMethodCallback_Ex(iotHubClientInstance->IoTHubClientLLHandle, iothub_ll_device_method_callback, iotHubClientInstance->method_user_context)) != IOTHUB_CLIENT_OK) + { + LogError("IoTHubClientCore_LL_SetDeviceMethodCallback_Ex failed"); + freeDeviceMethodContext(iotHubClientInstance); } else { - if (iotHubClientInstance->created_with_transport_handle == 0) - { - iotHubClientInstance->device_method_callback = deviceMethodCallback; - } - - if (iotHubClientInstance->method_user_context) - { - free(iotHubClientInstance->method_user_context); - iotHubClientInstance->method_user_context = NULL; - } - if (deviceMethodCallback == NULL) - { - result = IoTHubClientCore_LL_SetDeviceMethodCallback_Ex(iotHubClientInstance->IoTHubClientLLHandle, NULL, NULL); - } - else - { - iotHubClientInstance->method_user_context = (IOTHUB_QUEUE_CONTEXT*)malloc(sizeof(IOTHUB_QUEUE_CONTEXT)); - if (iotHubClientInstance->method_user_context == NULL) - { - result = IOTHUB_CLIENT_ERROR; - LogError("Failed allocating QUEUE_CONTEXT"); - } - else - { - iotHubClientInstance->method_user_context->iotHubClientHandle = iotHubClientHandle; - iotHubClientInstance->method_user_context->userContextCallback = userContextCallback; - - /*Codes_SRS_IOTHUBCLIENT_12_016: [ IoTHubClient_SetDeviceMethodCallback shall call IoTHubClientCore_LL_SetDeviceMethodCallback, while passing the IoTHubClientCore_LL_handle created by IoTHubClientCore_LL_Create along with the parameters deviceMethodCallback and userContextCallback. ]*/ - /*Codes_SRS_IOTHUBCLIENT_12_017: [ When IoTHubClientCore_LL_SetDeviceMethodCallback is called, IoTHubClient_SetDeviceMethodCallback shall return the result of IoTHubClientCore_LL_SetDeviceMethodCallback. ]*/ - result = IoTHubClientCore_LL_SetDeviceMethodCallback_Ex(iotHubClientInstance->IoTHubClientLLHandle, iothub_ll_device_method_callback, iotHubClientInstance->method_user_context); - if (result != IOTHUB_CLIENT_OK) - { - LogError("IoTHubClientCore_LL_SetDeviceMethodCallback_Ex failed"); - free(iotHubClientInstance->method_user_context); - iotHubClientInstance->method_user_context = NULL; - } - else - { - iotHubClientInstance->device_method_callback = deviceMethodCallback; - } - } - } - - (void)Unlock(iotHubClientInstance->LockHandle); + iotHubClientInstance->device_method_callback = deviceMethodCallback; } - } + (void)Unlock(iotHubClientInstance->LockHandle); } + return result; } IOTHUB_CLIENT_RESULT IoTHubClientCore_SetDeviceMethodCallback_Ex(IOTHUB_CLIENT_CORE_HANDLE iotHubClientHandle, IOTHUB_CLIENT_INBOUND_DEVICE_METHOD_CALLBACK inboundDeviceMethodCallback, void* userContextCallback) { IOTHUB_CLIENT_RESULT result; + IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_CORE_INSTANCE*)iotHubClientHandle; /*Codes_SRS_IOTHUBCLIENT_07_001: [ If iotHubClientHandle is NULL, IoTHubClient_SetDeviceMethodCallback_Ex shall return IOTHUB_CLIENT_INVALID_ARG. ]*/ if (iotHubClientHandle == NULL) @@ -2084,76 +2087,49 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_SetDeviceMethodCallback_Ex(IOTHUB_CLIENT_C result = IOTHUB_CLIENT_INVALID_ARG; LogError("invalid arg (NULL)"); } + /*Codes_SRS_IOTHUBCLIENT_07_003: [ If the transport handle is NULL and the worker thread is not initialized, the thread shall be started by calling IoTHubTransport_StartWorkerThread. ]*/ + else if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK) + { + /*Codes_SRS_IOTHUBCLIENT_07_004: [ If starting the thread fails, IoTHubClient_SetDeviceMethodCallback_Ex shall return IOTHUB_CLIENT_ERROR. ]*/ + result = IOTHUB_CLIENT_ERROR; + LogError("Could not start worker thread"); + } + else if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK) + { + /*Codes_SRS_IOTHUBCLIENT_07_002: [ If acquiring the lock fails, IoTHubClient_SetDeviceMethodCallback_Ex shall return IOTHUB_CLIENT_ERROR. ]*/ + result = IOTHUB_CLIENT_ERROR; + LogError("Could not acquire lock"); + } else { - IOTHUB_CLIENT_CORE_INSTANCE* iotHubClientInstance = (IOTHUB_CLIENT_CORE_INSTANCE*)iotHubClientHandle; - - /*Codes_SRS_IOTHUBCLIENT_07_003: [ If the transport handle is NULL and the worker thread is not initialized, the thread shall be started by calling IoTHubTransport_StartWorkerThread. ]*/ - if ((result = StartWorkerThreadIfNeeded(iotHubClientInstance)) != IOTHUB_CLIENT_OK) + freeDeviceMethodContext(iotHubClientInstance); + if (inboundDeviceMethodCallback == NULL) { - /*Codes_SRS_IOTHUBCLIENT_07_004: [ If starting the thread fails, IoTHubClient_SetDeviceMethodCallback_Ex shall return IOTHUB_CLIENT_ERROR. ]*/ - result = IOTHUB_CLIENT_ERROR; - LogError("Could not start worker thread"); + /* Codes_SRS_IOTHUBCLIENT_07_008: [ If inboundDeviceMethodCallback is NULL, IoTHubClient_SetDeviceMethodCallback_Ex shall call IoTHubClientCore_LL_SetDeviceMethodCallback_Ex, passing NULL for the iothub_ll_inbound_device_method_callback. ] */ + result = IoTHubClientCore_LL_SetDeviceMethodCallback_Ex(iotHubClientInstance->IoTHubClientLLHandle, NULL, NULL); } else { - /*Codes_SRS_IOTHUBCLIENT_07_007: [ IoTHubClient_SetDeviceMethodCallback_Ex shall be made thread-safe by using the lock created in IoTHubClient_Create. ]*/ - if (Lock(iotHubClientInstance->LockHandle) != LOCK_OK) + if ((result = allocateQueueContextForMethodCallback(iotHubClientInstance, userContextCallback)) != IOTHUB_CLIENT_OK) { - /*Codes_SRS_IOTHUBCLIENT_07_002: [ If acquiring the lock fails, IoTHubClient_SetDeviceMethodCallback_Ex shall return IOTHUB_CLIENT_ERROR. ]*/ - result = IOTHUB_CLIENT_ERROR; - LogError("Could not acquire lock"); + ; + } + /*Codes_SRS_IOTHUBCLIENT_07_005: [ IoTHubClient_SetDeviceMethodCallback_Ex shall call IoTHubClientCore_LL_SetDeviceMethodCallback_Ex, while passing the IoTHubClientCore_LL_handle created by IoTHubClientCore_LL_Create along with the parameters iothub_ll_inbound_device_method_callback and IOTHUB_QUEUE_CONTEXT. ]*/ + /* Codes_SRS_IOTHUBCLIENT_07_006: [ When IoTHubClientCore_LL_SetDeviceMethodCallback_Ex is called, IoTHubClient_SetDeviceMethodCallback_Ex shall return the result of IoTHubClientCore_LL_SetDeviceMethodCallback_Ex. ] */ + else if ((result = IoTHubClientCore_LL_SetDeviceMethodCallback_Ex(iotHubClientInstance->IoTHubClientLLHandle, iothub_ll_inbound_device_method_callback, iotHubClientInstance->method_user_context)) != IOTHUB_CLIENT_OK) + { + LogError("IoTHubClientCore_LL_SetDeviceMethodCallback_Ex failed"); + freeDeviceMethodContext(iotHubClientInstance); } else { - if (iotHubClientInstance->created_with_transport_handle == 0) - { - iotHubClientInstance->inbound_device_method_callback = inboundDeviceMethodCallback; - } - - if (iotHubClientInstance->method_user_context) - { - free(iotHubClientInstance->method_user_context); - iotHubClientInstance->method_user_context = NULL; - } - if (inboundDeviceMethodCallback == NULL) - { - /* Codes_SRS_IOTHUBCLIENT_07_008: [ If inboundDeviceMethodCallback is NULL, IoTHubClient_SetDeviceMethodCallback_Ex shall call IoTHubClientCore_LL_SetDeviceMethodCallback_Ex, passing NULL for the iothub_ll_inbound_device_method_callback. ] */ - result = IoTHubClientCore_LL_SetDeviceMethodCallback_Ex(iotHubClientInstance->IoTHubClientLLHandle, NULL, NULL); - } - else - { - iotHubClientInstance->method_user_context = (IOTHUB_QUEUE_CONTEXT*)malloc(sizeof(IOTHUB_QUEUE_CONTEXT)); - if (iotHubClientInstance->method_user_context == NULL) - { - result = IOTHUB_CLIENT_ERROR; - LogError("Failed allocating QUEUE_CONTEXT"); - } - else - { - /*Codes_SRS_IOTHUBCLIENT_07_005: [ IoTHubClient_SetDeviceMethodCallback_Ex shall call IoTHubClientCore_LL_SetDeviceMethodCallback_Ex, while passing the IoTHubClientCore_LL_handle created by IoTHubClientCore_LL_Create along with the parameters iothub_ll_inbound_device_method_callback and IOTHUB_QUEUE_CONTEXT. ]*/ - iotHubClientInstance->method_user_context->iotHubClientHandle = iotHubClientHandle; - iotHubClientInstance->method_user_context->userContextCallback = userContextCallback; - - /* Codes_SRS_IOTHUBCLIENT_07_006: [ When IoTHubClientCore_LL_SetDeviceMethodCallback_Ex is called, IoTHubClient_SetDeviceMethodCallback_Ex shall return the result of IoTHubClientCore_LL_SetDeviceMethodCallback_Ex. ] */ - result = IoTHubClientCore_LL_SetDeviceMethodCallback_Ex(iotHubClientInstance->IoTHubClientLLHandle, iothub_ll_inbound_device_method_callback, iotHubClientInstance->method_user_context); - if (result != IOTHUB_CLIENT_OK) - { - LogError("IoTHubClientCore_LL_SetDeviceMethodCallback_Ex failed"); - free(iotHubClientInstance->method_user_context); - iotHubClientInstance->method_user_context = NULL; - } - else - { - iotHubClientInstance->inbound_device_method_callback = inboundDeviceMethodCallback; - } - } - } - - (void)Unlock(iotHubClientInstance->LockHandle); + iotHubClientInstance->inbound_device_method_callback = inboundDeviceMethodCallback; } } + + (void)Unlock(iotHubClientInstance->LockHandle); } + return result; } diff --git a/iothub_client/src/iothub_client_core_ll.c b/iothub_client/src/iothub_client_core_ll.c index 94e246ee3a..4956fbab00 100755 --- a/iothub_client/src/iothub_client_core_ll.c +++ b/iothub_client/src/iothub_client_core_ll.c @@ -2537,6 +2537,55 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_GetTwinAsync(IOTHUB_CLIENT_CORE_LL_HAND } +static void ResetMethodCallbackData(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData) +{ + handleData->methodCallback.type = CALLBACK_TYPE_NONE; + handleData->methodCallback.callbackSync = NULL; + handleData->methodCallback.callbackAsync = NULL; + handleData->methodCallback.userContextCallback = NULL; +} + +static IOTHUB_CLIENT_RESULT VerifyMethodCallbackType(IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData, CALLBACK_TYPE desiredCallbackType, bool unsubscribing) +{ + IOTHUB_CLIENT_RESULT result; + + if (unsubscribing) + { + // If we are unsubscribing, method (Ex or the original non-Ex) performing the unsubscribe must be the same function that subscribed initially. + if (handleData->methodCallback.type == CALLBACK_TYPE_NONE) + { + /* Codes_SRS_IOTHUBCLIENT_LL_10_029: [ If deviceMethodCallback is NULL and the client is not subscribed to receive method calls, IoTHubClientCore_LL_SetDeviceMethodCallback shall fail and return IOTHUB_CLIENT_ERROR. ] */ + LogError("not currently set to accept or process incoming messages."); + result = IOTHUB_CLIENT_ERROR; + } + else if (handleData->methodCallback.type != desiredCallbackType) + { + LogError("Need to unsubscribe with same type of device method function (original or _Ex()"); + result = IOTHUB_CLIENT_ERROR; + } + else + { + result = IOTHUB_CLIENT_OK; + } + } + else + { + // If we are already subscribed and changing the callback method, the type of method (Ex or original non-Ex) must match what was used for the original subscribe. + if ((handleData->methodCallback.type != CALLBACK_TYPE_NONE) && + (handleData->methodCallback.type != desiredCallbackType)) + { + LogError("Need to change callback function with same type of device method function (original or _Ex()"); + result = IOTHUB_CLIENT_ERROR; + } + else + { + result = IOTHUB_CLIENT_OK; + } + } + + return result; +} + IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetDeviceMethodCallback(IOTHUB_CLIENT_CORE_LL_HANDLE iotHubClientHandle, IOTHUB_CLIENT_DEVICE_METHOD_CALLBACK_ASYNC deviceMethodCallback, void* userContextCallback) { IOTHUB_CLIENT_RESULT result; @@ -2550,66 +2599,43 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetDeviceMethodCallback(IOTHUB_CLIENT_C else { IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle; - if (deviceMethodCallback == NULL) + bool unsubscribing = (deviceMethodCallback == NULL); + + if ((result = VerifyMethodCallbackType(handleData, CALLBACK_TYPE_SYNC, unsubscribing)) != IOTHUB_CLIENT_OK) { - if (handleData->methodCallback.type == CALLBACK_TYPE_NONE) - { - /* Codes_SRS_IOTHUBCLIENT_LL_10_029: [ If deviceMethodCallback is NULL and the client is not subscribed to receive method calls, IoTHubClientCore_LL_SetDeviceMethodCallback shall fail and return IOTHUB_CLIENT_ERROR. ] */ - LogError("not currently set to accept or process incoming messages."); - result = IOTHUB_CLIENT_ERROR; - } - else if (handleData->methodCallback.type == CALLBACK_TYPE_ASYNC) - { - /* Codes_SRS_IOTHUBCLIENT_LL_10_028: [If the user has subscribed using IoTHubClientCore_LL_SetDeviceMethodCallback_Ex, IoTHubClientCore_LL_SetDeviceMethodCallback shall fail and return IOTHUB_CLIENT_ERROR. ] */ - LogError("Invalid workflow sequence. Please unsubscribe using the IoTHubClientCore_LL_SetDeviceMethodCallback_Ex function."); - result = IOTHUB_CLIENT_ERROR; - } - else - { - /*Codes_SRS_IOTHUBCLIENT_LL_02_019: [If parameter messageCallback is NULL then IoTHubClientCore_LL_SetMessageCallback shall call the underlying layer's _Unsubscribe function and return IOTHUB_CLIENT_OK.] */ - /*Codes_SRS_IOTHUBCLIENT_LL_12_018: [If deviceMethodCallback is NULL, then IoTHubClientCore_LL_SetDeviceMethodCallback shall call the underlying layer's IoTHubTransport_Unsubscribe_DeviceMethod function and return IOTHUB_CLIENT_OK. ] */ - /*Codes_SRS_IOTHUBCLIENT_LL_12_022: [ Otherwise IoTHubClientCore_LL_SetDeviceMethodCallback shall succeed and return IOTHUB_CLIENT_OK. ]*/ - handleData->IoTHubTransport_Unsubscribe_DeviceMethod(handleData->deviceHandle); - handleData->methodCallback.type = CALLBACK_TYPE_NONE; - handleData->methodCallback.callbackSync = NULL; - handleData->methodCallback.userContextCallback = NULL; - result = IOTHUB_CLIENT_OK; - } + LogInfo("Incorrect callback type"); + } + else if (unsubscribing) + { + /*Codes_SRS_IOTHUBCLIENT_LL_02_019: [If parameter messageCallback is NULL then IoTHubClientCore_LL_SetMessageCallback shall call the underlying layer's _Unsubscribe function and return IOTHUB_CLIENT_OK.] */ + /*Codes_SRS_IOTHUBCLIENT_LL_12_018: [If deviceMethodCallback is NULL, then IoTHubClientCore_LL_SetDeviceMethodCallback shall call the underlying layer's IoTHubTransport_Unsubscribe_DeviceMethod function and return IOTHUB_CLIENT_OK. ] */ + /*Codes_SRS_IOTHUBCLIENT_LL_12_022: [ Otherwise IoTHubClientCore_LL_SetDeviceMethodCallback shall succeed and return IOTHUB_CLIENT_OK. ]*/ + handleData->IoTHubTransport_Unsubscribe_DeviceMethod(handleData->deviceHandle); + ResetMethodCallbackData(handleData); + result = IOTHUB_CLIENT_OK; } else { - if (handleData->methodCallback.type == CALLBACK_TYPE_ASYNC) + /*Codes_SRS_IOTHUBCLIENT_LL_12_019: [ If deviceMethodCallback is not NULL, then IoTHubClientCore_LL_SetDeviceMethodCallback shall call the underlying layer's IoTHubTransport_Subscribe_DeviceMethod function. ]*/ + if (handleData->IoTHubTransport_Subscribe_DeviceMethod(handleData->deviceHandle) == 0) { - /* Codes_SRS_IOTHUBCLIENT_LL_10_028: [If the user has subscribed using IoTHubClientCore_LL_SetDeviceMethodCallback_Ex, IoTHubClientCore_LL_SetDeviceMethodCallback shall fail and return IOTHUB_CLIENT_ERROR. ] */ - LogError("Invalid workflow sequence. Please unsubscribe using the IoTHubClientCore_LL_SetDeviceMethodCallback_Ex function before subscribing with IoTHubClientCore_LL_SetDeviceMethodCallback."); - result = IOTHUB_CLIENT_ERROR; + /*Codes_SRS_IOTHUBCLIENT_LL_12_022: [ Otherwise IoTHubClientCore_LL_SetDeviceMethodCallback shall succeed and return IOTHUB_CLIENT_OK. ]*/ + handleData->methodCallback.type = CALLBACK_TYPE_SYNC; + handleData->methodCallback.callbackSync = deviceMethodCallback; + handleData->methodCallback.userContextCallback = userContextCallback; + result = IOTHUB_CLIENT_OK; } else { - /*Codes_SRS_IOTHUBCLIENT_LL_12_019: [ If deviceMethodCallback is not NULL, then IoTHubClientCore_LL_SetDeviceMethodCallback shall call the underlying layer's IoTHubTransport_Subscribe_DeviceMethod function. ]*/ - if (handleData->IoTHubTransport_Subscribe_DeviceMethod(handleData->deviceHandle) == 0) - { - /*Codes_SRS_IOTHUBCLIENT_LL_12_022: [ Otherwise IoTHubClientCore_LL_SetDeviceMethodCallback shall succeed and return IOTHUB_CLIENT_OK. ]*/ - handleData->methodCallback.type = CALLBACK_TYPE_SYNC; - handleData->methodCallback.callbackSync = deviceMethodCallback; - handleData->methodCallback.callbackAsync = NULL; - handleData->methodCallback.userContextCallback = userContextCallback; - result = IOTHUB_CLIENT_OK; - } - else - { - /*Codes_SRS_IOTHUBCLIENT_LL_12_020: [ If the underlying layer's IoTHubTransport_Subscribe_DeviceMethod function fails, then IoTHubClientCore_LL_SetDeviceMethodCallback shall fail and return IOTHUB_CLIENT_ERROR. ]*/ - /*Codes_SRS_IOTHUBCLIENT_LL_12_021: [ If adding the information fails for any reason, IoTHubClientCore_LL_SetDeviceMethodCallback shall fail and return IOTHUB_CLIENT_ERROR. ]*/ - LogError("IoTHubTransport_Subscribe_DeviceMethod failed"); - handleData->methodCallback.type = CALLBACK_TYPE_NONE; - handleData->methodCallback.callbackAsync = NULL; - handleData->methodCallback.callbackSync = NULL; - handleData->methodCallback.userContextCallback = NULL; - result = IOTHUB_CLIENT_ERROR; - } + /*Codes_SRS_IOTHUBCLIENT_LL_12_020: [ If the underlying layer's IoTHubTransport_Subscribe_DeviceMethod function fails, then IoTHubClientCore_LL_SetDeviceMethodCallback shall fail and return IOTHUB_CLIENT_ERROR. ]*/ + /*Codes_SRS_IOTHUBCLIENT_LL_12_021: [ If adding the information fails for any reason, IoTHubClientCore_LL_SetDeviceMethodCallback shall fail and return IOTHUB_CLIENT_ERROR. ]*/ + LogError("IoTHubTransport_Subscribe_DeviceMethod failed"); + ResetMethodCallbackData(handleData); + result = IOTHUB_CLIENT_ERROR; } } } + return result; } @@ -2625,59 +2651,34 @@ IOTHUB_CLIENT_RESULT IoTHubClientCore_LL_SetDeviceMethodCallback_Ex(IOTHUB_CLIEN else { IOTHUB_CLIENT_CORE_LL_HANDLE_DATA* handleData = (IOTHUB_CLIENT_CORE_LL_HANDLE_DATA*)iotHubClientHandle; - if (inboundDeviceMethodCallback == NULL) + bool unsubscribing = (inboundDeviceMethodCallback == NULL); + + if ((result = VerifyMethodCallbackType(handleData, CALLBACK_TYPE_ASYNC, unsubscribing)) != IOTHUB_CLIENT_OK) { - if (handleData->methodCallback.type == CALLBACK_TYPE_NONE) - { - /* Codes_SRS_IOTHUBCLIENT_LL_10_030: [ If deviceMethodCallback is NULL and the client is not subscribed to receive method calls, IoTHubClientCore_LL_SetDeviceMethodCallback shall fail and return IOTHUB_CLIENT_ERROR. ] */ - LogError("not currently set to accept or process incoming messages."); - result = IOTHUB_CLIENT_ERROR; - } - else if (handleData->methodCallback.type == CALLBACK_TYPE_SYNC) - { - /* Codes_SRS_IOTHUBCLIENT_LL_10_031: [If the user has subscribed using IoTHubClientCore_LL_SetDeviceMethodCallback, IoTHubClientCore_LL_SetDeviceMethodCallback_Ex shall fail and return IOTHUB_CLIENT_ERROR. ] */ - LogError("Invalid workflow sequence. Please unsubscribe using the IoTHubClientCore_LL_SetDeviceMethodCallback function."); - result = IOTHUB_CLIENT_ERROR; - } - else - { - /* Codes_SRS_IOTHUBCLIENT_LL_07_022: [ If inboundDeviceMethodCallback is NULL then IoTHubClientCore_LL_SetDeviceMethodCallback_Ex shall call the underlying layer's IoTHubTransport_Unsubscribe_DeviceMethod function and return IOTHUB_CLIENT_OK.] */ - handleData->IoTHubTransport_Unsubscribe_DeviceMethod(handleData->deviceHandle); - handleData->methodCallback.type = CALLBACK_TYPE_NONE; - handleData->methodCallback.callbackAsync = NULL; - handleData->methodCallback.userContextCallback = NULL; - result = IOTHUB_CLIENT_OK; - } + LogInfo("Incorrect callback type"); + } + else if (unsubscribing) + { + /* Codes_SRS_IOTHUBCLIENT_LL_07_022: [ If inboundDeviceMethodCallback is NULL then IoTHubClientCore_LL_SetDeviceMethodCallback_Ex shall call the underlying layer's IoTHubTransport_Unsubscribe_DeviceMethod function and return IOTHUB_CLIENT_OK.] */ + handleData->IoTHubTransport_Unsubscribe_DeviceMethod(handleData->deviceHandle); + ResetMethodCallbackData(handleData); + result = IOTHUB_CLIENT_OK; } else { - if (handleData->methodCallback.type == CALLBACK_TYPE_SYNC) + if (handleData->IoTHubTransport_Subscribe_DeviceMethod(handleData->deviceHandle) == 0) { - /* Codes_SRS_IOTHUBCLIENT_LL_10_031: [If the user has subscribed using IoTHubClientCore_LL_SetDeviceMethodCallback, IoTHubClientCore_LL_SetDeviceMethodCallback_Ex shall fail and return IOTHUB_CLIENT_ERROR. ] */ - LogError("Invalid workflow sequence. Please unsubscribe using the IoTHubClientCore_LL_SetDeviceMethodCallback function before subscribing with IoTHubClientCore_LL_SetDeviceMethodCallback_Ex."); - result = IOTHUB_CLIENT_ERROR; + handleData->methodCallback.type = CALLBACK_TYPE_ASYNC; + handleData->methodCallback.callbackAsync = inboundDeviceMethodCallback; + handleData->methodCallback.userContextCallback = userContextCallback; + result = IOTHUB_CLIENT_OK; } else { - /* Codes_SRS_IOTHUBCLIENT_LL_07_023: [ If inboundDeviceMethodCallback is non-NULL then IoTHubClientCore_LL_SetDeviceMethodCallback_Ex shall call the underlying layer's IoTHubTransport_Subscribe_DeviceMethod function.]*/ - if (handleData->IoTHubTransport_Subscribe_DeviceMethod(handleData->deviceHandle) == 0) - { - handleData->methodCallback.type = CALLBACK_TYPE_ASYNC; - handleData->methodCallback.callbackAsync = inboundDeviceMethodCallback; - handleData->methodCallback.callbackSync = NULL; - handleData->methodCallback.userContextCallback = userContextCallback; - result = IOTHUB_CLIENT_OK; - } - else - { - /* Codes_SRS_IOTHUBCLIENT_LL_07_025: [ If any error is encountered then IoTHubClientCore_LL_SetDeviceMethodCallback_Ex shall return IOTHUB_CLIENT_ERROR.] */ - LogError("IoTHubTransport_Subscribe_DeviceMethod failed"); - handleData->methodCallback.type = CALLBACK_TYPE_NONE; - handleData->methodCallback.callbackAsync = NULL; - handleData->methodCallback.callbackSync = NULL; - handleData->methodCallback.userContextCallback = NULL; - result = IOTHUB_CLIENT_ERROR; - } + /* Codes_SRS_IOTHUBCLIENT_LL_07_025: [ If any error is encountered then IoTHubClientCore_LL_SetDeviceMethodCallback_Ex shall return IOTHUB_CLIENT_ERROR.] */ + LogError("IoTHubTransport_Subscribe_DeviceMethod failed"); + ResetMethodCallbackData(handleData); + result = IOTHUB_CLIENT_ERROR; } } }