Microsoft Azure IoTHub client AMQP transport
Dependents: sht15_remote_monitoring RobotArmDemo iothub_client_sample_amqp iothub_client_sample_amqp ... more
This library implements the AMQP transport for Microsoft Azure IoTHub client. The code is replicated from https://github.com/Azure/azure-iot-sdks
Diff: iothubtransportamqp.c
- Revision:
- 19:ea016664011a
- Parent:
- 18:239d162e3607
- Child:
- 20:8dec76e7ba34
--- a/iothubtransportamqp.c Fri Jul 01 10:42:04 2016 -0700 +++ b/iothubtransportamqp.c Mon Jul 18 16:44:19 2016 -0700 @@ -61,16 +61,46 @@ CBS_STATE_AUTHENTICATED } CBS_STATE; +typedef enum AMQP_TRANSPORT_CREDENTIAL_TYPE_TAG +{ + CREDENTIAL_NOT_BUILD, + X509, + DEVICE_KEY, + DEVICE_SAS_TOKEN, +}AMQP_TRANSPORT_CREDENTIAL_TYPE; + +typedef struct X509_CREDENTIAL_TAG +{ + const char* x509certificate; + const char* x509privatekey; +}X509_CREDENTIAL; + +typedef union AMQP_TRANSPORT_CREDENTIAL_UNION_TAG +{ + // Key associated to the device to be used. + STRING_HANDLE deviceKey; + + // SAS associated to the device to be used. + STRING_HANDLE deviceSasToken; + + // X509 + X509_CREDENTIAL x509credential; +}AMQP_TRANSPORT_CREDENTIAL_UNION; + +typedef struct AMQP_TRANSPORT_CREDENTIAL_TAG +{ + AMQP_TRANSPORT_CREDENTIAL_TYPE credentialType; + AMQP_TRANSPORT_CREDENTIAL_UNION credential; +}AMQP_TRANSPORT_CREDENTIAL; + typedef struct AMQP_TRANSPORT_STATE_TAG { // FQDN of the IoT Hub. STRING_HANDLE iotHubHostFqdn; // AMQP port of the IoT Hub. int iotHubPort; - // Key associated to the device to be used. - STRING_HANDLE deviceKey; - // SAS associated to the device to be used. - STRING_HANDLE deviceSasToken; + // contains the credentials to be used + AMQP_TRANSPORT_CREDENTIAL credential; // Address to which the transport will connect to and send events. STRING_HANDLE targetAddress; // Address to which the transport will connect to and receive messages from. @@ -224,32 +254,32 @@ const char* const* propertyValues; size_t propertyCount; - /* Codes_SRS_IOTHUBTRANSPORTUAMQP_01_007: [The IoTHub message properties shall be obtained by calling IoTHubMessage_Properties.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_01_007: [The IoTHub message properties shall be obtained by calling IoTHubMessage_Properties.] */ properties_map = IoTHubMessage_Properties(iothub_message_handle); if (properties_map == NULL) { - /* Codes_SRS_IOTHUBTRANSPORTUAMQP_01_014: [If any of the APIs fails while building the property map and setting it on the uAMQP message, IoTHubTransportAMQP_DoWork shall notify the failure by invoking the upper layer message send callback with IOTHUB_CLIENT_CONFIRMATION_ERROR.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_01_014: [If any of the APIs fails while building the property map and setting it on the uAMQP message, IoTHubTransportAMQP_DoWork shall notify the failure by invoking the upper layer message send callback with IOTHUB_CLIENT_CONFIRMATION_ERROR.] */ LogError("Failed to get property map from IoTHub message."); result = __LINE__; } - /* Codes_SRS_IOTHUBTRANSPORTUAMQP_01_015: [The actual keys and values, as well as the number of properties shall be obtained by calling Map_GetInternals on the handle obtained from IoTHubMessage_Properties.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_01_015: [The actual keys and values, as well as the number of properties shall be obtained by calling Map_GetInternals on the handle obtained from IoTHubMessage_Properties.] */ else if (Map_GetInternals(properties_map, &propertyKeys, &propertyValues, &propertyCount) != MAP_OK) { - /* Codes_SRS_IOTHUBTRANSPORTUAMQP_01_014: [If any of the APIs fails while building the property map and setting it on the uAMQP message, IoTHubTransportAMQP_DoWork shall notify the failure by invoking the upper layer message send callback with IOTHUB_CLIENT_CONFIRMATION_ERROR.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_01_014: [If any of the APIs fails while building the property map and setting it on the uAMQP message, IoTHubTransportAMQP_DoWork shall notify the failure by invoking the upper layer message send callback with IOTHUB_CLIENT_CONFIRMATION_ERROR.] */ LogError("Failed to get the internals of the property map."); result = __LINE__; } else { - /* Codes_SRS_IOTHUBTRANSPORTUAMQP_01_016: [If the number of properties is 0, no uAMQP map shall be created and no application properties shall be set on the uAMQP message.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_01_016: [If the number of properties is 0, no uAMQP map shall be created and no application properties shall be set on the uAMQP message.] */ if (propertyCount != 0) { size_t i; - /* Codes_SRS_IOTHUBTRANSPORTUAMQP_01_009: [The uAMQP map shall be created by calling amqpvalue_create_map.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_01_009: [The uAMQP map shall be created by calling amqpvalue_create_map.] */ AMQP_VALUE uamqp_map = amqpvalue_create_map(); if (uamqp_map == NULL) { - /* Codes_SRS_IOTHUBTRANSPORTUAMQP_01_014: [If any of the APIs fails while building the property map and setting it on the uAMQP message, IoTHubTransportAMQP_DoWork shall notify the failure by invoking the upper layer message send callback with IOTHUB_CLIENT_CONFIRMATION_ERROR.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_01_014: [If any of the APIs fails while building the property map and setting it on the uAMQP message, IoTHubTransportAMQP_DoWork shall notify the failure by invoking the upper layer message send callback with IOTHUB_CLIENT_CONFIRMATION_ERROR.] */ LogError("Failed to create uAMQP map for the properties."); result = __LINE__; } @@ -257,32 +287,32 @@ { for (i = 0; i < propertyCount; i++) { - /* Codes_SRS_IOTHUBTRANSPORTUAMQP_01_010: [A key uAMQP value shall be created by using amqpvalue_create_string.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_01_010: [A key uAMQP value shall be created by using amqpvalue_create_string.] */ AMQP_VALUE map_key_value = amqpvalue_create_string(propertyKeys[i]); if (map_key_value == NULL) { - /* Codes_SRS_IOTHUBTRANSPORTUAMQP_01_014: [If any of the APIs fails while building the property map and setting it on the uAMQP message, IoTHubTransportAMQP_DoWork shall notify the failure by invoking the upper layer message send callback with IOTHUB_CLIENT_CONFIRMATION_ERROR.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_01_014: [If any of the APIs fails while building the property map and setting it on the uAMQP message, IoTHubTransportAMQP_DoWork shall notify the failure by invoking the upper layer message send callback with IOTHUB_CLIENT_CONFIRMATION_ERROR.] */ LogError("Failed to create uAMQP property key value."); break; } - /* Codes_SRS_IOTHUBTRANSPORTUAMQP_01_011: [A value uAMQP value shall be created by using amqpvalue_create_string.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_01_011: [A value uAMQP value shall be created by using amqpvalue_create_string.] */ AMQP_VALUE map_value_value = amqpvalue_create_string(propertyValues[i]); if (map_value_value == NULL) { amqpvalue_destroy(map_key_value); - /* Codes_SRS_IOTHUBTRANSPORTUAMQP_01_014: [If any of the APIs fails while building the property map and setting it on the uAMQP message, IoTHubTransportAMQP_DoWork shall notify the failure by invoking the upper layer message send callback with IOTHUB_CLIENT_CONFIRMATION_ERROR.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_01_014: [If any of the APIs fails while building the property map and setting it on the uAMQP message, IoTHubTransportAMQP_DoWork shall notify the failure by invoking the upper layer message send callback with IOTHUB_CLIENT_CONFIRMATION_ERROR.] */ LogError("Failed to create uAMQP property key value."); break; } - /* Codes_SRS_IOTHUBTRANSPORTUAMQP_01_008: [All properties shall be transferred to a uAMQP map.] */ - /* Codes_SRS_IOTHUBTRANSPORTUAMQP_01_012: [The key/value pair for the property shall be set into the uAMQP property map by calling amqpvalue_map_set_value.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_01_008: [All properties shall be transferred to a uAMQP map.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_01_012: [The key/value pair for the property shall be set into the uAMQP property map by calling amqpvalue_map_set_value.] */ if (amqpvalue_set_map_value(uamqp_map, map_key_value, map_value_value) != 0) { amqpvalue_destroy(map_key_value); amqpvalue_destroy(map_value_value); - /* Codes_SRS_IOTHUBTRANSPORTUAMQP_01_014: [If any of the APIs fails while building the property map and setting it on the uAMQP message, IoTHubTransportAMQP_DoWork shall notify the failure by invoking the upper layer message send callback with IOTHUB_CLIENT_CONFIRMATION_ERROR.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_01_014: [If any of the APIs fails while building the property map and setting it on the uAMQP message, IoTHubTransportAMQP_DoWork shall notify the failure by invoking the upper layer message send callback with IOTHUB_CLIENT_CONFIRMATION_ERROR.] */ LogError("Failed to create uAMQP property key value."); break; } @@ -297,10 +327,10 @@ } else { - /* Codes_SRS_IOTHUBTRANSPORTUAMQP_01_013: [After all properties have been filled in the uAMQP map, the uAMQP properties map shall be set on the uAMQP message by calling message_set_application_properties.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_01_013: [After all properties have been filled in the uAMQP map, the uAMQP properties map shall be set on the uAMQP message by calling message_set_application_properties.] */ if (message_set_application_properties(uamqp_message, uamqp_map) != 0) { - /* Codes_SRS_IOTHUBTRANSPORTUAMQP_01_014: [If any of the APIs fails while building the property map and setting it on the uAMQP message, IoTHubTransportAMQP_DoWork shall notify the failure by invoking the upper layer message send callback with IOTHUB_CLIENT_CONFIRMATION_ERROR.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_01_014: [If any of the APIs fails while building the property map and setting it on the uAMQP message, IoTHubTransportAMQP_DoWork shall notify the failure by invoking the upper layer message send callback with IOTHUB_CLIENT_CONFIRMATION_ERROR.] */ LogError("Failed to transfer the message properties to the uAMQP message."); result = __LINE__; } @@ -333,7 +363,7 @@ /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_155: [uAMQP message properties shall be retrieved using message_get_properties.] */ if ((api_call_result = message_get_properties(uamqp_message, &uamqp_message_properties)) != 0) { - /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_156: [If message_get_properties fails, the error shall be notified and on_message_received shall continue.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_156: [If message_get_properties fails, the error shall be notified and on_message_received' shall continue.] */ LogError("Failed to get property properties map from uAMQP message (error code %d).", api_call_result); return_value = __LINE__; } @@ -344,7 +374,7 @@ /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_157: [The message-id property shall be read from the uAMQP message by calling properties_get_message_id.] */ if ((api_call_result = properties_get_message_id(uamqp_message_properties, &uamqp_message_property)) != 0) { - /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_158: [If properties_get_message_id fails, the error shall be notified and on_message_received shall continue.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_158: [If properties_get_message_id fails, the error shall be notified and on_message_received' shall continue.] */ LogInfo("Failed to get value of uAMQP message 'message-id' property (%d).", api_call_result); return_value = __LINE__; } @@ -353,14 +383,14 @@ /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_159: [The message-id value shall be retrieved from the AMQP_VALUE as char* by calling amqpvalue_get_string.] */ if ((api_call_result = amqpvalue_get_string(uamqp_message_property, &uamqp_message_property_value)) != 0) { - /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_160: [If amqpvalue_get_string fails, the error shall be notified and on_message_received shall continue.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_160: [If amqpvalue_get_string fails, the error shall be notified and on_message_received' shall continue.] */ LogError("Failed to get value of uAMQP message 'message-id' property (%d).", api_call_result); return_value = __LINE__; } /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_161: [The message-id property shall be set on the IOTHUB_MESSAGE_HANDLE by calling IoTHubMessage_SetMessageId, passing the value read from the uAMQP message.] */ else if (IoTHubMessage_SetMessageId(iothub_message_handle, uamqp_message_property_value) != IOTHUB_MESSAGE_OK) { - /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_162: [If IoTHubMessage_SetMessageId fails, the error shall be notified and on_message_received shall continue.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_162: [If IoTHubMessage_SetMessageId fails, the error shall be notified and on_message_received' shall continue.] */ LogError("Failed to set IOTHUB_MESSAGE_HANDLE 'message-id' property."); return_value = __LINE__; } @@ -369,7 +399,7 @@ /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_163: [The correlation-id property shall be read from the uAMQP message by calling properties_get_correlation_id.] */ if ((api_call_result = properties_get_correlation_id(uamqp_message_properties, &uamqp_message_property)) != 0) { - /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_164: [If properties_get_correlation_id fails, the error shall be notified and on_message_received shall continue.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_164: [If properties_get_correlation_id fails, the error shall be notified and on_message_received' shall continue.] */ LogError("Failed to get value of uAMQP message 'correlation-id' property (%d).", api_call_result); return_value = __LINE__; } @@ -378,14 +408,14 @@ /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_165: [The correlation-id value shall be retrieved from the AMQP_VALUE as char* by calling amqpvalue_get_string.] */ if ((api_call_result = amqpvalue_get_string(uamqp_message_property, &uamqp_message_property_value)) != 0) { - /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_166: [If amqpvalue_get_string fails, the error shall be notified and on_message_received shall continue.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_166: [If amqpvalue_get_string fails, the error shall be notified and on_message_received' shall continue.] */ LogError("Failed to get value of uAMQP message 'correlation-id' property (%d).", api_call_result); return_value = __LINE__; } /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_167: [The correlation-id property shall be set on the IOTHUB_MESSAGE_HANDLE by calling IoTHubMessage_SetCorrelationId, passing the value read from the uAMQP message.] */ else if (IoTHubMessage_SetCorrelationId(iothub_message_handle, uamqp_message_property_value) != IOTHUB_MESSAGE_OK) { - /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_168: [If IoTHubMessage_SetCorrelationId fails, the error shall be notified and on_message_received shall continue.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_168: [If IoTHubMessage_SetCorrelationId fails, the error shall be notified and on_message_received' shall continue.] */ LogError("Failed to set IOTHUB_MESSAGE_HANDLE 'correlation-id' property."); return_value = __LINE__; } @@ -406,18 +436,18 @@ // Codes_SRS_IOTHUBTRANSPORTAMQP_09_170: [The IOTHUB_MESSAGE_HANDLE properties shall be retrieved using IoTHubMessage_Properties.] if ((iothub_message_properties_map = IoTHubMessage_Properties(iothub_message_handle)) == NULL) { - // Codes_SRS_IOTHUBTRANSPORTAMQP_09_186: [If IoTHubMessage_Properties fails, the error shall be notified and on_message_received shall continue.] + // Codes_SRS_IOTHUBTRANSPORTAMQP_09_186: [If IoTHubMessage_Properties fails, the error shall be notified and on_message_received' shall continue.] LogError("Failed to get property map from IoTHub message."); result = __LINE__; } // Codes_SRS_IOTHUBTRANSPORTAMQP_09_171: [uAMQP message application properties shall be retrieved using message_get_application_properties.] else if ((result = message_get_application_properties(uamqp_message, &uamqp_app_properties)) != 0) { - // Codes_SRS_IOTHUBTRANSPORTAMQP_09_172: [If message_get_application_properties fails, the error shall be notified and on_message_received shall continue.] + // Codes_SRS_IOTHUBTRANSPORTAMQP_09_172: [If message_get_application_properties fails, the error shall be notified and on_message_received' shall continue.] LogError("Failed reading the incoming uAMQP message properties (return code %d).", result); result = __LINE__; } - // Codes_SRS_IOTHUBTRANSPORTAMQP_09_187: [If message_get_application_properties succeeds but returns a NULL application properties map (there are no properties), on_message_received shall continue normally.] + // Codes_SRS_IOTHUBTRANSPORTAMQP_09_187: [If message_get_application_properties succeeds but returns a NULL application properties map (there are no properties), on_message_received' shall continue normally.] else if (uamqp_app_properties == NULL) { result = 0; @@ -425,21 +455,21 @@ // Codes_SRS_IOTHUBTRANSPORTAMQP_09_173: [The actual uAMQP message application properties should be extracted from the result of message_get_application_properties using amqpvalue_get_inplace_described_value.] else if ((uamqp_app_properties = amqpvalue_get_inplace_described_value(uamqp_app_properties)) == NULL) { - // Codes_SRS_IOTHUBTRANSPORTAMQP_09_174: [If amqpvalue_get_inplace_described_value fails, the error shall be notified and on_message_received shall continue.] + // Codes_SRS_IOTHUBTRANSPORTAMQP_09_174: [If amqpvalue_get_inplace_described_value fails, the error shall be notified and on_message_received' shall continue.] LogError("Failed getting the map of uAMQP message application properties (return code %d).", result); result = __LINE__; } // Codes_SRS_IOTHUBTRANSPORTAMQP_09_175: [The number of items in the uAMQP message application properties shall be obtained using amqpvalue_get_map_pair_count.] else if ((result = amqpvalue_get_map_pair_count(uamqp_app_properties, &property_count)) != 0) { - // Codes_SRS_IOTHUBTRANSPORTAMQP_09_176: [If amqpvalue_get_map_pair_count fails, the error shall be notified and on_message_received shall continue.] + // Codes_SRS_IOTHUBTRANSPORTAMQP_09_176: [If amqpvalue_get_map_pair_count fails, the error shall be notified and on_message_received' shall continue.] LogError("Failed reading the number of values in the uAMQP property map (return code %d).", result); result = __LINE__; } else { - // Codes_SRS_IOTHUBTRANSPORTAMQP_09_177: [on_message_received shall iterate through each uAMQP application property and add it on IOTHUB_MESSAGE_HANDLE properties.] - size_t i; + // Codes_SRS_IOTHUBTRANSPORTAMQP_09_177: [on_message_received' shall iterate through each uAMQP application property and add it on IOTHUB_MESSAGE_HANDLE properties.] + uint32_t i; for (i = 0; i < property_count; i++) { AMQP_VALUE map_key_name; @@ -450,7 +480,7 @@ // Codes_SRS_IOTHUBTRANSPORTAMQP_09_178: [The uAMQP application property name and value shall be obtained using amqpvalue_get_map_key_value_pair.] if ((result = amqpvalue_get_map_key_value_pair(uamqp_app_properties, i, &map_key_name, &map_key_value)) != 0) { - // Codes_SRS_IOTHUBTRANSPORTAMQP_09_179: [If amqpvalue_get_map_key_value_pair fails, the error shall be notified and on_message_received shall continue.] + // Codes_SRS_IOTHUBTRANSPORTAMQP_09_179: [If amqpvalue_get_map_key_value_pair fails, the error shall be notified and on_message_received' shall continue.] LogError("Failed reading the key/value pair from the uAMQP property map (return code %d).", result); result = __LINE__; break; @@ -458,7 +488,7 @@ // Codes_SRS_IOTHUBTRANSPORTAMQP_09_180: [The uAMQP application property name shall be extracted as string using amqpvalue_get_string.] else if ((result = amqpvalue_get_string(map_key_name, &key_name)) != 0) { - // Codes_SRS_IOTHUBTRANSPORTAMQP_09_181: [If amqpvalue_get_string fails, the error shall be notified and on_message_received shall continue.] + // Codes_SRS_IOTHUBTRANSPORTAMQP_09_181: [If amqpvalue_get_string fails, the error shall be notified and on_message_received' shall continue.] LogError("Failed parsing the uAMQP property name (return code %d).", result); result = __LINE__; break; @@ -466,7 +496,7 @@ // Codes_SRS_IOTHUBTRANSPORTAMQP_09_182: [The uAMQP application property value shall be extracted as string using amqpvalue_get_string.] else if ((result = amqpvalue_get_string(map_key_value, &key_value)) != 0) { - // Codes_SRS_IOTHUBTRANSPORTAMQP_09_183: [If amqpvalue_get_string fails, the error shall be notified and on_message_received shall continue.] + // Codes_SRS_IOTHUBTRANSPORTAMQP_09_183: [If amqpvalue_get_string fails, the error shall be notified and on_message_received' shall continue.] LogError("Failed parsing the uAMQP property value (return code %d).", result); result = __LINE__; break; @@ -474,7 +504,7 @@ // Codes_SRS_IOTHUBTRANSPORTAMQP_09_184: [The application property name and value shall be added to IOTHUB_MESSAGE_HANDLE properties using Map_AddOrUpdate.] else if (Map_AddOrUpdate(iothub_message_properties_map, key_name, key_value) != MAP_OK) { - // Codes_SRS_IOTHUBTRANSPORTAMQP_09_185: [If Map_AddOrUpdate fails, the error shall be notified and on_message_received shall continue.] + // Codes_SRS_IOTHUBTRANSPORTAMQP_09_185: [If Map_AddOrUpdate fails, the error shall be notified and on_message_received' shall continue.] LogError("Failed to add/update IoTHub message property map."); result = __LINE__; break; @@ -529,6 +559,10 @@ { transportState->cbs_state = CBS_STATE_AUTHENTICATED; } + else + { + LogError("CBS reported status %u error: %s", status_code, status_description); + } } static AMQP_VALUE on_message_received(const void* context, MESSAGE_HANDLE message) @@ -567,17 +601,17 @@ } else { - /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_153: [The callback on_message_received shall read the message-id property from the uAMQP message and set it on the IoT Hub Message if the property is defined.] */ - /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_154: [The callback on_message_received shall read the correlation-id property from the uAMQP message and set it on the IoT Hub Message if the property is defined.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_153: [The callback on_message_received' shall read the message-id property from the uAMQP message and set it on the IoT Hub Message if the property is defined.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_09_154: [The callback on_message_received' shall read the correlation-id property from the uAMQP message and set it on the IoT Hub Message if the property is defined.] */ if (readPropertiesFromuAMQPMessage(iothub_message, message) != 0) { LogError("Transport failed reading properties of the message received."); } - // Codes_SRS_IOTHUBTRANSPORTAMQP_09_169: [The callback on_message_received shall read the application properties from the uAMQP message and set it on the IoT Hub Message if any are provided.] + // Codes_SRS_IOTHUBTRANSPORTAMQP_09_169: [The callback on_message_received' shall read the application properties from the uAMQP message and set it on the IoT Hub Message if any are provided.] if (readApplicationPropertiesFromuAMQPMessage(iothub_message, message) != 0) { - // Codes_SRS_IOTHUBTRANSPORTAMQP_09_188: [If on_message_received fails reading the application properties from the uAMQP message, it shall NOT call IoTHubClient_LL_MessageCallback and shall reject the message.] + // Codes_SRS_IOTHUBTRANSPORTAMQP_09_188: [If on_message_received' fails reading the application properties from the uAMQP message, it shall NOT call IoTHubClient_LL_MessageCallback and shall reject the message.] LogError("Transport failed reading application properties of the message received."); result = messaging_delivery_rejected("Rejected due to failure reading AMQP message", "Failed reading application properties"); @@ -613,7 +647,9 @@ static XIO_HANDLE getTLSIOTransport(const char* fqdn, int port) { - TLSIO_CONFIG tls_io_config = { fqdn, port }; + TLSIO_CONFIG tls_io_config; + tls_io_config.hostname = fqdn; + tls_io_config.port = port; const IO_INTERFACE_DESCRIPTION* io_interface_description = platform_get_default_tlsio(); return xio_create(io_interface_description, &tls_io_config); } @@ -701,7 +737,9 @@ else { // Codes_SRS_IOTHUBTRANSPORTAMQP_09_060: [IoTHubTransportAMQP_DoWork shall create the SASL I / O layer using the xio_create() C Shared Utility API] - SASLCLIENTIO_CONFIG sasl_client_config = { transport_state->tls_io, transport_state->sasl_mechanism }; + SASLCLIENTIO_CONFIG sasl_client_config; + sasl_client_config.sasl_mechanism = transport_state->sasl_mechanism; + sasl_client_config.underlying_io = transport_state->tls_io; if ((transport_state->sasl_io = xio_create(saslclientio_get_interface_description(), &sasl_client_config)) == NULL) { // Codes_SRS_IOTHUBTRANSPORTAMQP_09_061: [If xio_create() fails creating the SASL I/O layer, IoTHubTransportAMQP_DoWork shall fail and return immediately] @@ -755,6 +793,7 @@ transport_state->connection_establish_time = getSecondsSinceEpoch(); transport_state->cbs_state = CBS_STATE_IDLE; connection_set_trace(transport_state->connection, transport_state->is_trace_on); + (void)xio_setoption(transport_state->sasl_io, "logtrace", &transport_state->is_trace_on); result = RESULT_OK; } } @@ -768,6 +807,23 @@ return result; } +static int handSASTokenToCbs(AMQP_TRANSPORT_INSTANCE* transport_state, STRING_HANDLE sasToken, size_t sas_token_create_time) +{ + int result; + if (cbs_put_token(transport_state->cbs, CBS_AUDIENCE, STRING_c_str(transport_state->devicesPath), STRING_c_str(sasToken), on_put_token_complete, transport_state) != RESULT_OK) + { + LogError("Failed applying new SAS token to CBS."); + result = __LINE__; + } + else + { + transport_state->cbs_state = CBS_STATE_AUTH_IN_PROGRESS; + transport_state->current_sas_token_create_time = sas_token_create_time; + result = RESULT_OK; + } + return result; +} + static int startAuthentication(AMQP_TRANSPORT_INSTANCE* transport_state) { int result; @@ -779,38 +835,65 @@ STRING_HANDLE newSASToken; - if (transport_state->deviceSasToken == NULL) - { - newSASToken = SASToken_Create(transport_state->deviceKey, transport_state->devicesPath, transport_state->sasTokenKeyName, new_expiry_time); - } - else - { - newSASToken = STRING_clone(transport_state->deviceSasToken); - } - - if (newSASToken == NULL) - { - LogError("Could not generate a new SAS token for the CBS."); - result = RESULT_FAILURE; - } - else if (cbs_put_token(transport_state->cbs, CBS_AUDIENCE, STRING_c_str(transport_state->devicesPath), STRING_c_str(newSASToken), on_put_token_complete, transport_state) != RESULT_OK) + switch (transport_state->credential.credentialType) { - LogError("Failed applying new SAS token to CBS."); - result = RESULT_FAILURE; + default: + { + result = __LINE__; + LogError("internal error, unexpected enum value transport_state->credential.credentialType=%d", transport_state->credential.credentialType); + break; + } + case DEVICE_KEY: + { + newSASToken = SASToken_Create(transport_state->credential.credential.deviceKey, transport_state->devicesPath, transport_state->sasTokenKeyName, new_expiry_time); + if (newSASToken == NULL) + { + LogError("Could not generate a new SAS token for the CBS."); + result = RESULT_FAILURE; + } + else + { + if (handSASTokenToCbs(transport_state, newSASToken, sas_token_create_time) != 0) + { + LogError("unable to handSASTokenToCbs"); + result = RESULT_FAILURE; + } + else + { + result = RESULT_OK; + } + + // Codes_SRS_IOTHUBTRANSPORTAMQP_09_145: [Each new SAS token created shall be deleted from memory immediately after sending it to CBS] + STRING_delete(newSASToken); + } + break; + } + case DEVICE_SAS_TOKEN: + { + newSASToken = STRING_clone(transport_state->credential.credential.deviceSasToken); + if (newSASToken == NULL) + { + LogError("Could not generate a new SAS token for the CBS."); + result = RESULT_FAILURE; + } + else + { + if (handSASTokenToCbs(transport_state, newSASToken, sas_token_create_time) != 0) + { + LogError("unable to handSASTokenToCbs"); + result = RESULT_FAILURE; + } + else + { + result = RESULT_OK; + } + + // Codes_SRS_IOTHUBTRANSPORTAMQP_09_145: [Each new SAS token created shall be deleted from memory immediately after sending it to CBS] + STRING_delete(newSASToken); + } + break; + } } - else - { - transport_state->cbs_state = CBS_STATE_AUTH_IN_PROGRESS; - transport_state->current_sas_token_create_time = sas_token_create_time; - result = RESULT_OK; - } - - // Codes_SRS_IOTHUBTRANSPORTAMQP_09_145: [Each new SAS token created shall be deleted from memory immediately after sending it to CBS] - if (newSASToken != NULL) - { - STRING_delete(newSASToken); - } - return result; } @@ -887,7 +970,9 @@ void on_event_sender_state_changed(void* context, MESSAGE_SENDER_STATE new_state, MESSAGE_SENDER_STATE previous_state) { - LogInfo("Event sender state changed [%d->%d]", previous_state, new_state); + (void)context; + (void)new_state; + (void)previous_state; } static int createEventSender(AMQP_TRANSPORT_INSTANCE* transport_state) @@ -1058,8 +1143,8 @@ result = RESULT_FAILURE; IOTHUBMESSAGE_CONTENT_TYPE contentType = IoTHubMessage_GetContentType(message->messageHandle); - const unsigned char* messageContent; - size_t messageContentSize; + const unsigned char* messageContent = NULL; + size_t messageContentSize = 0; MESSAGE_HANDLE amqp_message = NULL; bool is_message_error = false; @@ -1076,7 +1161,7 @@ // Codes_SRS_IOTHUBTRANSPORTAMQP_09_089: [If the event contains a message of type IOTHUBMESSAGE_STRING, IoTHubTransportAMQP_DoWork shall obtain its char* representation using IoTHubMessage_GetString()] // Codes_SRS_IOTHUBTRANSPORTAMQP_09_090: [If the event contains a message of type IOTHUBMESSAGE_STRING, IoTHubTransportAMQP_DoWork shall obtain the size of its char* representation using strlen()] else if (contentType == IOTHUBMESSAGE_STRING && - ((messageContent = IoTHubMessage_GetString(message->messageHandle)) == NULL)) + ((messageContent = (const unsigned char*)IoTHubMessage_GetString(message->messageHandle)) == NULL)) { LogError("Failed getting the STRING representation of the event content to be sent."); is_message_error = true; @@ -1098,7 +1183,7 @@ if (contentType == IOTHUBMESSAGE_STRING) { - messageContentSize = strlen(messageContent); + messageContentSize = strlen((const char*)messageContent); } binary_data.bytes = messageContent; @@ -1113,7 +1198,7 @@ { if (addPropertiesTouAMQPMessage(message->messageHandle, amqp_message) != 0) { - /* Codes_SRS_IOTHUBTRANSPORTUAMQP_01_014: [If any of the APIs fails while building the property map and setting it on the uAMQP message, IoTHubTransportAMQP_DoWork shall notify the failure by invoking the upper layer message send callback with IOTHUB_CLIENT_CONFIRMATION_ERROR.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_01_014: [If any of the APIs fails while building the property map and setting it on the uAMQP message, IoTHubTransportAMQP_DoWork shall notify the failure by invoking the upper layer message send callback with IOTHUB_CLIENT_CONFIRMATION_ERROR.] */ is_message_error = true; } else @@ -1161,7 +1246,7 @@ static bool isSasTokenRefreshRequired(AMQP_TRANSPORT_INSTANCE* transport_state) { - if (transport_state->deviceSasToken != NULL) + if (transport_state->credential.credentialType == DEVICE_SAS_TOKEN) { return false; } @@ -1181,12 +1266,43 @@ } +static void credential_destroy(AMQP_TRANSPORT_INSTANCE* transport_state) +{ + switch (transport_state->credential.credentialType) + { + default: + { + LogError("internal error: unexpected enum value transport_state->credential.credentialType=%d", transport_state->credential.credentialType); + break; + } + case (CREDENTIAL_NOT_BUILD): + { + /*nothing to do*/ + break; + } + case(X509): + { + /*nothing to do here, x509certificate and x509privatekey are both NULL*/ + break; + } + case(DEVICE_KEY): + { + STRING_delete(transport_state->credential.credential.deviceKey); + break; + } + case(DEVICE_SAS_TOKEN): + { + STRING_delete(transport_state->credential.credential.deviceSasToken); + break; + } + } +} + // API functions static TRANSPORT_LL_HANDLE IoTHubTransportAMQP_Create(const IOTHUBTRANSPORT_CONFIG* config) { AMQP_TRANSPORT_INSTANCE* transport_state = NULL; - bool cleanup_required = false; size_t deviceIdLength; // Codes_SRS_IOTHUBTRANSPORTAMQP_09_005: [If parameter config (or its fields) is NULL then IoTHubTransportAMQP_Create shall fail and return NULL.] @@ -1204,10 +1320,6 @@ { LogError("Invalid configuration (NULL deviceId detected)"); } - else if (config->upperConfig->deviceKey == NULL && config->upperConfig->deviceSasToken == NULL) - { - LogError("Invalid configuration (NULL deviceKey/deviceSasToken detected)"); - } else if (config->upperConfig->deviceKey != NULL && config->upperConfig->deviceSasToken != NULL) { LogError("Invalid configuration (Both deviceKey and deviceSasToken are defined)"); @@ -1260,10 +1372,10 @@ } else { + bool cleanup_required = false; + transport_state->iotHubHostFqdn = NULL; transport_state->iotHubPort = DEFAULT_IOTHUB_AMQP_PORT; - transport_state->deviceKey = NULL; - transport_state->deviceSasToken = NULL; transport_state->devicesPath = NULL; transport_state->messageReceiveAddress = NULL; transport_state->sasTokenKeyName = NULL; @@ -1293,6 +1405,8 @@ transport_state->waitingToSend = config->waitingToSend; DList_InitializeListHead(&transport_state->inProgress); + transport_state->credential.credentialType = CREDENTIAL_NOT_BUILD; + // Codes_SRS_IOTHUBTRANSPORTAMQP_09_010: [IoTHubTransportAMQP_Create shall create an immutable string, referred to as iotHubHostFqdn, from the following pieces: config->iotHubName + "." + config->iotHubSuffix.] if ((transport_state->iotHubHostFqdn = concat3Params(config->upperConfig->iotHubName, ".", config->upperConfig->iotHubSuffix)) == NULL) { @@ -1327,58 +1441,92 @@ LogError("Failed to allocate transport_state->sasTokenKeyName."); cleanup_required = true; } - else if (config->upperConfig->deviceSasToken != NULL) - { - if ((transport_state->deviceSasToken = STRING_construct(config->upperConfig->deviceSasToken)) == NULL) - { - // Codes_SRS_IOTHUBTRANSPORTAMQP_09_019: [If IoTHubTransportAMQP_Create fails to copy config->deviceKey, the function shall fail and return NULL.] - LogError("Failed to allocate transport_state->deviceSasToken."); - cleanup_required = true; - } - } - // Codes_SRS_IOTHUBTRANSPORTAMQP_09_018: [IoTHubTransportAMQP_Create shall store a copy of config->deviceKey (passed by upper layer) into the transports own deviceKey field.] - else if ((config->upperConfig->deviceKey != NULL) && ((transport_state->deviceKey = STRING_new()) == NULL || - STRING_copy(transport_state->deviceKey, config->upperConfig->deviceKey) != 0)) + else { - // Codes_SRS_IOTHUBTRANSPORTAMQP_09_019: [If IoTHubTransportAMQP_Create fails to copy config->deviceKey, the function shall fail and return NULL.] - LogError("Failed to allocate transport_state->deviceKey."); - cleanup_required = true; + + if (config->upperConfig->deviceSasToken != NULL) + { + if (config->upperConfig->deviceKey != NULL) + { + LogError("invalid configuration, both deviceSasToken AND deviceKey specified"); + cleanup_required = true; + } + else + { + /*only SAS token specified*/ + transport_state->credential.credential.deviceSasToken = STRING_construct(config->upperConfig->deviceSasToken); + if (transport_state->credential.credential.deviceSasToken == NULL) + { + LogError("unable to STRING_construct for deviceSasToken"); + cleanup_required = true; + } + else + { + transport_state->credential.credentialType = DEVICE_SAS_TOKEN; + } + } + } + else + { + /*when deviceSasToken == NULL*/ + if (config->upperConfig->deviceKey != NULL) + { + /*it is device key*/ + + transport_state->credential.credential.deviceKey = STRING_construct(config->upperConfig->deviceKey); + if (transport_state->credential.credential.deviceKey == NULL) + { + LogError("unable to STRING_construct for a deviceKey"); + cleanup_required = true; + } + else + { + transport_state->credential.credentialType = DEVICE_KEY; + } + } + else + { + /*Codes_SRS_IOTHUBTRANSPORTAMQP_02_003: [ IoTHubTransportAMQP_Register shall assume a x509 authentication mechanism when both deviceKey and deviceSasToken are NULL. ]*/ + /*when both SAS token AND devicekey are NULL*/ + transport_state->credential.credentialType = X509; + transport_state->credential.credential.x509credential.x509certificate = NULL; + transport_state->credential.credential.x509credential.x509privatekey = NULL; + } + } + + if(transport_state->credential.credentialType != CREDENTIAL_NOT_BUILD ) + { + // Codes_SRS_IOTHUBTRANSPORTAMQP_09_020: [IoTHubTransportAMQP_Create shall set parameter transport_state->sas_token_lifetime with the default value of 3600000 (milliseconds).] + transport_state->sas_token_lifetime = DEFAULT_SAS_TOKEN_LIFETIME_MS; + + // Codes_SRS_IOTHUBTRANSPORTAMQP_09_128: [IoTHubTransportAMQP_Create shall set parameter transport_state->sas_token_refresh_time with the default value of sas_token_lifetime/2 (milliseconds).] + transport_state->sas_token_refresh_time = transport_state->sas_token_lifetime / 2; + + // Codes_SRS_IOTHUBTRANSPORTAMQP_09_129 : [IoTHubTransportAMQP_Create shall set parameter transport_state->cbs_request_timeout with the default value of 30000 (milliseconds).] + transport_state->cbs_request_timeout = DEFAULT_CBS_REQUEST_TIMEOUT_MS; + } } - else + + if (cleanup_required) { - // Codes_SRS_IOTHUBTRANSPORTAMQP_09_020: [IoTHubTransportAMQP_Create shall set parameter transport_state->sas_token_lifetime with the default value of 3600000 (milliseconds).] - transport_state->sas_token_lifetime = DEFAULT_SAS_TOKEN_LIFETIME_MS; + credential_destroy(transport_state); + if (transport_state->sasTokenKeyName != NULL) + STRING_delete(transport_state->sasTokenKeyName); + if (transport_state->targetAddress != NULL) + STRING_delete(transport_state->targetAddress); + if (transport_state->messageReceiveAddress != NULL) + STRING_delete(transport_state->messageReceiveAddress); + if (transport_state->devicesPath != NULL) + STRING_delete(transport_state->devicesPath); + if (transport_state->iotHubHostFqdn != NULL) + STRING_delete(transport_state->iotHubHostFqdn); - // Codes_SRS_IOTHUBTRANSPORTAMQP_09_128: [IoTHubTransportAMQP_Create shall set parameter transport_state->sas_token_refresh_time with the default value of sas_token_lifetime/2 (milliseconds).] - transport_state->sas_token_refresh_time = transport_state->sas_token_lifetime / 2; - - // Codes_SRS_IOTHUBTRANSPORTAMQP_09_129 : [IoTHubTransportAMQP_Create shall set parameter transport_state->cbs_request_timeout with the default value of 30000 (milliseconds).] - transport_state->cbs_request_timeout = DEFAULT_CBS_REQUEST_TIMEOUT_MS; + free(transport_state); + transport_state = NULL; } } } - if (cleanup_required) - { - if (transport_state->deviceSasToken != NULL) - STRING_delete(transport_state->deviceSasToken); - if (transport_state->deviceKey != NULL) - STRING_delete(transport_state->deviceKey); - if (transport_state->sasTokenKeyName != NULL) - STRING_delete(transport_state->sasTokenKeyName); - if (transport_state->targetAddress != NULL) - STRING_delete(transport_state->targetAddress); - if (transport_state->messageReceiveAddress != NULL) - STRING_delete(transport_state->messageReceiveAddress); - if (transport_state->devicesPath != NULL) - STRING_delete(transport_state->devicesPath); - if (transport_state->iotHubHostFqdn != NULL) - STRING_delete(transport_state->iotHubHostFqdn); - - free(transport_state); - transport_state = NULL; - } - // Codes_SRS_IOTHUBTRANSPORTAMQP_09_023: [If IoTHubTransportAMQP_Create succeeds it shall return a non-NULL pointer to the structure that represents the transport.] return transport_state; } @@ -1408,7 +1556,7 @@ STRING_delete(transport_state->targetAddress); STRING_delete(transport_state->messageReceiveAddress); STRING_delete(transport_state->sasTokenKeyName); - STRING_delete(transport_state->deviceKey); + credential_destroy(transport_state); STRING_delete(transport_state->devicesPath); STRING_delete(transport_state->iotHubHostFqdn); @@ -1623,7 +1771,7 @@ } else if (strcmp("logtrace", option) == 0) { - transport_state->is_trace_on = (bool*)value; + transport_state->is_trace_on = *((bool*)value); if (transport_state->connection != NULL) { connection_set_trace(transport_state->connection, transport_state->is_trace_on); @@ -1641,7 +1789,7 @@ } else { - /* Codes_SRS_IOTHUBTRANSPORTUAMQP_03_001: [If xio_setoption fails, IoTHubTransportAMQP_SetOption shall return IOTHUB_CLIENT_ERROR.] */ + /* Codes_SRS_IOTHUBTRANSPORTAMQP_03_001: [If xio_setoption fails, IoTHubTransportAMQP_SetOption shall return IOTHUB_CLIENT_ERROR.] */ if (xio_setoption(transport_state->tls_io, option, value) == 0) { result = IOTHUB_CLIENT_OK; @@ -1661,70 +1809,74 @@ static IOTHUB_DEVICE_HANDLE IoTHubTransportAMQP_Register(TRANSPORT_LL_HANDLE handle, const IOTHUB_DEVICE_CONFIG* device, IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, PDLIST_ENTRY waitingToSend) { IOTHUB_DEVICE_HANDLE result; - // Codes_SRS_IOTHUBTRANSPORTUAMQP_17_001: [IoTHubTransportAMQP_Register shall return NULL if device, or waitingToSend are NULL.] - // Codes_SRS_IOTHUBTRANSPORTUAMQP_17_005: [IoTHubTransportAMQP_Register shall return NULL if the TRANSPORT_LL_HANDLE is NULL.] + // Codes_SRS_IOTHUBTRANSPORTAMQP_17_001: [IoTHubTransportAMQP_Register shall return NULL if device, or waitingToSend are NULL.] + // Codes_SRS_IOTHUBTRANSPORTAMQP_17_005: [IoTHubTransportAMQP_Register shall return NULL if the TRANSPORT_LL_HANDLE is NULL.] if ((handle == NULL) || (device == NULL) || (waitingToSend == NULL)) { + LogError("invalid parameter TRANSPORT_LL_HANDLE handle=%p, const IOTHUB_DEVICE_CONFIG* device=%p, IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle=%p, PDLIST_ENTRY waitingToSend=%p", + handle, device, iotHubClientHandle, waitingToSend); result = NULL; } else { AMQP_TRANSPORT_INSTANCE* transport_state = (AMQP_TRANSPORT_INSTANCE*)handle; - // Codes_SRS_IOTHUBTRANSPORTUAMQP_03_002: [IoTHubTransportAMQP_Register shall return NULL if deviceId, or both deviceKey and deviceSasToken are NULL.**] - if ((device->deviceId == NULL) || (device->deviceSasToken == NULL && device->deviceKey == NULL)) + // Codes_SRS_IOTHUBTRANSPORTAMQP_03_002: [IoTHubTransportAMQP_Register shall return NULL if deviceId is NULL.**] + if (device->deviceId == NULL) { + LogError("invalid parameter device->deviceId was NULL"); result = NULL; } - // Codes_SRS_IOTHUBTRANSPORTUAMQP_03_003: [IoTHubTransportAMQP_Register shall return NULL if both deviceKey and deviceSasToken are not NULL.] + // Codes_SRS_IOTHUBTRANSPORTAMQP_03_003: [IoTHubTransportAMQP_Register shall return NULL if both deviceKey and deviceSasToken are not NULL.] else if ( (device->deviceSasToken != NULL) && (device->deviceKey != NULL) ) { + LogError("invalid parameter both device->deviceSasToken and device->deviceKey were NULL"); result = NULL; } else { STRING_HANDLE devicesPath = concat3Params(STRING_c_str(transport_state->iotHubHostFqdn), "/devices/", device->deviceId); - if (devicesPath == NULL) - { + if (devicesPath == NULL) + { LogError("Could not create devicesPath"); - result = NULL; - } - else - { - // Codes_SRS_IOTHUBTRANSPORTUAMQP_17_002: [IoTHubTransportAMQP_Register shall return NULL if deviceId or deviceKey do not match the deviceId and deviceKey passed in during IoTHubTransportAMQP_Create.] - if (strcmp(STRING_c_str(transport_state->devicesPath), STRING_c_str(devicesPath)) != 0) - { - LogError("Attemping to add new device to AMQP transport, not allowed."); - result = NULL; - } - else if ((transport_state->deviceSasToken == NULL) && strcmp(STRING_c_str(transport_state->deviceKey), device->deviceKey) != 0) - { - LogError("Attemping to add new device to AMQP transport, not allowed."); result = NULL; } else { - if (transport_state->isRegistered == true) + // Codes_SRS_IOTHUBTRANSPORTAMQP_17_002: [IoTHubTransportAMQP_Register shall return NULL if deviceId or deviceKey do not match the deviceId and deviceKey passed in during IoTHubTransportAMQP_Create.] + if (strcmp(STRING_c_str(transport_state->devicesPath), STRING_c_str(devicesPath)) != 0) { - LogError("Transport already has device registered by id: [%s]", device->deviceId); + LogError("Attemping to add new device to AMQP transport, not allowed."); + result = NULL; + } + else if ((transport_state->credential.credentialType == DEVICE_KEY) && strcmp(STRING_c_str(transport_state->credential.credential.deviceKey), device->deviceKey) != 0) + { + LogError("Attemping to add new device to AMQP transport, not allowed."); result = NULL; } else { - transport_state->isRegistered = true; - // Codes_SRS_IOTHUBTRANSPORTUAMQP_17_003: [IoTHubTransportAMQP_Register shall return the TRANSPORT_LL_HANDLE as the IOTHUB_DEVICE_HANDLE.] - result = (IOTHUB_DEVICE_HANDLE)handle; + if (transport_state->isRegistered == true) + { + LogError("Transport already has device registered by id: [%s]", device->deviceId); + result = NULL; + } + else + { + transport_state->isRegistered = true; + // Codes_SRS_IOTHUBTRANSPORTAMQP_17_003: [IoTHubTransportAMQP_Register shall return the TRANSPORT_LL_HANDLE as the IOTHUB_DEVICE_HANDLE.] + result = (IOTHUB_DEVICE_HANDLE)handle; + } } + STRING_delete(devicesPath); } - STRING_delete(devicesPath); } } - } return result; } -// Codes_SRS_IOTHUBTRANSPORTUAMQP_17_004: [IoTHubTransportAMQP_Unregister shall return.] +// Codes_SRS_IOTHUBTRANSPORTAMQP_17_004: [IoTHubTransportAMQP_Unregister shall return.] static void IoTHubTransportAMQP_Unregister(IOTHUB_DEVICE_HANDLE deviceHandle) { if (deviceHandle != NULL)