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:
- 22:8b70cf813f25
- Parent:
- 21:32a1746384ba
- Child:
- 23:2c6779675a01
--- a/iothubtransportamqp.c Fri Aug 12 10:03:28 2016 -0700 +++ b/iothubtransportamqp.c Fri Aug 26 12:58:26 2016 -0700 @@ -34,6 +34,8 @@ #include "iothubtransportamqp.h" #include "iothub_client_version.h" +#define INDEFINITE_TIME ((time_t)(-1)) + #define RESULT_OK 0 #define RESULT_FAILURE 1 #define RESULT_TIMEOUT 2 @@ -207,9 +209,24 @@ return result; } -static size_t getSecondsSinceEpoch(void) +static int getSecondsSinceEpoch(size_t* seconds) { - return (size_t)(difftime(get_time(NULL), (time_t)0)); + int result; + time_t current_time; + + if ((current_time = get_time(NULL)) == INDEFINITE_TIME) + { + LogError("Failed getting the current local time (get_time() failed)"); + result = __LINE__; + } + else + { + *seconds = (size_t)get_difftime(current_time, (time_t)0); + + result = RESULT_OK; + } + + return result; } static void trackEventInProgress(IOTHUB_MESSAGE_LIST* message, AMQP_TRANSPORT_INSTANCE* transport_state) @@ -661,6 +678,11 @@ static void on_put_token_complete(void* context, CBS_OPERATION_RESULT operation_result, unsigned int status_code, const char* status_description) { +#ifdef NO_LOGGING + UNUSED(status_code); + UNUSED(status_description); +#endif + AMQP_TRANSPORT_INSTANCE* transportState = (AMQP_TRANSPORT_INSTANCE*)context; if (operation_result == CBS_OPERATION_RESULT_OK) @@ -935,9 +957,13 @@ result = RESULT_FAILURE; LogError("Failed to open the connection with CBS."); } + else if (getSecondsSinceEpoch(&transport_state->connection_establish_time) != RESULT_OK) + { + LogError("Failed setting the connection establish time."); + result = RESULT_FAILURE; + } else { - transport_state->connection_establish_time = getSecondsSinceEpoch(); transport_state->cbs.cbs_state = CBS_STATE_IDLE; connection_set_trace(transport_state->connection, transport_state->is_trace_on); (void)xio_setoption(transport_state->cbs.sasl_io, OPTION_LOG_TRACE, &transport_state->is_trace_on); @@ -980,10 +1006,17 @@ LogError("Failed to set the AMQP outgoing window size."); } - transport_state->connection_establish_time = getSecondsSinceEpoch(); + if (getSecondsSinceEpoch(&transport_state->connection_establish_time) != RESULT_OK) + { + LogError("Failed setting the connection establish time."); + result = RESULT_FAILURE; + } + else + { connection_set_trace(transport_state->connection, transport_state->is_trace_on); (void)xio_setoption(transport_state->tls_io, OPTION_LOG_TRACE, &transport_state->is_trace_on); result = RESULT_OK; + } } } break; @@ -1025,79 +1058,97 @@ static int startAuthentication(AMQP_TRANSPORT_INSTANCE* transport_state) { int result; - - size_t sas_token_create_time = getSecondsSinceEpoch(); // I.e.: NOW, in seconds since epoch. + size_t currentTimeInSeconds; - // Codes_SRS_IOTHUBTRANSPORTAMQP_09_083: [Each new SAS token created by the transport shall be valid for up to 'sas_token_lifetime' milliseconds from the time of creation] - size_t new_expiry_time = sas_token_create_time + (transport_state->cbs.sas_token_lifetime / 1000); + if (getSecondsSinceEpoch(¤tTimeInSeconds) != RESULT_OK) + { + LogError("Failed getting current time to compute the SAS token creation time."); + result = __LINE__; + } + else + { + // Codes_SRS_IOTHUBTRANSPORTAMQP_09_083: [SAS tokens expiration time shall be calculated using the number of seconds since Epoch UTC (Jan 1st 1970 00h00m00s000 GMT) to now (GMT), plus the 'sas_token_lifetime'.] + size_t new_expiry_time = currentTimeInSeconds + (transport_state->cbs.sas_token_lifetime / 1000); - STRING_HANDLE newSASToken; + STRING_HANDLE newSASToken; - switch (transport_state->credential.credentialType) - { - 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->cbs.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; - } + switch (transport_state->credential.credentialType) + { + 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->cbs.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, currentTimeInSeconds) != 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; + } + 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, currentTimeInSeconds) != 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; - } - } + // 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; + } + } + } return result; } static int verifyAuthenticationTimeout(AMQP_TRANSPORT_INSTANCE* transport_state) { - return ((getSecondsSinceEpoch() - transport_state->cbs.current_sas_token_create_time) * 1000 >= transport_state->cbs.cbs_request_timeout) ? RESULT_TIMEOUT : RESULT_OK; + int result; + size_t currentTimeInSeconds; + if (getSecondsSinceEpoch(¤tTimeInSeconds) != RESULT_OK) + { + LogError("Failed getting the current time to verify if the SAS token needs to be refreshed."); + result = RESULT_TIMEOUT; // Fail safe. + } + else + { + result = ((currentTimeInSeconds - transport_state->cbs.current_sas_token_create_time) * 1000 >= transport_state->cbs.cbs_request_timeout) ? RESULT_TIMEOUT : RESULT_OK; + } + return result; } static void attachDeviceClientTypeToLink(LINK_HANDLE link) @@ -1482,14 +1533,23 @@ static bool isSasTokenRefreshRequired(AMQP_TRANSPORT_INSTANCE* transport_state) { + bool result; + size_t currentTimeInSeconds; if (transport_state->credential.credentialType == DEVICE_SAS_TOKEN) { - return false; + result = false; } + else if (getSecondsSinceEpoch(¤tTimeInSeconds) != RESULT_OK) + { + LogError("Failed getting the current time to verify if the SAS token needs to be refreshed."); + result = true; // Fail safe. + } else { - return ((getSecondsSinceEpoch() - transport_state->cbs.current_sas_token_create_time) >= (transport_state->cbs.sas_token_refresh_time / 1000)) ? true : false; + result = ((currentTimeInSeconds - transport_state->cbs.current_sas_token_create_time) >= (transport_state->cbs.sas_token_refresh_time / 1000)) ? true : false; } + + return result; } static void prepareForConnectionRetry(AMQP_TRANSPORT_INSTANCE* transport_state) @@ -2130,6 +2190,10 @@ static IOTHUB_DEVICE_HANDLE IoTHubTransportAMQP_Register(TRANSPORT_LL_HANDLE handle, const IOTHUB_DEVICE_CONFIG* device, IOTHUB_CLIENT_LL_HANDLE iotHubClientHandle, PDLIST_ENTRY waitingToSend) { +#ifdef NO_LOGGING + UNUSED(iotHubClientHandle); +#endif + IOTHUB_DEVICE_HANDLE result; // 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.]